From 95fc665771abeb335b29e6d59fe74d69cf9c446f Mon Sep 17 00:00:00 2001
From: hanbaoshan <hanbaoshan@aiotlink.com>
Date: 星期四, 23 七月 2020 08:49:20 +0800
Subject: [PATCH] 首页更新,加入算法管理

---
 public/images/app-mid/GB-config.png                           |    0 
 src/components/subComponents/FileUpload/list.vue              |   42 
 public/images/app-mid/device.png                              |    0 
 public/images/app-mid/360.png                                 |    0 
 src/components/subComponents/imgDown.vue                      |   93 
 src/pages/desktop/index/components/ToolsEntry.vue             |   95 
 public/images/app-mid/data-push.png                           |    0 
 src/components/subComponents/IPInput.vue                      |  231 +
 src/pages/desktop/index/components/Dock.vue                   |   14 
 public/images/header-icon/SmartAI.png                         |    0 
 src/assets/img/desktop/desktop.png                            |    0 
 src/components/subComponents/CardItem.vue                     |  881 +++++++
 src/pages/desktop/index/components/Tools.vue                  |  124 
 public/images/app-mid/monitor.png                             |    0 
 public/images/app-mid/vindicate.png                           |    0 
 src/components/subComponents/FileUpload/unsupport.vue         |   30 
 src/components/subComponents/VueCron.vue                      |  194 +
 src/components/subComponents/FileUpload/file.vue              |  452 +++
 src/components/subComponents/FileUpload/btn.vue               |   56 
 src/components/subComponents/RuleEditor.vue                   |  811 ++++++
 src/components/subComponents/MultiRangeSlider.vue             |  761 ++++++
 public/images/header-icon/notice.png                          |    0 
 src/components/subComponents/LocalVedioList.vue               |  129 +
 public/images/app-mid/library.png                             |    0 
 public/images/header-icon/help.png                            |    0 
 public/images/app-mid/scene-config.png                        |    0 
 public/images/app-mid/poll.png                                |    0 
 public/images/app-mid/algorithm-manage.png                    |    0 
 public/images/app-mid/search.png                              |    0 
 public/images/app-mid/DVR-access.png                          |    0 
 src/components/subComponents/BoardCard.vue                    |  135 +
 src/components/subComponents/ParticleNetwork.vue              |  351 ++
 src/pages/desktop/index/mock/userData.json                    |    7 
 public/images/app-mid/hashrate-manage.png                     |    0 
 src/components/subComponents/ModelCard.vue                    |  583 ++++
 public/images/app-mid/log-manage.png                          |    0 
 public/images/app-mid/settings.png                            |    0 
 src/components/subComponents/FileUpload/common/mixins.js      |   14 
 src/components/subComponents/FileUpload/drop.vue              |   64 
 public/images/header-icon/search.png                          |    0 
 src/components/subComponents/FileUpload/index.vue             |  230 +
 src/components/subComponents/eChartsBar.vue                   |  174 +
 public/images/logo.png                                        |    0 
 src/components/subComponents/FileUpload/common/utils.js       |   28 
 src/pages/index/app.vue                                       |    5 
 src/components/subComponents/chartLiquid.vue                  |  141 +
 src/components/subComponents/FileUpload/uploader.vue          |  155 +
 public/images/app-mid/camera-access.png                       |    0 
 src/pages/desktop/index/App.vue                               |   14 
 public/images/header-icon/system.png                          |    0 
 src/pages/algorithmManage/index/main.ts                       |   11 
 src/components/subComponents/FileUpload/common/file-events.js |    3 
 src/pages/algorithmManage/index/api.ts                        |  145 +
 src/pages/algorithmManage/index/App.vue                       |  861 +++++++
 src/components/subComponents/DataStackCard.vue                |  158 +
 package.json                                                  |    2 
 src/components/subComponents/FileUpload/files.vue             |   42 
 src/components/subComponents/Card.vue                         |  163 +
 public/images/app-mid/algorithm-store.png                     |    0 
 src/components/subComponents/LocalVedioCard.vue               |  139 +
 public/images/header-icon/user.png                            |    0 
 public/images/app-mid/datastack-config.png                    |    0 
 62 files changed, 7,285 insertions(+), 53 deletions(-)

diff --git a/package.json b/package.json
index 9dc2faf..e11d6ad 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,8 @@
     "axios": "^0.19.2",
     "element-ui": "^2.4.6",
     "qs": "^6.9.4",
+    "simple-uploader.js": "^0.5.4",
+    "spark-md5": "^3.0.1",
     "vue": "^2.6.11",
     "vue-qrcode-component": "^2.1.1",
     "vuex": "^3.5.1"
diff --git a/public/images/app-mid/360.png b/public/images/app-mid/360.png
new file mode 100644
index 0000000..0bd5367
--- /dev/null
+++ b/public/images/app-mid/360.png
Binary files differ
diff --git a/public/images/app-mid/DVR-access.png b/public/images/app-mid/DVR-access.png
new file mode 100644
index 0000000..f99d3ac
--- /dev/null
+++ b/public/images/app-mid/DVR-access.png
Binary files differ
diff --git a/public/images/app-mid/GB-config.png b/public/images/app-mid/GB-config.png
new file mode 100644
index 0000000..c315518
--- /dev/null
+++ b/public/images/app-mid/GB-config.png
Binary files differ
diff --git a/public/images/app-mid/algorithm-manage.png b/public/images/app-mid/algorithm-manage.png
new file mode 100644
index 0000000..d71f14a
--- /dev/null
+++ b/public/images/app-mid/algorithm-manage.png
Binary files differ
diff --git a/public/images/app-mid/algorithm-store.png b/public/images/app-mid/algorithm-store.png
new file mode 100644
index 0000000..412f391
--- /dev/null
+++ b/public/images/app-mid/algorithm-store.png
Binary files differ
diff --git a/public/images/app-mid/camera-access.png b/public/images/app-mid/camera-access.png
new file mode 100644
index 0000000..35e41c7
--- /dev/null
+++ b/public/images/app-mid/camera-access.png
Binary files differ
diff --git a/public/images/app-mid/data-push.png b/public/images/app-mid/data-push.png
new file mode 100644
index 0000000..c4187c6
--- /dev/null
+++ b/public/images/app-mid/data-push.png
Binary files differ
diff --git a/public/images/app-mid/datastack-config.png b/public/images/app-mid/datastack-config.png
new file mode 100644
index 0000000..5d38c44
--- /dev/null
+++ b/public/images/app-mid/datastack-config.png
Binary files differ
diff --git a/public/images/app-mid/device.png b/public/images/app-mid/device.png
new file mode 100644
index 0000000..b0076d1
--- /dev/null
+++ b/public/images/app-mid/device.png
Binary files differ
diff --git a/public/images/app-mid/hashrate-manage.png b/public/images/app-mid/hashrate-manage.png
new file mode 100644
index 0000000..b755899
--- /dev/null
+++ b/public/images/app-mid/hashrate-manage.png
Binary files differ
diff --git a/public/images/app-mid/library.png b/public/images/app-mid/library.png
new file mode 100644
index 0000000..46681ff
--- /dev/null
+++ b/public/images/app-mid/library.png
Binary files differ
diff --git a/public/images/app-mid/log-manage.png b/public/images/app-mid/log-manage.png
new file mode 100644
index 0000000..4c90102
--- /dev/null
+++ b/public/images/app-mid/log-manage.png
Binary files differ
diff --git a/public/images/app-mid/monitor.png b/public/images/app-mid/monitor.png
new file mode 100644
index 0000000..5fa6242
--- /dev/null
+++ b/public/images/app-mid/monitor.png
Binary files differ
diff --git a/public/images/app-mid/poll.png b/public/images/app-mid/poll.png
new file mode 100644
index 0000000..8773201
--- /dev/null
+++ b/public/images/app-mid/poll.png
Binary files differ
diff --git a/public/images/app-mid/scene-config.png b/public/images/app-mid/scene-config.png
new file mode 100644
index 0000000..096c1b7
--- /dev/null
+++ b/public/images/app-mid/scene-config.png
Binary files differ
diff --git a/public/images/app-mid/search.png b/public/images/app-mid/search.png
new file mode 100644
index 0000000..e122fc9
--- /dev/null
+++ b/public/images/app-mid/search.png
Binary files differ
diff --git a/public/images/app-mid/settings.png b/public/images/app-mid/settings.png
new file mode 100644
index 0000000..02b36db
--- /dev/null
+++ b/public/images/app-mid/settings.png
Binary files differ
diff --git a/public/images/app-mid/vindicate.png b/public/images/app-mid/vindicate.png
new file mode 100644
index 0000000..038e685
--- /dev/null
+++ b/public/images/app-mid/vindicate.png
Binary files differ
diff --git a/public/images/header-icon/SmartAI.png b/public/images/header-icon/SmartAI.png
new file mode 100644
index 0000000..10b127b
--- /dev/null
+++ b/public/images/header-icon/SmartAI.png
Binary files differ
diff --git a/public/images/header-icon/help.png b/public/images/header-icon/help.png
new file mode 100644
index 0000000..e66a57f
--- /dev/null
+++ b/public/images/header-icon/help.png
Binary files differ
diff --git a/public/images/header-icon/notice.png b/public/images/header-icon/notice.png
new file mode 100644
index 0000000..ce93ca9
--- /dev/null
+++ b/public/images/header-icon/notice.png
Binary files differ
diff --git a/public/images/header-icon/search.png b/public/images/header-icon/search.png
new file mode 100644
index 0000000..b9ebcd8
--- /dev/null
+++ b/public/images/header-icon/search.png
Binary files differ
diff --git a/public/images/header-icon/system.png b/public/images/header-icon/system.png
new file mode 100644
index 0000000..4c37730
--- /dev/null
+++ b/public/images/header-icon/system.png
Binary files differ
diff --git a/public/images/header-icon/user.png b/public/images/header-icon/user.png
new file mode 100644
index 0000000..e97e46e
--- /dev/null
+++ b/public/images/header-icon/user.png
Binary files differ
diff --git a/public/images/logo.png b/public/images/logo.png
new file mode 100644
index 0000000..dabfdaa
--- /dev/null
+++ b/public/images/logo.png
Binary files differ
diff --git a/src/assets/img/desktop/desktop.png b/src/assets/img/desktop/desktop.png
new file mode 100644
index 0000000..7b9b347
--- /dev/null
+++ b/src/assets/img/desktop/desktop.png
Binary files differ
diff --git a/src/components/subComponents/BoardCard.vue b/src/components/subComponents/BoardCard.vue
new file mode 100644
index 0000000..ae1f688
--- /dev/null
+++ b/src/components/subComponents/BoardCard.vue
@@ -0,0 +1,135 @@
+<template>
+  <div class="board-card">
+    <div class="top-text">
+      <em>{{title}}</em>
+      <em style="color:#ff7733;font-size:13px">{{channelTotal}}</em>
+    </div>
+    <div class="bottom-icon">
+      <div style="height:45%;" class="flex-center">
+        <div class="right-bot-css">
+          <el-tooltip effect="dark" placement="top">
+            <div slot="content">鏈夎鍒�</div>
+            <span class="bottom-text">
+              <i class="el-icon-success" style="color:#149A46;" v-show="ValidCount.length"></i>
+              {{ValidCount}}
+            </span>
+          </el-tooltip>
+
+          <el-tooltip effect="dark" placement="top">
+            <div slot="content">鏃犺鍒�</div>
+            <span class="bottom-text">
+              <i class="el-icon-warning" style="color:orange;margin-left: 18px;" v-show="InValidCount.length"></i>
+              {{InValidCount}}
+            </span>
+          </el-tooltip>
+        </div>
+      </div>
+      <div style="width:100%;">
+        <el-divider></el-divider>
+      </div>
+      <div style="height:45%;" class="flex-center">
+        <div class="right-bot-css">
+          <el-tooltip effect="dark" placement="top">
+            <div slot="content">澶勭悊涓�</div>
+            <span class="bottom-text">
+              <i class="iconfont iconzhengzaichuli" style="color:#3D68E1;font-size:18px;" v-show="RunningCount.length"></i>
+              {{RunningCount}}
+            </span>
+          </el-tooltip>
+
+          <el-tooltip effect="dark" placement="top">
+            <div slot="content">鏈鐞�</div>
+            <span class="bottom-text">
+              <i class="iconfont iconchuli" title="鏈鐞�" style="margin-left:18px;font-size:18px;" v-show="NoDeal.length"></i>
+              {{NoDeal}}
+            </span>
+          </el-tooltip>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "BoardCard",
+  props: {
+    title: { type: String, default: "" },
+    total: { type: String, default: "" },
+    ValidCount: { type: String, default: "" },
+    InValidCount: { type: String, default: "" },
+    RunningCount: { type: String, default: "" },
+    channelTotal: { type: String, default: "" },
+    NoDeal: { type: String, default: "" },
+    width: { type: String, default: "126px"}
+  }
+}
+</script>
+<style lang="scss">
+.board-card {
+  height: 120px;
+  width: 100%;
+  display: inline-block;
+  margin: 10px;
+  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;
+  }
+  .bottom-icon {
+    width: 100%;
+    height: calc(100% - 30px);
+  }
+  .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;
+  }
+  hr {
+    background: rgb(226, 226, 226);
+    border: 0;
+    height: 1px;
+  }
+  i {
+    font-size: 20px;
+  }
+  .divider-css{
+    height: 100%;
+    margin: 0;
+  }
+  .el-divider--horizontal {
+    display: block;
+    height: 1px;
+    width: 100%;
+    margin: 3px 0;
+  }
+  .right-top-css{
+    margin: 0px auto;
+    position: relative;
+  }
+  .right-bot-css{
+    margin: 0px auto;
+    position: relative;
+  }
+  .item {
+    margin: 4px;
+  } 
+}
+</style>
\ No newline at end of file
diff --git a/src/components/subComponents/Card.vue b/src/components/subComponents/Card.vue
new file mode 100644
index 0000000..7749870
--- /dev/null
+++ b/src/components/subComponents/Card.vue
@@ -0,0 +1,163 @@
+<template>
+  <el-card
+    class="my-card"
+    shadow="never"
+    :style="`height:${outHeight};width:${outWidth};max-height:160px;min-height:135px`"
+    :body-style="`height:${height};width:${width};`"
+  >
+    <el-carousel
+      ref="carousel"
+      :autoplay="false"
+      indicator-position="none"
+      :arrow="data.list.length > 1 ? 'always' : 'never'"
+      @change="changeHandle"
+    >
+      <el-carousel-item v-for="(item, index) in data.list" :key="index">
+        <card-item
+          :data="item"
+          :showType="showType"
+          @detailsClick="detailsClick"
+          @addToBase="toAdd"
+        ></card-item>
+      </el-carousel-item>
+    </el-carousel>
+  </el-card>
+</template>
+
+<script>
+import CardItem from "./CardItem";
+export default {
+  components: {
+    CardItem
+  },
+  props: {
+    data: {
+      type: Object,
+      default: null
+    },
+    showType: {
+      type: String,
+      default: ""
+    },
+    height: {
+      type: String,
+      default: "100%"
+    },
+    width: {
+      type: String,
+      default: "100%"
+    },
+    outHeight: {
+      type: String,
+      default: "100%"
+    },
+    outWidth: {
+      type: String,
+      default: "100%"
+    }
+  },
+  watch: {
+
+  },
+  data() {
+    return {
+      items: [],
+      filled: false
+    }
+  },
+  watch: {
+    data(newVal) {
+      this.len = this.data.list.length;
+      if (this.len > 3) {
+        this.data.list = this.data.list.slice(0, 3)
+      }
+    }
+  },
+  methods: {
+    detailsClick(ev) {
+      this.$emit("detailsClick", ev);
+    },
+    toAdd(item) {
+      this.$emit("addToBase", item);
+    },
+    changeHandle(e) {
+      // 鐐瑰嚮鍒囨崲鏃�, 浼氳Е鍙戣浜嬩欢, 姝ゆ椂閲嶆柊濉厖鍏ㄩ儴鏁版嵁, 缁勪欢浼氶噸鏂版覆鏌�, DOM鏇存柊鍚庢牴鎹偣鍑荤殑鎸夐挳,鎵嬪姩鍒囨崲
+      // filled 鎺у埗鍙湪绗竴娆$偣鍑绘椂瑙﹀彂.鐒跺悗涓嶅啀骞查璺戦┈鐏垏鎹�
+      if (this.len > 3 && !this.filled) {
+        this.items = this.data.list
+        this.filled = true
+
+        this.$nextTick(() => {
+          if (e == 1) { // 鐐瑰嚮浜嗕笅涓�寮�
+            this.$refs.carousel.next()
+          }
+          if (e == 2) { // 鐐瑰嚮浜嗕笂涓�寮�
+            this.$refs.carousel.prev()
+          }
+        })
+      }
+    }
+  }
+};
+</script>
+<style lang="scss">
+.my-active-card {
+  border: 2px solid #ff7733 !important;
+  // background: rgba(145,197,255, 0.6) !important;
+}
+.my-card {
+  box-sizing: border-box;
+  padding: 12px 10px;
+  cursor: default;
+  .el-carousel__arrow {
+    top: 90%;
+  }
+  .el-carousel__arrow {
+    height: 20px;
+    width: 20px;
+  }
+  .el-carousel__arrow:hover {
+    background-color: rgba(102, 102, 102);
+  }
+  .el-card__body {
+    padding: 0px !important;
+  }
+  .el-card:hover {
+    box-sizing: border-box;
+  }
+  // .el-carousel__arrow {
+  //   top: inherit;
+  //   bottom: 0px;
+  // }
+  .el-carousel {
+    height: 100% !important;
+    width: 100%;
+    .el-carousel__container {
+      height: 100% !important;
+      width: 100%;
+    }
+  }
+}
+.my-card:hover {
+  -webkit-box-shadow: 0px 0px 5px 1px rgba(0, 0, 0, 0.3);
+  box-shadow: 0px 0px 5px 1px rgba(0, 0, 0, 0.3);
+}
+</style>
+<style lang = "scss" scoped>
+.el-carousel__container {
+  height: 100% !important;
+  .el-carousel__arrow {
+    top: 70% !important;
+  }
+  .el-carousel__arrow {
+    height: 20px;
+    width: 20px;
+  }
+  .el-carousel__arrow--right {
+    right: 10px !important;
+  }
+  .el-carousel__arrow--left {
+    left: 10px !important;
+  }
+}
+</style>
diff --git a/src/components/subComponents/CardItem.vue b/src/components/subComponents/CardItem.vue
new file mode 100644
index 0000000..e6abb97
--- /dev/null
+++ b/src/components/subComponents/CardItem.vue
@@ -0,0 +1,881 @@
+<template>
+  <div class="box-card" ref="cardItem">
+    <!-- 宸︿晶鍥剧墖鍖哄煙 -->
+    <!-- 姣斿妯″紡 -->
+    <div class="s-card-left-isCompare" v-if="showType === 'compare' ">
+      <div class="card-img-box">
+        <div class="card-img-box-compear">
+          <div class="card-img-box-compear-left" ref="firstImg">
+            <img
+              :src="'/httpImage/'+data.targetInfo[0].picSmUrl+'?width=160'"
+              :id="'/compear/'+data.targetInfo[0].picSmUrl"
+              class="cursor-pointer"
+              @click="detailsClick($event)"
+            />
+          </div>
+          <el-carousel
+            @change="changeInitialIndex"
+            :initial-index="initialIndex"
+            :autoplay="false"
+            indicator-position="none"
+            :arrow="data.baseInfo.length > 1 ? 'always' : 'never'"
+          >
+            <el-carousel-item v-for="(item, index) in data.baseInfo" :key="index">
+              <img
+                :src="'/httpImage/'+item.targetPicUrl+'?width=160'"
+                class="cursor-pointer"
+                @click="detailsClick($event)"
+              />
+            </el-carousel-item>
+          </el-carousel>
+        </div>
+        <div
+          class="s-card-left-isCompare-div compareScore111"
+          style
+          :style="{
+            bottom: getBottom(),
+            background: getUrl(data.baseInfo[initialIndex].bwType)
+          }"
+        >
+          <b>{{ `${data.baseInfo[initialIndex].compareScore}%` }}</b>
+        </div>
+      </div>
+    </div>
+    <!-- 鏅�氭ā寮� -->
+    <div v-else class="s-card-left">
+      <!-- 姝e父鐨勬姄鎷嶅簱鍥剧墖 data.targetInfo == null 涓烘棤浜哄�煎畧 data.id == '' 涓哄姣斿嚭鏉ョ殑搴曞簱鍥剧墖-->
+      <div class="s-card-left-box" v-if="data.id !== ''">
+        <el-carousel
+          trigger="click"
+          height="100%"
+          indicator-position="none"
+          v-if="data.picMaxUrl.length > 1"
+          :autoplay="false"
+          @change="changeCarousel"
+        >
+          <el-carousel-item v-for="(item, index) in data.picMaxUrl" :key="index + 'img'">
+            <img
+              :src="'/httpImage/'+item+'?width=160'"
+              class="cursor-pointer"
+              @click="detailsClick($event)"
+            />
+          </el-carousel-item>
+        </el-carousel>
+        <img
+          v-else-if="data.targetInfo == null || data.targetInfo[0].picSmUrl == ''"
+          :src="'/httpImage/'+data.picMaxUrl[0]+'?width=160'"
+          class="cursor-pointer"
+          @click="detailsClick($event)"
+        />
+        <img
+          v-else
+          :src="'/httpImage/'+data.targetInfo[0].picSmUrl+'?width=160'"
+          class="cursor-pointer"
+          @click="detailsClick($event)"
+        />
+      </div>
+      <div class="s-card-left-box" v-else>
+        <img :src="'/httpImage/'+data.baseInfo[0].targetPicUrl+'?width=160'" class="cursor-pointer" />
+      </div>
+    </div>
+    <!-- 鍙充晶鏂囧瓧鍖哄煙 -->
+    <!-- 澶氬紶搴曞浘鍒囨崲 -->
+    <div class="s-card-right-isCompare" v-if="showType == 'compare'">
+      <div
+        class="person"
+        :style="overflowState ? 'overflow: hidden' : 'overflow: auto'"
+        @mouseenter="cardMouseenter($event)"
+        @mouseleave="cardMouseleave($event)"
+      >
+        <!-- <p :title="data.baseInfo[0].compareScore" class="score">
+          <span v-if="data.id">{{ data.compareScore }}%</span>
+          <span v-else>{{ data.baseInfo[0].compareScore }}%</span>
+        </p>-->
+        <p>
+          <span class="fontStyle color222">{{ data.picDate }}</span>
+        </p>
+        <p style="margin-bottom: 8px;">
+          <span class="fontStyle color222">{{ data.cameraAddr }}</span>
+        </p>
+        <el-tooltip placement="right" popper-class="atooltip">
+          <div slot="content">
+            <p v-for="(item,index) in data.alarmRules" :key="index+'rule'">
+              <span>{{data.taskName}}</span>&nbsp;
+              <span v-if="item.alarmLevel !== '鎾ら槻'">&nbsp;{{item.alarmLevel}}</span>&nbsp;
+              <span v-if="item.linkInfo == '鑱斿姩浠诲姟'">&nbsp;鑱斿姩浠诲姟</span>
+            </p>
+          </div>
+          <el-button
+            style="line-height:17px;border:none;padding:0;overflow:hidden;text-overflow:ellipsis;cursor:default;width:100%;text-align:left"
+          >
+            <span
+              v-for="(item,index) in data.alarmRules"
+              :key="index+'rule1'"
+              style="text-overflow:ellipsis;max-width:100px"
+            >
+              <span class="fontStyle color666">{{data.taskName}}</span>&nbsp;
+              <span
+                class="fontStyle color666"
+                v-if="item.alarmLevel !== '鎾ら槻'"
+              >&nbsp;{{item.alarmLevel}}</span>&nbsp;
+              <span class="fontStyle color666" v-if="item.linkInfo == '鑱斿姩浠诲姟'">&nbsp;鑱斿姩浠诲姟</span>
+              <span v-if="index < data.alarmRules.length-1">/&nbsp;</span>
+            </span>
+          </el-button>
+        </el-tooltip>
+        <el-tooltip placement="right" popper-class="atooltip">
+          <div slot="content">
+            <p>
+              <span
+                class="fontStyle"
+                v-if="data.baseInfo[initialIndex].tableName"
+              >{{ data.baseInfo[initialIndex].tableName }}</span>&nbsp;
+              <span
+                class="fontStyle"
+                v-if="data.baseInfo[initialIndex].targetName"
+              >/&nbsp;{{ data.baseInfo[initialIndex].targetName }}</span>&nbsp;
+              <span
+                class="fontStyle"
+                v-if="data.baseInfo[initialIndex].labels"
+              >/&nbsp;{{ data.baseInfo[initialIndex].labels.split("/")[1] }}</span>&nbsp;
+              <span
+                class="fontStyle"
+                v-if="data.baseInfo[initialIndex].monitorLevel"
+              >/&nbsp;{{ data.baseInfo[initialIndex].monitorLevel }}</span>
+            </p>
+          </div>
+          <el-button
+            style="line-height:17px;border:none;padding:0;margin:0;overflow:hidden;text-overflow:ellipsis;cursor:default;width:100%;text-align:left"
+          >
+            <span
+              :style="data.baseInfo[initialIndex].bwType === '1'
+              ? 'color: red;font-size:12px;line-height:20px'
+              : 'font-size:12px;line-height:20px'"
+            >
+              <span
+                class="fontStyle"
+                v-if="data.baseInfo[initialIndex].tableName"
+              >{{ data.baseInfo[initialIndex].tableName }}</span>&nbsp;
+              <span
+                class="fontStyle"
+                v-if="data.baseInfo[initialIndex].targetName"
+              >/&nbsp;{{ data.baseInfo[initialIndex].targetName }}</span>&nbsp;
+              <span
+                class="fontStyle"
+                v-if="data.baseInfo[initialIndex].labels"
+              >/&nbsp;{{ data.baseInfo[initialIndex].labels.split("/")[1] }}</span>&nbsp;
+              <span
+                class="fontStyle"
+                v-if="data.baseInfo[initialIndex].monitorLevel"
+              >/&nbsp;{{ data.baseInfo[initialIndex].monitorLevel }}</span>
+            </span>
+          </el-button>
+        </el-tooltip>
+      </div>
+      <div class="card-icon-box">
+        <el-tooltip content="璇︽儏" placement="top" popper-class="atooltip">
+          <i class="iconfont iconcaidan" @click="detailsClick($event)"></i>
+        </el-tooltip>
+        <el-tooltip content="鏌ユ壘姝や汉" placement="top" popper-class="atooltip">
+          <i class="iconfont iconsousuoren" @click="tosearch(data)"></i>
+        </el-tooltip>
+        <el-tooltip content="鍔犲叆搴曞簱" placement="top" popper-class="atooltip">
+          <i class="iconfont icontianjiaren" @click="toAdd(data)"></i>
+        </el-tooltip>
+        <el-tooltip content="鏀惰棌" placement="top" popper-class="atooltip">
+          <i class="iconfont iconshoucang2"></i>
+        </el-tooltip>
+      </div>
+    </div>
+    <!-- 搴曞簱浜哄憳妯″紡 -->
+    <div v-else-if="data.id == ''" class="s-card-right-isCompare">
+      <div
+        class="person"
+        :style="overflowState ? 'overflow: hidden' : 'overflow: auto'"
+        @mouseenter="cardMouseenter($event)"
+        @mouseleave="cardMouseleave($event)"
+      >
+        <p
+          :title="data.baseInfo[0].compareScore"
+          class="score"
+          style="font-family: PingFangSC-Medium;font-size: 20px;color: #3D68E1;letter-spacing: 0.4px;"
+        >
+          <span>{{ data.baseInfo[0].compareScore }}%</span>
+        </p>
+        <p
+          :style="data.baseInfo[0].bwType == '0' ? 'font-size:12px;line-height:20px' : 'color:red;font-size:12px;line-height:20px'"
+        >{{ data.baseInfo[0].tableName }}</p>
+        <p :style="data.baseInfo[0].bwType == '0' ? '' : 'color:red'">
+          <span>{{ data.baseInfo[0].targetName }}</span>&nbsp;&nbsp;
+          <span
+            v-if="data.baseInfo[0].labels"
+          >/&nbsp;{{ data.baseInfo[0].labels.split("/")[1] }}</span>
+        </p>
+      </div>
+      <div class="card-icon-box">
+        <el-tooltip content="鏌ユ壘姝や汉" placement="top" popper-class="atooltip" style="margin-left:10px">
+          <i class="iconfont iconsousuoren" @click="tosearch(data)" title="鏌ユ壘姝や汉"></i>
+        </el-tooltip>
+      </div>
+    </div>
+    <!-- 娌℃湁搴曞簱 16锛�9鍥剧墖 鏈�姝e父鐨剏olo鎶撴媿 鏃犱汉鍊煎畧  姝e父yolo鎶撴媿娌℃湁灏忓浘-->
+    <div
+      v-else-if="data.targetInfo == null || data.targetInfo[0].picSmUrl == ''"
+      class="s-card-right-signal"
+    >
+      <div
+        class="signal-img-dev"
+        :style="overflowState ? 'overflow: hidden' : 'overflow: auto'"
+        @mouseenter="cardMouseenter($event)"
+        @mouseleave="cardMouseleave($event)"
+      >
+        <p :title="data.picDate">
+          <span class="fontStyle color222">{{ data.picDate }}</span>
+        </p>
+        <p :title="data.cameraAddr" style="margin-bottom: 8px;">
+          <span class="fontStyle color222">{{ data.cameraAddr }}</span>
+        </p>
+        <el-tooltip placement="right" popper-class="atooltip">
+          <div slot="content">
+            <p v-for="(item,index) in data.alarmRules" :key="index+'rule'">
+              <span>{{data.taskName}}</span>&nbsp;&nbsp;
+              <span v-if="item.alarmLevel !== '鎾ら槻'">{{item.alarmLevel}}</span>&nbsp;
+              <span v-if="item.linkInfo == '鑱斿姩浠诲姟'">&nbsp;鑱斿姩浠诲姟</span>
+            </p>
+          </div>
+          <el-button
+            style="border:none;padding:0;overflow:hidden;text-overflow:ellipsis;cursor:default;width:100%;text-align:left"
+          >
+            <span
+              v-for="(item,index) in data.alarmRules"
+              :key="index+'rule1'"
+              style="text-overflow:ellipsis;max-width:100px"
+            >
+              <span class="fontStyle color666">{{data.taskName}}</span>&nbsp;&nbsp;
+              <span
+                class="fontStyle color666"
+                v-if="item.alarmLevel !== '鎾ら槻'"
+              >{{item.alarmLevel}}</span>&nbsp;
+              <span class="fontStyle color666" v-if="item.linkInfo == '鑱斿姩浠诲姟'">&nbsp;鑱斿姩浠诲姟</span>
+              <span v-if="index < data.alarmRules.length-1">/&nbsp;</span>
+            </span>
+          </el-button>
+        </el-tooltip>
+      </div>
+      <div class="right-bottom">
+        <div v-if="!data.id" class="card-icon-box">
+          <!-- <i class="iconfont systemxing ml50" title="鏀惰棌" ></i> -->
+          <el-tooltip content="鏌ユ壘姝や汉" placement="top" popper-class="atooltip">
+            <i class="iconfont iconsousuoren ml50" @click="tosearch(data)"></i>
+          </el-tooltip>
+        </div>
+        <div
+          v-if="data.targetInfo == null || data.targetInfo[0].picSmUrl == ''"
+          class="card-icon-box"
+        >
+          <el-tooltip content="璇︽儏" placement="top" popper-class="atooltip">
+            <i class="iconfont iconcaidan" @click="detailsClick($event)"></i>
+          </el-tooltip>
+          <el-tooltip content="鏀惰棌" placement="top" popper-class="atooltip">
+            <i class="iconfont iconshoucang2" @click="dialogVisible = true"></i>
+          </el-tooltip>
+          <!-- :class="
+              data.isAlarm ? 'iconfont systemmm' : 'iconfont systemxing'
+          "-->
+        </div>
+        <div class="card-icon-box" v-else>
+          <el-tooltip content="璇︽儏" placement="top" popper-class="atooltip">
+            <i class="iconfont iconcaidan" @click="detailsClick($event)"></i>
+          </el-tooltip>
+          <el-tooltip content="鏌ユ壘姝や汉" placement="top" popper-class="atooltip">
+            <i class="iconfont iconsousuoren" @click="tosearch(data)"></i>
+          </el-tooltip>
+          <el-tooltip content="鍔犲叆搴曞簱" placement="top" popper-class="atooltip">
+            <i class="iconfont icontianjiaren" @click="toAdd(data)"></i>
+          </el-tooltip>
+          <el-tooltip content="鏀惰棌" placement="top" popper-class="atooltip">
+            <i class="iconfont iconshoucang2" @click="dialogVisible = true"></i>
+          </el-tooltip>
+        </div>
+      </div>
+    </div>
+
+    <!-- 娌℃湁搴曞簱锛岄潪姣斿锛屾櫘閫氭ā寮� 涓�瀹氭湁targetInfo锛屽苟涓攖argetInfo涓暟涓�1-->
+    <div
+      v-else-if="data.targetInfo !== null && data.targetInfo[0].picSmUrl !== '' && data.targetInfo.length == 1"
+      class="s-card-right-signal"
+    >
+      <div
+        class="signal-img-dev"
+        :style="overflowState ? 'overflow: hidden' : 'overflow: auto'"
+        @mouseenter="cardMouseenter($event)"
+        @mouseleave="cardMouseleave($event)"
+      >
+        <p
+          class="score"
+          v-if="VideoPhotoData.uploadType"
+          style="font-family: PingFangSC-Medium;font-size: 20px;color: #3D68E1;letter-spacing: 0.4px;"
+        >
+          <span v-if="data.id">{{ data.compareScore }}%</span>
+          <span v-else>{{ data.baseInfo[0].compareScore }}%</span>
+        </p>
+        <p :title="data.picDate">
+          <span class="fontStyle color222">{{ data.picDate }}</span>
+        </p>
+        <p :title="data.cameraAddr" style="margin-bottom: 8px;">
+          <span class="fontStyle color222">{{ data.cameraAddr }}</span>
+        </p>
+        <el-tooltip placement="right" popper-class="atooltip" v-if="!VideoPhotoData.uploadType">
+          <div slot="content">
+            <p v-for="(item,index) in data.alarmRules" :key="index+'rule2'">
+              <span class="fontStyle">{{data.taskName}}</span>&nbsp;&nbsp;
+              <span
+                class="fontStyle"
+                v-if="item.alarmLevel !== '鎾ら槻'"
+              >{{item.alarmLevel}}</span>&nbsp;
+              <span v-if="item.linkInfo == '鑱斿姩浠诲姟'" class="fontStyle">&nbsp;鑱斿姩浠诲姟</span>
+              <span v-if="index < data.alarmRules.length-1">/&nbsp;</span>
+            </p>
+          </div>
+          <el-button
+            style="border:none;padding:0;margin:0px;overflow:hidden;text-overflow:ellipsis;cursor:default;width:100%;text-align:left"
+          >
+            <span v-for="(item,index) in data.alarmRules" :key="index+'rule3'">
+              <span class="fontStyle color666">{{data.taskName}}</span>&nbsp;&nbsp;
+              <span
+                class="fontStyle color666"
+                v-if="item.alarmLevel !== '鎾ら槻'"
+              >{{item.alarmLevel}}</span>&nbsp;
+              <span v-if="item.linkInfo == '鑱斿姩浠诲姟'" class="fontStyle color666">&nbsp;鑱斿姩浠诲姟</span>
+              <span v-if="index < data.alarmRules.length-1">/&nbsp;</span>
+            </span>
+          </el-button>
+        </el-tooltip>
+        <!-- <p>
+          <span class="fontStyle color666">{{ data.sex }}</span>&nbsp;/&nbsp;<span class="fontStyle color666">{{ data.ageDescription }}</span>&nbsp;/&nbsp;<span class="fontStyle color666">{{ data.race }}</span>
+        </p>-->
+        <el-tooltip
+          placement="right"
+          popper-class="atooltip"
+          v-if="data.baseInfo && data.baseInfo[0].targetName != ''"
+        >
+          <div slot="content">
+            <p v-for="(item,index) in data.baseInfo" :key="index+'base1'">
+              <span class="fontStyle">{{item.tableName}}</span>&nbsp;
+              <span class="fontStyle" v-if="item.targetName !== ''">/&nbsp;{{item.targetName}}</span>&nbsp;
+              <span
+                class="fontStyle"
+                v-if="item.labels !== '' && item.labels.split('/')[1] !== ''"
+              >/&nbsp;{{item.labels.split("/")[1]}}</span>&nbsp;
+              <span
+                class="fontStyle"
+                v-if="item.labels !== '' && item.labels.split('/')[0] !== ''"
+              >/&nbsp;{{item.labels.split("/")[0]}}</span>
+            </p>
+          </div>
+          <el-button
+            style="border:none;padding:0;margin:0px;overflow:hidden;text-overflow:ellipsis;cursor:default;width:100%;text-align:left"
+          >
+            <span
+              v-for="(item,index) in data.baseInfo"
+              :key="index+'base'"
+              :style="item.bwType == '1' ? 'color:red;font-size:12px;line-height:20px':'font-size:12px;line-height:20px'"
+            >
+              <span class="fontStyle">{{item.tableName}}</span>&nbsp;
+              <span class="fontStyle" v-if="item.targetName !== ''">/&nbsp;{{item.targetName}}</span>&nbsp;
+              <span
+                class="fontStyle"
+                v-if="item.labels !== '' && item.labels.split('/')[1] !== ''"
+              >/&nbsp;{{item.labels.split("/")[1]}}</span>&nbsp;
+              <span
+                class="fontStyle"
+                v-if="item.labels !== '' && item.labels.split('/')[0] !== ''"
+              >/&nbsp;{{item.labels.split("/")[0]}}</span>
+            </span>
+          </el-button>
+        </el-tooltip>
+
+        <el-tooltip
+          placement="right"
+          popper-class="atooltip"
+          v-if="data.baseInfo == null"
+          style="margin-top:5px"
+        >
+          <div slot="content">
+            <span :style="'color:red;font-size:14px;line-height:20px'">{{data.showLabels}}</span>
+          </div>
+          <el-button
+            style="border:none;padding:0;margin:0px;overflow:hidden;text-overflow:ellipsis;cursor:default;width:100%;text-align:left"
+          >
+            <span :style=" 'color:red;font-size:14px;line-height:20px'">{{data.showLabels}}</span>
+          </el-button>
+        </el-tooltip>
+      </div>
+      <div class="right-bottom">
+        <div v-if="!data.id" class="card-icon-box">
+          <!-- 搴曞簱浜哄憳 -->
+          <!-- <i class="iconfont systemxing ml50" title="鏀惰棌" ></i> -->
+          <el-tooltip content="鏌ユ壘姝や汉" placement="top" popper-class="atooltip">
+            <i class="iconfont iconsousuoren ml50" @click="tosearch(data)"></i>
+          </el-tooltip>
+        </div>
+        <div v-if="data.targetInfo[0].picSmUrl == ''" class="card-icon-box">
+          <!-- yolo -->
+          <el-tooltip content="璇︽儏" placement="top" popper-class="atooltip">
+            <i class="iconfont iconcaidan" @click="detailsClick($event)"></i>
+          </el-tooltip>
+          <el-tooltip content="鏀惰棌" placement="top" popper-class="atooltip">
+            <i class="iconfont iconshoucang2"></i>
+          </el-tooltip>
+          <!-- :class="
+              data.isAlarm ? 'iconfont systemmm' : 'iconfont systemxing'
+          "-->
+        </div>
+        <div class="card-icon-box" v-else>
+          <!-- 姝e父浜鸿劯 -->
+          <el-tooltip content="璇︽儏" placement="top" popper-class="atooltip">
+            <i class="iconfont iconcaidan" @click="detailsClick($event)"></i>
+          </el-tooltip>
+          <el-tooltip
+            content="鏌ユ壘姝や汉"
+            placement="top"
+            popper-class="atooltip"
+            v-if="data.targetInfo[0].targetType == 'FaceDetect'"
+          >
+            <i class="iconfont iconsousuoren" @click="tosearch(data)"></i>
+          </el-tooltip>
+          <el-tooltip
+            content="鍔犲叆搴曞簱"
+            placement="top"
+            popper-class="atooltip"
+            v-if="data.targetInfo[0].targetType == 'FaceDetect'"
+          >
+            <i class="iconfont icontianjiaren" @click="toAdd(data)"></i>
+          </el-tooltip>
+          <el-tooltip content="鏀惰棌" placement="top" popper-class="atooltip">
+            <i class="iconfont iconshoucang2"></i>
+          </el-tooltip>
+        </div>
+      </div>
+    </div>
+    <!-- 鎸佺画鏃堕棿妯″紡锛屽寮犲浘 -->
+    <div v-else class="s-card-right-double">
+      <transition name="fade">
+        <div
+          class="double-person"
+          :style="overflowState ? 'overflow: hidden' : 'overflow: auto'"
+          @mouseenter="cardMouseenter($event)"
+          @mouseleave="cardMouseleave($event)"
+        >
+          <div>
+            <p :title="data.picDate">
+              <span class="fontStyle color222">{{ data.picDate }}</span>
+            </p>
+            <p :title="data.cameraAddr" style="margin-bottom: 8px;">
+              <span class="fontStyle color222">{{ data.cameraAddr }}</span>
+            </p>
+            <p v-for="(item,index) in data.alarmRules" :key="index+'rule'">
+              <span class="fontStyle color666">{{data.taskName}}</span>&nbsp;/&nbsp;
+              <span class="fontStyle color666">{{item.alarmLevel}}</span>&nbsp;/&nbsp;
+              <span v-if="item.linkInfo == '鑱斿姩浠诲姟'" class="fontStyle color666">鑱斿姩浠诲姟</span>
+              <span v-if="index < data.alarmRules.length-1">/&nbsp;</span>
+            </p>
+          </div>
+        </div>
+      </transition>
+    </div>
+  </div>
+</template>
+
+<script>
+import cardType from "../../mockData/cardType.ts";
+import bus from "@/main";
+
+export default {
+  mounted() {
+    bus.$on('refreshCompareImg', () => {
+      // this.tempShowType = false
+    })
+    window.addEventListener("resize", this.watchWindow);
+  },
+  props: {
+    data: {
+      type: Object,
+      default: null
+    },
+    showType: {
+      type: String,
+      default: "search"
+    }
+  },
+  watch: {
+    data: {
+      handler(val, oldVal) {
+        console.log('鏁版嵁鍙戠敓鍙樺寲')
+        this.$forceUpdate()
+      },
+      deep: true
+    }
+  },
+  computed: {
+    isId() {
+      return this.data.id
+    }
+  },
+  data() {
+    return {
+      tempShowType: true,
+      initialIndex: 0,
+      cardType,
+      carouselIndex: 0,
+      dialogVisible: false,
+      overflowState: true
+    };
+  },
+  methods: {
+    watchWindow() {
+      // console.log('height')
+      // this.$nextTick(() => {
+      //   document.querySelectorAll('.compareScore111').forEach(ele => {
+      //     ele.style.bottom = this.getBottom()
+      //     console.log("鍏冪礌鐨勬牱寮忓�硷細",ele.style.bottom)
+      //   }); 
+      //   this.$forceUpdate()
+      // })
+    },
+    getBottom() {
+      // let imgDom = document.getElementById(str)
+      let imgDom = this.$refs.firstImg
+      if (imgDom) {
+        let num = (imgDom.offsetHeight - imgDom.offsetWidth) / 2
+        return `${num}px`;
+      }
+      return `4px`;
+    },
+    getUrl(bwtype) {
+      if (bwtype == 1) {
+        return `url(${require("@/assets/bg/red.png")})`
+      } else {
+        return `url(${require("@/assets/bg/green.png")})`
+      }
+    },
+    changeInitialIndex(index) {
+      this.initialIndex = index;
+    },
+    cardMouseenter(ev) {
+      this.overflowState = false;
+    },
+    cardMouseleave(ev) {
+      this.overflowState = true;
+    },
+    changeCarousel(index) {
+      this.carouselIndex = index;
+    },
+    detailsClick(ev) {
+      this.$emit("detailsClick", ev);
+    },
+    toAdd(item) {
+      console.log("瑙﹀彂鍔犲叆搴曞簱")
+      this.$emit("addToBase", item);
+    },
+    tosearch(item) {
+      var curWwwPath = window.document.location.href;
+      var pathname = window.document.location.pathname;
+      var pos = curWwwPath.indexOf(pathname);
+      var localhostPath = curWwwPath.substring(0, pos); //ip+port
+      var href = localhostPath + "/Layout/Searching"
+      let captureId = item.id == "" ? item.baseInfo[0].targetId : item.id
+      var url = item.targetInfo ? item.targetInfo[0].picSmUrl : item.baseInfo[0].targetPicUrl
+      console.log("璺宠浆鍦板潃", href, "url", url)
+      var compType = 1 //  鏁版嵁鏉ヨ嚜浜巈s
+      if (!item.id || item.id == "") {
+        compType = 0 // 鏁版嵁鏉ヨ嚜浜庡簳搴�
+      }
+      window.open(href + '?showType=findByPic&targetId=' + captureId + '&picSmUrl=' + url + '&compType=' + compType)
+    }
+  }
+};
+</script>
+<style lang="scss">
+.fontStyle {
+  font-family: PingFangSC-Medium;
+}
+.color222 {
+  font-size: 0.75rem;
+  font-weight: 600;
+  line-height: 1rem;
+  color: #222222;
+}
+.color666 {
+  color: #666666;
+  font-size: 0.75rem;
+  line-height: 1.25rem;
+}
+.box-card {
+  cursor: default;
+  .el-carousel__arrow {
+    height: 20px;
+    width: 20px;
+  }
+  height: 100%;
+  .el-card__body {
+    height: 100%;
+    padding: 5px;
+    box-sizing: border-box;
+  }
+  .s-card-left-isCompare {
+    float: left;
+    height: 100%;
+    width: calc(60% - 10px);
+    margin-right: 10px;
+    .card-img-box {
+      box-sizing: border-box;
+      width: 100%;
+      height: 100%;
+      position: relative;
+      overflow: hidden;
+      .card-img-box-compear {
+        height: 100%;
+        width: 100%;
+        display: flex;
+        .card-img-box-compear-left {
+          display: inline-block;
+          display: flex;
+          justify-content: center;
+          align-items: Center;
+          overflow: hidden;
+          width: 100%;
+          height: 100%;
+        }
+        .el-carousel__item {
+          display: flex;
+          justify-content: center;
+          align-items: Center;
+          overflow: hidden;
+        }
+        .el-carousel__container {
+          height: 100% !important;
+          .el-carousel__arrow {
+            top: 50% !important;
+          }
+          .el-carousel__arrow {
+            height: 20px;
+            width: 20px;
+          }
+          .el-carousel__arrow--right {
+            right: 5px !important;
+          }
+          .el-carousel__arrow--left {
+            left: 5px !important;
+          }
+        }
+      }
+    }
+    .card-icon-box {
+      width: 100%;
+      text-align: left;
+      position: absolute;
+      bottom: 0px;
+      i {
+        font-size: 20px !important;
+        padding-right: 10px;
+        cursor: pointer;
+      }
+    }
+    img {
+      width: 100%;
+      height: 100%;
+      object-fit: contain;
+    }
+    .s-card-left-isCompare-div {
+      width: 60px;
+      position: absolute;
+      left: calc(50% - 35px);
+      bottom: 16px;
+      padding: 0px 8px;
+      height: 20px;
+      line-height: 20px;
+      color: white;
+      //background-color: red;
+      z-index: 2;
+      border-top-right-radius: 5px;
+      border-top-left-radius: 5px;
+      background-size: 100% 100%;
+    }
+  }
+  .s-card-left {
+    float: left;
+    height: 100%;
+    width: calc(50% - 10px);
+    margin-right: 10px;
+    .s-card-left-box {
+      overflow: hidden;
+      width: 100%;
+      height: 100%;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      .el-carousel__arrow {
+        top: 50%;
+        bottom: inherit;
+      }
+    }
+    .card-icon-box {
+      height: 30px;
+      width: 100%;
+      text-align: left;
+      margin-left: 10px;
+      padding-top: 10px;
+      i {
+        color: #3d68e1;
+        font-size: 20px !important;
+        padding-right: 10px;
+        cursor: pointer;
+      }
+    }
+    .el-carousel {
+      height: 100%;
+      width: 100%;
+      .el-carousel__container {
+        height: 100 !important;
+        width: 100%;
+      }
+      .el-carousel__item {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        background-color: #fff;
+      }
+    }
+    img {
+      width: 100%;
+      height: 100%;
+      object-fit: contain;
+    }
+  }
+  .s-card-right-isCompare {
+    width: 40%;
+    height: 100%;
+    float: left;
+    padding-left: 10px;
+    box-sizing: border-box;
+    position: relative;
+    .active-pull {
+      height: 100% !important;
+      overflow: auto !important;
+      position: relative;
+      z-index: 1;
+    }
+    .overflow {
+      overflow: auto !important;
+    }
+    .person {
+      height: calc(100% - 25px);
+      overflow: hidden;
+      background-color: #fff;
+      text-align: left;
+      .score {
+        font-size: 25px;
+      }
+      p {
+        width: 100%;
+        overflow: hidden;
+        padding: 3px 0px;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+        // cursor: pointer;
+        b {
+          display: inline-block;
+          width: 48px;
+        }
+      }
+    }
+    .card-icon-box {
+      width: 100%;
+      text-align: left;
+      position: absolute;
+      bottom: 0px;
+      i {
+        color: #3d68e1;
+        font-size: 20px !important;
+        padding-right: 10px;
+        cursor: pointer;
+      }
+    }
+  }
+  .s-card-right-signal {
+    width: 50%;
+    height: 100%;
+    float: left;
+    overflow: hidden;
+    background-color: #fff;
+    text-align: left;
+    padding-left: 10px;
+    box-sizing: border-box;
+    position: relative;
+    .el-carousel__arrow {
+      top: 50%;
+    }
+    p {
+      width: 100%;
+      overflow: hidden;
+      padding: 3px 0px;
+      text-overflow: ellipsis;
+      // cursor: pointer;
+      white-space: nowrap;
+      b {
+        display: inline-block;
+        width: 48px;
+      }
+    }
+    .signal-img-dev {
+      height: 100%;
+      width: 100%;
+      //overflow: auto;
+    }
+    .right-bottom {
+      width: 100%;
+      text-align: left;
+      position: absolute;
+      bottom: 0px;
+      i {
+        color: #3d68e1;
+        font-size: 20px !important;
+        padding-right: 10px;
+        cursor: pointer;
+      }
+    }
+  }
+  .s-card-right-double {
+    width: 50%;
+    height: 100%;
+    float: left;
+    overflow: hidden;
+    background-color: #fff;
+    text-align: left;
+    box-sizing: border-box;
+    .double-person {
+      padding: 10px;
+      box-sizing: border-box;
+      overflow: auto;
+      p {
+        width: 100%;
+        overflow: hidden;
+        padding: 3px 0px;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+        // cursor: pointer;
+        b {
+          display: inline-block;
+          width: 48px;
+        }
+      }
+    }
+    .double-person,
+    div {
+      height: 100%;
+      width: 100%;
+    }
+  }
+}
+</style>
diff --git a/src/components/subComponents/DataStackCard.vue b/src/components/subComponents/DataStackCard.vue
new file mode 100644
index 0000000..0cd0054
--- /dev/null
+++ b/src/components/subComponents/DataStackCard.vue
@@ -0,0 +1,158 @@
+<template>
+  <div class="s-board-card flex-center">
+    <div style="width:38%;">
+      <div class="top-text">
+        <em>{{title}}</em>
+      </div>
+      <div class="mid-text">
+        <em>{{total}}</em>
+      </div>
+    </div>
+    <div style="height:86px;">
+      <el-divider class="divider-css" direction="vertical"></el-divider>
+    </div>
+    <div style="width:61%;height:100%;">
+      <div style="height:50%;" class="flex-center right-bot-css">
+        <el-tooltip effect="dark" placement="top">
+          <div slot="content">鍏ㄩ儴鎵撳紑鍒嗘瀽寮�鍏�</div>
+          <span class="bottom-text">
+            <i class="iconfont iconquanbu" style="color:#3D68E1;" v-show="ValidCount.length"></i>
+            {{ValidCount}}
+          </span>
+        </el-tooltip>
+
+        <el-tooltip effect="dark" placement="top">
+          <div slot="content">绠楁硶閰嶇疆涓嶅叏</div>
+          <span class="bottom-text">
+            <i
+              class="iconfont iconicon-test6"
+              style="color:#3D68E1;margin-left: 15px;"
+              v-show="InValidCount.length"
+            ></i>
+            {{InValidCount}}
+          </span>
+        </el-tooltip>
+      </div>
+      <div style="width:100%;">
+        <el-divider></el-divider>
+      </div>
+      <div style="height:40%;" class="flex-center right-bot-css">
+        <el-tooltip effect="dark" placement="top">
+          <div slot="content">姝e湪鎵ц鍒嗘瀽澶勭悊</div>
+          <span class="bottom-text">
+            <i class="iconfont iconicon-test11" style="color:#3D68E1" v-show="RunningCount.length"></i>
+            {{RunningCount}}
+          </span>
+        </el-tooltip>
+
+        <el-tooltip effect="dark" placement="top">
+          <div slot="content">{{fourTip}}</div>
+          <span class="bottom-text">
+            <i
+              :class="`iconfont ${fourIcon}`"
+              style="color:#3D68E1;margin-left:15px;"
+              v-show="NoDeal.length"
+            ></i>
+            {{NoDeal}}
+          </span>
+        </el-tooltip>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "BoardCard",
+  props: {
+    title: { type: String, default: "" },
+    total: { type: String, default: "" },
+    ValidCount: { type: String, default: "" },
+    InValidCount: { type: String, default: "" },
+    RunningCount: { type: String, default: "" },
+    NoDeal: { type: String, default: "" },
+    width: { type: String, default: "126px" },
+    fourTip: { type: String, default: "" },
+    fourIcon: { type: String, default: "" }
+  }
+}
+</script>
+<style lang="scss">
+.s-board-card {
+  height: 120px;
+  width: 100%;
+  display: inline-block;
+  margin: 10px;
+  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 {
+    word-break: keep-all;
+    text-align: right;
+    // position: relative;
+    // top: 3px;
+    // left: 1px;
+    // color: #666666;
+    // font-size: 13px;
+  }
+  em {
+    font-weight: 700;
+  }
+  hr {
+    background: rgb(226, 226, 226);
+    border: 0;
+    height: 1px;
+  }
+  i {
+    font-size: 20px;
+  }
+  .divider-css {
+    height: 100%;
+    margin: 0;
+  }
+  .el-divider--horizontal {
+    display: block;
+    height: 1px;
+    width: 100%;
+    margin: 3px 0;
+  }
+  .right-top-css {
+    margin: 0px auto;
+    position: relative;
+  }
+  .right-bot-css {
+    margin: 0px 5px;
+    position: relative;
+  }
+  .out-div-33 {
+    width: 33%;
+    height: 100%;
+    .txt-css {
+      width: 100%;
+      height: 50%;
+      position: relative;
+      top: 30px;
+    }
+    .icon-css {
+      width: 100%;
+      height: 30%;
+      margin-top: 10px;
+      position: relative;
+    }
+  }
+}
+</style>
\ No newline at end of file
diff --git a/src/components/subComponents/FileUpload/btn.vue b/src/components/subComponents/FileUpload/btn.vue
new file mode 100644
index 0000000..7ea24ff
--- /dev/null
+++ b/src/components/subComponents/FileUpload/btn.vue
@@ -0,0 +1,56 @@
+<template>
+  <label class="uploader-btn" ref="btn" v-show="support">
+    <slot></slot>
+  </label>
+</template>
+
+<script>
+import { uploaderMixin, supportMixin } from './common/mixins'
+
+const COMPONENT_NAME = 'uploader-btn'
+
+export default {
+  name: COMPONENT_NAME,
+  mixins: [uploaderMixin, supportMixin],
+  props: {
+    directory: {
+      type: Boolean,
+      default: false
+    },
+    single: {
+      type: Boolean,
+      default: false
+    },
+    attrs: {
+      type: Object,
+      default() {
+        return {}
+      }
+    }
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.uploader.uploader.assignBrowse(this.$refs.btn, this.directory, this.single, this.attrs)
+    })
+  }
+}
+</script>
+
+<style>
+.uploader-btn {
+  display: inline-block;
+  position: relative;
+  padding: 4px 8px;
+  font-size: 100%;
+  line-height: 1.4;
+  color: #666;
+  border: 1px solid #666;
+  cursor: pointer;
+  border-radius: 2px;
+  background: none;
+  outline: none;
+}
+.uploader-btn:hover {
+  background-color: rgba(0, 0, 0, 0.08);
+}
+</style>
diff --git a/src/components/subComponents/FileUpload/common/file-events.js b/src/components/subComponents/FileUpload/common/file-events.js
new file mode 100644
index 0000000..2aba807
--- /dev/null
+++ b/src/components/subComponents/FileUpload/common/file-events.js
@@ -0,0 +1,3 @@
+const events = ['fileProgress', 'fileSuccess', 'fileComplete', 'fileError']
+
+export default events
diff --git a/src/components/subComponents/FileUpload/common/mixins.js b/src/components/subComponents/FileUpload/common/mixins.js
new file mode 100644
index 0000000..efab3b0
--- /dev/null
+++ b/src/components/subComponents/FileUpload/common/mixins.js
@@ -0,0 +1,14 @@
+export const uploaderMixin = {
+  inject: ['uploader']
+}
+
+export const supportMixin = {
+  data () {
+    return {
+      support: true
+    }
+  },
+  mounted () {
+    this.support = this.uploader.uploader.support
+  }
+}
diff --git a/src/components/subComponents/FileUpload/common/utils.js b/src/components/subComponents/FileUpload/common/utils.js
new file mode 100644
index 0000000..92c775a
--- /dev/null
+++ b/src/components/subComponents/FileUpload/common/utils.js
@@ -0,0 +1,28 @@
+export function secondsToStr(temp) {
+  const years = Math.floor(temp / 31536000)
+  if (years) {
+    return years + ' 骞�' + numberEnding(years)
+  }
+  const days = Math.floor((temp %= 31536000) / 86400)
+  if (days) {
+    return days + ' 澶�' + numberEnding(days)
+  }
+  const hours = Math.floor((temp %= 86400) / 3600)
+  if (hours) {
+    return hours + ' 灏忔椂' + numberEnding(hours)
+  }
+  const minutes = Math.floor((temp %= 3600) / 60)
+  if (minutes) {
+    return minutes + ' 鍒�' + numberEnding(minutes)
+  }
+  const seconds = temp % 60
+  return seconds + ' 绉�' + numberEnding(seconds)
+  function numberEnding(number) {
+    // return (number > 1) ? 's' : ''
+    return ''
+  }
+}
+
+export function kebabCase(s) {
+  return s.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`)
+}
diff --git a/src/components/subComponents/FileUpload/drop.vue b/src/components/subComponents/FileUpload/drop.vue
new file mode 100644
index 0000000..9c88666
--- /dev/null
+++ b/src/components/subComponents/FileUpload/drop.vue
@@ -0,0 +1,64 @@
+<template>
+  <div class="uploader-drop" :class="dropClass" ref="drop" v-show="support">
+    <slot></slot>
+  </div>
+</template>
+
+<script>
+import { uploaderMixin, supportMixin } from './common/mixins'
+
+const COMPONENT_NAME = 'uploader-drop'
+
+export default {
+  name: COMPONENT_NAME,
+  mixins: [uploaderMixin, supportMixin],
+  data() {
+    return {
+      dropClass: ''
+    }
+  },
+  methods: {
+    onDragEnter() {
+      this.dropClass = 'uploader-dragover'
+    },
+    onDragLeave() {
+      this.dropClass = ''
+    },
+    onDrop() {
+      this.dropClass = 'uploader-droped'
+    }
+  },
+  mounted() {
+    this.$nextTick(() => {
+      const dropEle = this.$refs.drop
+      const uploader = this.uploader.uploader
+      uploader.assignDrop(dropEle)
+      uploader.on('dragenter', this.onDragEnter)
+      uploader.on('dragleave', this.onDragLeave)
+      uploader.on('drop', this.onDrop)
+    })
+  },
+  beforeDestroy() {
+    const dropEle = this.$refs.drop
+    const uploader = this.uploader.uploader
+    uploader.off('dragenter', this.onDragEnter)
+    uploader.off('dragleave', this.onDragLeave)
+    uploader.off('drop', this.onDrop)
+    uploader.unAssignDrop(dropEle)
+  }
+}
+</script>
+
+<style>
+.uploader-drop {
+  position: relative;
+  padding: 10px;
+  overflow: hidden;
+  border: 1px dashed #ccc;
+  background-color: #f5f5f5;
+}
+.uploader-dragover {
+  border-color: #999;
+  background-color: #f7f7f7;
+}
+</style>
diff --git a/src/components/subComponents/FileUpload/file.vue b/src/components/subComponents/FileUpload/file.vue
new file mode 100644
index 0000000..43034f2
--- /dev/null
+++ b/src/components/subComponents/FileUpload/file.vue
@@ -0,0 +1,452 @@
+<template>
+  <div class="uploader-file" :status="status">
+    <slot
+      :file="file"
+      :list="list"
+      :status="status"
+      :paused="paused"
+      :error="error"
+      :response="response"
+      :average-speed="averageSpeed"
+      :formated-average-speed="formatedAverageSpeed"
+      :current-speed="currentSpeed"
+      :is-complete="isComplete"
+      :is-uploading="isUploading"
+      :size="size"
+      :formated-size="formatedSize"
+      :uploaded-size="uploadedSize"
+      :progress="progress"
+      :progress-style="progressStyle"
+      :progressing-class="progressingClass"
+      :time-remaining="timeRemaining"
+      :formated-time-remaining="formatedTimeRemaining"
+      :type="type"
+      :extension="extension"
+      :file-category="fileCategory"
+    >
+      <div class="uploader-file-progress" :class="progressingClass" :style="progressStyle"></div>
+      <div class="uploader-file-info">
+        <div class="uploader-file-name">
+          <i class="uploader-file-icon" :icon="fileCategory"></i>
+          {{file.name}}
+        </div>
+        <div class="uploader-file-size">{{formatedSize}}</div>
+        <div class="uploader-file-meta"></div>
+        <div class="uploader-file-status">
+          <span v-show="status !== 'uploading'">{{statusText}}</span>
+          <span v-show="status === 'uploading'">
+            <!-- <span>{{progressStyle.progress}}</span> -->
+            <em>{{formatedAverageSpeed}}</em>
+
+            <i>&nbsp;&nbsp;{{formatedTimeRemaining}}</i>
+          </span>
+        </div>
+        <div class="uploader-file-actions">
+          <span class="uploader-file-pause" @click="pause"></span>
+          <span class="uploader-file-resume" @click="resume">锔�</span>
+          <span class="uploader-file-retry" @click="retry"></span>
+          <span class="uploader-file-remove" @click="remove"></span>
+        </div>
+      </div>
+    </slot>
+  </div>
+</template>
+
+<script>
+import Uploader from 'simple-uploader.js'
+import events from './common/file-events'
+import { secondsToStr } from './common/utils'
+
+const COMPONENT_NAME = 'uploader-file'
+
+export default {
+  name: COMPONENT_NAME,
+  props: {
+    file: {
+      type: Object,
+      default() {
+        return {}
+      }
+    },
+    list: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      response: null,
+      paused: false,
+      error: false,
+      averageSpeed: 0,
+      currentSpeed: 0,
+      isComplete: false,
+      isUploading: false,
+      size: 0,
+      formatedSize: '',
+      uploadedSize: 0,
+      progress: 0,
+      timeRemaining: 0,
+      type: '',
+      extension: '',
+      progressingClass: ''
+    }
+  },
+  computed: {
+    fileCategory() {
+      const extension = this.extension
+      const isFolder = this.file.isFolder
+      let type = isFolder ? 'folder' : 'unknown'
+      const categoryMap = this.file.uploader.opts.categoryMap
+      const typeMap = categoryMap || {
+        image: ['gif', 'jpg', 'jpeg', 'png', 'bmp', 'webp'],
+        video: ['mp4', 'm3u8', 'rmvb', 'avi', 'swf', '3gp', 'mkv', 'flv'],
+        audio: ['mp3', 'wav', 'wma', 'ogg', 'aac', 'flac'],
+        document: ['doc', 'txt', 'docx', 'pages', 'epub', 'pdf', 'numbers', 'csv', 'xls', 'xlsx', 'keynote', 'ppt', 'pptx']
+      }
+      Object.keys(typeMap).forEach((_type) => {
+        const extensions = typeMap[_type]
+        if (extensions.indexOf(extension) > -1) {
+          type = _type
+        }
+      })
+      return type
+    },
+    progressStyle() {
+      const progress = Math.floor(this.progress * 100)
+      const style = `translateX(${Math.floor(progress - 100)}%)`
+      return {
+        progress: `${progress}%`,
+        webkitTransform: style,
+        mozTransform: style,
+        msTransform: style,
+        transform: style
+      }
+    },
+    formatedAverageSpeed() {
+      return `${Uploader.utils.formatSize(this.averageSpeed)} / s`
+    },
+    status() {
+      const isUploading = this.isUploading
+      const isComplete = this.isComplete
+      const isError = this.error
+      const paused = this.paused
+      if (isComplete) {
+        return 'success'
+      } else if (isError) {
+        return 'error'
+      } else if (isUploading) {
+        return 'uploading'
+      } else if (paused) {
+        return 'paused'
+      } else {
+        return 'waiting'
+      }
+    },
+    statusText() {
+      const status = this.status
+      const fileStatusText = this.file.uploader.fileStatusText
+      let txt = status
+      if (typeof fileStatusText === 'function') {
+        txt = fileStatusText(status, this.response)
+      } else {
+        txt = fileStatusText[status]
+      }
+      return txt || status
+    },
+    formatedTimeRemaining() {
+      const timeRemaining = this.timeRemaining
+      const file = this.file
+      if (timeRemaining === Number.POSITIVE_INFINITY || timeRemaining === 0) {
+        return ''
+      }
+      let parsedTimeRemaining = secondsToStr(timeRemaining)
+      const parseTimeRemaining = file.uploader.opts.parseTimeRemaining
+      if (parseTimeRemaining) {
+        parsedTimeRemaining = parseTimeRemaining(timeRemaining, parsedTimeRemaining)
+      }
+      return parsedTimeRemaining
+    }
+  },
+  watch: {
+    status(newStatus, oldStatus) {
+      if (oldStatus && newStatus === 'uploading' && oldStatus !== 'uploading') {
+        this.tid = setTimeout(() => {
+          this.progressingClass = 'uploader-file-progressing'
+        }, 200)
+      } else {
+        clearTimeout(this.tid)
+        this.progressingClass = ''
+      }
+    }
+  },
+  methods: {
+    _actionCheck() {
+      this.paused = this.file.paused
+      this.error = this.file.error
+      this.isUploading = this.file.isUploading()
+    },
+    pause() {
+      this.file.pause()
+      this._actionCheck()
+      this._fileProgress()
+    },
+    resume() {
+      this.file.resume()
+      this._actionCheck()
+    },
+    remove() {
+      this.file.cancel()
+    },
+    retry() {
+      this.file.retry()
+      this._actionCheck()
+    },
+    processResponse(message) {
+      debugger
+      let res = message
+      try {
+        res = JSON.parse(message)
+      } catch (e) { }
+      this.response = res
+    },
+    fileEventsHandler(event, args) {
+      const rootFile = args[0]
+      const file = args[1]
+      const target = this.list ? rootFile : file
+      if (this.file === target) {
+        if (this.list && event === 'fileSuccess') {
+          this.processResponse(args[2])
+          return
+        }
+        this[`_${event}`].apply(this, args)
+      }
+    },
+    _fileProgress() {
+      this.progress = this.file.progress()
+      this.averageSpeed = this.file.averageSpeed
+      this.currentSpeed = this.file.currentSpeed
+      this.timeRemaining = this.file.timeRemaining()
+      this.uploadedSize = this.file.sizeUploaded()
+      this._actionCheck()
+    },
+    _fileSuccess(rootFile, file, message) {
+      if (rootFile) {
+        this.processResponse(message)
+      }
+      this._fileProgress()
+      this.error = false
+      this.isComplete = true
+      this.isUploading = false
+      console.log('rootFile, file, message',rootFile, file, message)
+      debugger
+    },
+    _fileComplete() {
+      this._fileSuccess()
+    },
+    _fileError(rootFile, file, message) {
+      this._fileProgress()
+      console.log('rootFile, file, message',rootFile, file, message)
+      debugger
+      this.processResponse(message)
+      this.error = true
+      this.isComplete = false
+      this.isUploading = false
+    }
+  },
+  mounted() {
+    const staticProps = ['paused', 'error', 'averageSpeed', 'currentSpeed']
+    const fnProps = [
+      'isComplete',
+      'isUploading',
+      {
+        key: 'size',
+        fn: 'getSize'
+      },
+      {
+        key: 'formatedSize',
+        fn: 'getFormatSize'
+      },
+      {
+        key: 'uploadedSize',
+        fn: 'sizeUploaded'
+      },
+      'progress',
+      'timeRemaining',
+      {
+        key: 'type',
+        fn: 'getType'
+      },
+      {
+        key: 'extension',
+        fn: 'getExtension'
+      }
+    ]
+    staticProps.forEach(prop => {
+      this[prop] = this.file[prop]
+    })
+    fnProps.forEach((fnProp) => {
+      if (typeof fnProp === 'string') {
+        this[fnProp] = this.file[fnProp]()
+      } else {
+        this[fnProp.key] = this.file[fnProp.fn]()
+      }
+    })
+
+    const handlers = this._handlers = {}
+    const eventHandler = (event) => {
+      handlers[event] = (...args) => {
+        this.fileEventsHandler(event, args)
+      }
+      return handlers[event]
+    }
+    events.forEach((event) => {
+      this.file.uploader.on(event, eventHandler(event))
+    })
+  },
+  destroyed() {
+    events.forEach((event) => {
+      this.file.uploader.off(event, this._handlers[event])
+    })
+    this._handlers = null
+  }
+}
+</script>
+
+<style>
+.uploader-file {
+  position: relative;
+  height: 49px;
+  line-height: 49px;
+  overflow: hidden;
+  border-bottom: 1px solid #cdcdcd;
+}
+.uploader-file[status="waiting"] .uploader-file-pause,
+.uploader-file[status="uploading"] .uploader-file-pause {
+  display: block;
+}
+.uploader-file[status="paused"] .uploader-file-resume {
+  display: block;
+}
+.uploader-file[status="error"] .uploader-file-retry {
+  display: block;
+}
+.uploader-file[status="success"] .uploader-file-remove {
+  display: none;
+}
+.uploader-file[status="error"] .uploader-file-progress {
+  background: #ffe0e0;
+}
+.uploader-file-progress {
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  background: #e2eeff;
+  transform: translateX(-100%);
+}
+.uploader-file-progressing {
+  transition: all 0.4s linear;
+}
+.uploader-file-info {
+  position: relative;
+  z-index: 1;
+  height: 100%;
+  overflow: hidden;
+}
+.uploader-file-info:hover {
+  background-color: rgba(240, 240, 240, 0.2);
+}
+.uploader-file-info i,
+.uploader-file-info em {
+  font-style: normal;
+}
+.uploader-file-name,
+.uploader-file-size,
+.uploader-file-meta,
+.uploader-file-status,
+.uploader-file-actions {
+  float: left;
+  position: relative;
+  height: 100%;
+}
+.uploader-file-name {
+  width: 50%;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  text-indent: 14px;
+  text-align: left;
+}
+.uploader-file-icon {
+  width: 24px;
+  height: 24px;
+  display: inline-block;
+  vertical-align: top;
+  margin-top: 13px;
+  margin-right: 8px;
+}
+.uploader-file-icon::before {
+  content: "馃搩";
+  display: block;
+  height: 100%;
+  font-size: 24px;
+  line-height: 1;
+  text-indent: 0;
+}
+.uploader-file-icon[icon="folder"]::before {
+  content: "馃搨";
+}
+.uploader-file-icon[icon="image"]::before {
+  content: "馃寙";
+}
+.uploader-file-icon[icon="video"]::before {
+  content: "馃幀";
+}
+.uploader-file-icon[icon="audio"]::before {
+  content: "馃幍";
+}
+.uploader-file-icon[icon="document"]::before {
+  content: "馃搵";
+}
+.uploader-file-size {
+  width: 11%;
+  text-indent: 10px;
+}
+.uploader-file-meta {
+  width: 8%;
+}
+.uploader-file-status {
+  width: 24%;
+  text-indent: 20px;
+}
+.uploader-file-actions {
+  width: 6%;
+}
+.uploader-file-actions > span {
+  display: none;
+  float: left;
+  width: 16px;
+  height: 16px;
+  margin-top: 16px;
+  margin-right: 10px;
+  cursor: pointer;
+  background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAABkCAYAAAD0ZHJ6AAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAAJcEhZcwAACxMAAAsTAQCanBgAAARkSURBVGje7ZnfS1NRHMAH4ptPkvQSuAdBkCxD8FUQJMEULUgzy1KyyPVQ4JMiiP4Bvg6EwUQQfMmwhwRDshwaKUjDVCgoSdDNHkzTJZ6+Z37Purve8+PeTb2TM/ggu+ew89l33x8H9BBCPG7GowXTJej3+wnDvEm0JuLC04+EYWftVAUv+fiCvDUdQR1BHUEdQR3BTIygvixoQS14XgTtthLVdpNWwXRLqvQ724LplFRtyrYF0yVpFLQrKRVMh6RZ0I6kkmCqklaCqpKZH0FX56Crq9jVfdDVk0RfFrSgFsxkQVmLcdKCVrKySCrryhPEyYShhzOcrFtG0EoilfHHk1CRU5rF6ZjNZhlVOW6RnMSVyyilKies4pO41diVy8wIujoHXV3FGdMHXTtJKLFYTLhZtq4vC1rwXApCZTIqgR6g1PBMCO9DL3bMMSqBHqDU8EyISDAHiGKvWwcCQG2KgjlAFCDAOhAAap0K5gKLphk8mqJgLrCIgoxRJ4J5wKpJ7gAoMkn5EBXBPGDVJHcAFJmkfIhQcAql1oBpTvTol9gG9pm4RHAKpdaAaU706JfYBvaZuJVgPQrt4sFlnOh5MC/p3lmJYD0K7eLBZZzoeTAv6d5ZnuAYHjpgEOnk5F0ufhG6v1ggOIaHDhhEOjl5l4tfhO4vthLcwAMrFNvLJO5vEwhu4IEViu1lEve3WQmyoihQFBzG/V0CQVYUBYqCw7i/SxTBcpsRbFeIYLnNCLZbCY5b5KAnxRwct8hBj9McZFVMW0ihRNBuFdMWUigRlFaxuQ9WWYjRMTiIe5z0wSoLMToGB3GPsA9aTZIJoB+nRgBnM1tzOkkmgH6cGgGczWzNpzqLx3n/aULJJgezeNw07oxQySbVywKjBOgFRnDs+VEsx8FlgVEC9AIjOPb8KJYjvSzoG7UW1IJaUAtqQS14toLNM5fN5APdwBJA8G83Pk/aK/rgzVvXzeQD3cASQPBvNz5P2ssTzAaGUIrHEO6zI5gNDKEUjyHcxxWkh4Ylcowwk1QQpIeGJXKMMJO0EgwqyjGCioJBJvDrxRMSuVOTJEXfbz1/bHwWtBL0yoQehK6RucgE+bGzanzulQh6E3IgQV+xpc8kcrfuSO7eTfJ3ZYmQw0Oy9azVKOk1C/bJ5D5F38YPeLfx0rjWJxHsS0SqsSYuxySjj5qO5Oj7xQWy2VBtFOwzCy6ryH3YfE3uh64Y1xckgstJPydEjkkeHv07Iy4Xaao15+KCWTBx6M/db+T9xivSErqaJDdzXI6yLRE8Vgg0coex/SPJvT0SbWu0KpZtbgSpCH3NRt7I5OxHkObc6heU+/M/J5vrpBFM5GBLqCQux14COXs5CNXK5OjPGm1tSMrJSOMNYQ4mVTGV/L6zTL7+DovkbFUxbSW0Wo05l8hJWsU+cRWfSh+Mt5Lb1ck/J1TvVsdDaR/MiEni+llsdZuZp62EViu+96bpNjNPWwmtVnzvFd5m9IVVC54x/wA7gNvqFG9vXQAAAABJRU5ErkJggg==")
+    no-repeat 0 0;
+}
+.uploader-file-actions > span:hover {
+  background-position-x: -21px;
+}
+.uploader-file-actions .uploader-file-pause {
+  background-position-y: 0;
+}
+.uploader-file-actions .uploader-file-resume {
+  background-position-y: -17px;
+}
+.uploader-file-actions .uploader-file-retry {
+  background-position-y: -53px;
+}
+.uploader-file-actions .uploader-file-remove {
+  display: block;
+  background-position-y: -34px;
+}
+</style>
diff --git a/src/components/subComponents/FileUpload/files.vue b/src/components/subComponents/FileUpload/files.vue
new file mode 100644
index 0000000..1380ba9
--- /dev/null
+++ b/src/components/subComponents/FileUpload/files.vue
@@ -0,0 +1,42 @@
+<template>
+  <div class="uploader-files">
+    <slot :files="files">
+      <ul>
+        <li v-for="file in files" :key="file.id">
+          <uploader-file :file="file"></uploader-file>
+        </li>
+      </ul>
+    </slot>
+  </div>
+</template>
+
+<script>
+import { uploaderMixin } from './common/mixins'
+import UploaderFile from './file.vue'
+
+const COMPONENT_NAME = 'uploader-files'
+
+export default {
+  name: COMPONENT_NAME,
+  mixins: [uploaderMixin],
+  computed: {
+    files() {
+      return this.uploader.files
+    }
+  },
+  components: {
+    UploaderFile
+  }
+}
+</script>
+
+<style>
+.uploader-files {
+  position: relative;
+}
+.uploader-files > ul {
+  list-style: none;
+  margin: 0;
+  padding: 0;
+}
+</style>
diff --git a/src/components/subComponents/FileUpload/index.vue b/src/components/subComponents/FileUpload/index.vue
new file mode 100644
index 0000000..97c4562
--- /dev/null
+++ b/src/components/subComponents/FileUpload/index.vue
@@ -0,0 +1,230 @@
+<template>
+  <div class="file-uploader">
+    <uploader
+      v-if="single"
+      ref="uploader"
+      :options="options"
+      :file-status-text="statusText"
+      class="uploader-single"
+      @file-added="onFileAdded"
+      @complete="onComplete"
+    >
+      <el-input :placeholder="uploadPlaceholder" size="small" :readonly="true" v-model="fileName">
+        <uploader-btn slot="suffix" >
+          <el-tooltip :content="tipWords" placement="top" v-if="tip">
+            <i class="el-icon-upload2" style="font-size:18px; color:#0088ff"></i>
+          </el-tooltip>
+          <i v-else class="el-icon-upload2" style="font-size:18px; color:#0088ff"></i>
+        </uploader-btn>
+      </el-input>
+      <uploader-list />
+    </uploader>
+
+    <uploader
+      v-else
+      ref="uploader"
+      :options="options"
+      :file-status-text="statusText"
+      class="uploader-example"
+      @file-added="onFileAdded"
+      @file-complete="fileComplete"
+      @complete="onComplete"
+      @close="closeHandle"
+    >
+      <uploader-btn ref="button">        
+        <i class="el-icon-upload2" style="font-size:18px; color:#0088ff"></i>
+        涓婁紶
+      </uploader-btn>
+      <uploader-list />
+    </uploader>
+  </div>
+</template>
+
+<script>
+import uploader from "./uploader"
+import SparkMD5 from 'spark-md5';
+import UploaderBtn from "./btn"
+import UploaderList from "./list"
+
+export default {
+  components: {
+    uploader,
+    UploaderBtn,
+    UploaderList
+  },
+  props: {
+    tip: {
+      type: Boolean,
+      default: false
+    },
+    tipWords: {
+      type: String,
+      default: ''
+    },
+    single: {
+      type: Boolean,
+      default: false
+    },
+    uploadPlaceholder: {
+      type: String,
+      default: ''
+    },
+    url: {
+      type: String,
+      default: "/data/api-f/file/upload" //"//192.168.20.10:3000/upload"
+    },
+  },
+  data() {
+    return {
+      fileName: "",
+      fileMd5: "",
+      attrs: {
+        accept: 'image/*'
+      },
+      statusText: {
+        success: '涓婁紶鎴愬姛',
+        error: '涓婁紶澶辫触',
+        uploading: '涓婁紶涓�',
+        paused: '鏆傚仠涓�',
+        waiting: '绛夊緟涓�'
+      }
+    }
+  },
+  computed: {
+    uploader() {
+      return this.$refs.uploader.uploader;
+    },
+    options() {
+      return {
+        target: this.url,
+        testChunks: true,
+        headers: {
+          Authorization: sessionStorage.getItem('loginedInfo') && JSON.parse(sessionStorage.getItem('loginedInfo')).access_token
+        }
+      }
+    }
+  },
+  methods: {
+    onFileAdded(file) {
+      if (this.single) {
+        this.uploader.fileList = this.uploader.fileList.slice([-1]);
+        this.$emit("file-added")
+      }
+      this.computeMD5(file);
+    },
+    computeMD5(file) {
+      let fileReader = new FileReader();
+      let time = new Date().getTime();
+      let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
+      let currentChunk = 0;
+      const chunkSize = 10 * 1024 * 1000;
+      let chunks = Math.ceil(file.size / chunkSize);
+      let spark = new SparkMD5.ArrayBuffer();
+      // 鏂囦欢鐘舵�佽涓�"璁$畻MD5"
+      this.statusText.paused = "鍑嗗涓婁紶,姝e湪妫�鏌ユ枃浠�"
+      file.pause();
+      loadNext();
+      fileReader.onload = (e => {
+        spark.append(e.target.result);
+        if (currentChunk < chunks) {
+          currentChunk++;
+          loadNext();
+        } else {
+          let md5 = spark.end();
+          this.computeMD5Success(md5, file);
+          this.fileName = file.name;
+          this.fileMd5 = md5;
+          // console.log(`MD5璁$畻瀹屾瘯锛�${file.name} \nMD5锛�${md5} \n鍒嗙墖锛�${chunks} 澶у皬:${file.size} 鐢ㄦ椂锛�${new Date().getTime() - time} ms`);
+        }
+      });
+      fileReader.onerror = function () {
+        this.error(`鏂囦欢${file.name}璇诲彇鍑洪敊锛岃妫�鏌ヨ鏂囦欢`)
+        file.cancel();
+      };
+      function loadNext() {
+        let start = currentChunk * chunkSize;
+        let end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;
+        fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end));
+      }
+    },
+    computeMD5Success(md5, file) {
+      // 灏嗚嚜瀹氫箟鍙傛暟鐩存帴鍔犺浇uploader瀹炰緥鐨刼pts涓�
+      if (this.$route.path.indexOf("VideoManage") >= 0) {
+        Object.assign(this.uploader.opts, {
+          query: {
+            stackId: this.DataStackPool.selectedDir.id
+            // ...this.params,
+          }
+        })
+      }
+      file.uniqueIdentifier = md5;
+      file.resume();
+      this.statusText.paused = "鏆傚仠涓�";
+    },
+    onComplete() {
+      debugger
+      this.$emit("complete", { filename: this.fileName, identifier: this.fileMd5 });
+    },
+    fileComplete() {
+      // console.log('file complete', arguments)
+    },
+    closeHandle() {
+      this.$emit("close")
+    }
+  },
+  mounted() {
+    this.$nextTick(() => {
+      window.uploader = this.$refs.uploader.uploader
+    })
+  }
+}
+</script>
+
+<style lang="scss">
+.file-uploader {
+  .el-input__suffix,.el-input__suffix-inner{
+    outline: none!important;
+  }
+  .el-tooltip.focusing{
+    outline: none;
+  }
+  .uploader-example {
+    width: 99%;
+    // padding: 15px;
+    // margin: 40px auto 0;
+    font-size: 12px;
+    // box-shadow: 0 0 10px rgba(0, 0, 0, 0.4);
+    background-color: #fff;
+  }
+  .uploader-example .uploader-btn {
+    position: relative;
+    display: none;
+    // float: right;
+    // top: -45px;
+  }
+  .uploader-example .uploader-list {
+    max-height: 440px;
+    overflow: auto;
+    overflow-x: hidden;
+    overflow-y: auto;
+  }
+  .uploader-single {
+    position: unset;
+    .close {
+      display: none;
+    }
+    .uploader-btn {
+      border: 0px;  
+    }
+    .uploader-file {
+      height: 2px;
+      .uploader-file-progress {
+        background: #3d68e1;
+      }
+      .uploader-file-info {
+        display: none;
+      }
+    }
+  }
+}
+</style>>
diff --git a/src/components/subComponents/FileUpload/list.vue b/src/components/subComponents/FileUpload/list.vue
new file mode 100644
index 0000000..b572727
--- /dev/null
+++ b/src/components/subComponents/FileUpload/list.vue
@@ -0,0 +1,42 @@
+<template>
+  <div class="uploader-list">
+    <slot :file-list="fileList">
+      <ul>
+        <li v-for="file in fileList" :key="file.id">
+          <uploader-file :file="file" :list="true"></uploader-file>
+        </li>
+      </ul>
+    </slot>
+  </div>
+</template>
+
+<script>
+import { uploaderMixin } from './common/mixins'
+import UploaderFile from './file.vue'
+
+const COMPONENT_NAME = 'uploader-list'
+
+export default {
+  name: COMPONENT_NAME,
+  mixins: [uploaderMixin],
+  computed: {
+    fileList() {
+      return this.uploader.fileList
+    }
+  },
+  components: {
+    UploaderFile
+  }
+}
+</script>
+
+<style>
+.uploader-list {
+  position: relative;
+}
+.uploader-list > ul {
+  list-style: none;
+  margin: 0;
+  padding: 0;
+}
+</style>
diff --git a/src/components/subComponents/FileUpload/unsupport.vue b/src/components/subComponents/FileUpload/unsupport.vue
new file mode 100644
index 0000000..59626ee
--- /dev/null
+++ b/src/components/subComponents/FileUpload/unsupport.vue
@@ -0,0 +1,30 @@
+<template>
+  <div class="uploader-unsupport" v-show="!support">
+    <slot>
+      <p>
+        Your browser, unfortunately, is not supported by Uploader.js. The library requires support for
+        <a href="http://www.w3.org/TR/FileAPI/">the HTML5 File API</a> along with
+        <a href="http://www.w3.org/TR/FileAPI/#normalization-of-params">file slicing</a>.
+      </p>
+    </slot>
+  </div>
+</template>
+
+<script>
+import { uploaderMixin, supportMixin } from './common/mixins'
+
+const COMPONENT_NAME = 'uploader-unsupport'
+
+export default {
+  name: COMPONENT_NAME,
+  mixins: [uploaderMixin, supportMixin]
+}
+</script>
+
+<style>
+.uploader-unsupport {
+  position: relative;
+  z-index: 10;
+  overflow: hidden;
+}
+</style>
diff --git a/src/components/subComponents/FileUpload/uploader.vue b/src/components/subComponents/FileUpload/uploader.vue
new file mode 100644
index 0000000..2df8221
--- /dev/null
+++ b/src/components/subComponents/FileUpload/uploader.vue
@@ -0,0 +1,155 @@
+<template>
+  <div class="uploader">
+    <!-- <div class="close" @click="closeHandle">x</div> -->
+    <slot :files="files" :file-list="fileList" :started="started">
+      <uploader-unsupport></uploader-unsupport>
+      <uploader-drop>
+        <!-- <p>鎷栧姩鏂囦欢鍒拌鍖哄煙涓婁紶</p> -->
+        <uploader-btn>閫夋嫨鏂囦欢</uploader-btn>
+        <uploader-btn :directory="true">閫夋嫨鏂囦欢澶�</uploader-btn>
+      </uploader-drop>
+      <uploader-list></uploader-list>
+    </slot>
+  </div>
+</template>
+
+<script>
+import Uploader from 'simple-uploader.js'
+import { kebabCase } from './common/utils'
+import UploaderBtn from './btn.vue'
+import UploaderDrop from './drop.vue'
+import UploaderUnsupport from './unsupport.vue'
+import UploaderList from './list.vue'
+
+const COMPONENT_NAME = 'uploader'
+const FILE_ADDED_EVENT = 'fileAdded'
+const FILES_ADDED_EVENT = 'filesAdded'
+const UPLOAD_START_EVENT = 'uploadStart'
+
+export default {
+  name: COMPONENT_NAME,
+  provide() {
+    return {
+      uploader: this
+    }
+  },
+  props: {
+    options: {
+      type: Object,
+      default() {
+        return {}
+      }
+    },
+    autoStart: {
+      type: Boolean,
+      default: true
+    },
+    fileStatusText: {
+      type: [Object, Function],
+      default() {
+        return {
+          success: 'success',
+          error: 'error',
+          uploading: 'uploading',
+          paused: 'paused',
+          waiting: 'waiting'
+        }
+      }
+    }
+  },
+  data() {
+    return {
+      started: false,
+      files: [],
+      fileList: []
+    }
+  },
+  methods: {
+    uploadStart() {
+      this.started = true
+    },
+    fileAdded(file) {
+      this.$emit(kebabCase(FILE_ADDED_EVENT), file)
+      if (file.ignored) {
+        // is ignored, filter it
+        return false
+      }
+    },
+    filesAdded(files, fileList) {
+      this.$emit(kebabCase(FILES_ADDED_EVENT), files, fileList)
+      if (files.ignored || fileList.ignored) {
+        // is ignored, filter it
+        return false
+      }
+    },
+    fileRemoved(file) {
+      this.files = this.uploader.files
+      this.fileList = this.uploader.fileList
+    },
+    filesSubmitted(files, fileList) {
+      this.files = this.uploader.files
+      this.fileList = this.uploader.fileList
+      if (this.autoStart) {
+        this.uploader.upload()
+      }
+    },
+    allEvent(...args) {
+      const name = args[0]
+      const EVENTSMAP = {
+        [FILE_ADDED_EVENT]: true,
+        [FILES_ADDED_EVENT]: true,
+        [UPLOAD_START_EVENT]: 'uploadStart'
+      }
+      const handler = EVENTSMAP[name]
+      if (handler) {
+        if (handler === true) {
+          return
+        }
+        this[handler].apply(this, args.slice(1))
+      }
+      args[0] = kebabCase(name)
+      this.$emit.apply(this, args)
+    },
+    closeHandle() {
+      this.$emit("close")
+    }
+  },
+  created() {
+    this.options.initialPaused = !this.autoStart
+    const uploader = new Uploader(this.options)
+    this.uploader = uploader
+    this.uploader.fileStatusText = this.fileStatusText
+    uploader.on('catchAll', this.allEvent)
+    uploader.on(FILE_ADDED_EVENT, this.fileAdded)
+    uploader.on(FILES_ADDED_EVENT, this.filesAdded)
+    uploader.on('fileRemoved', this.fileRemoved)
+    uploader.on('filesSubmitted', this.filesSubmitted)
+  },
+  destroyed() {
+    const uploader = this.uploader
+    uploader.off('catchAll', this.allEvent)
+    uploader.off(FILE_ADDED_EVENT, this.fileAdded)
+    uploader.off(FILES_ADDED_EVENT, this.filesAdded)
+    uploader.off('fileRemoved', this.fileRemoved)
+    uploader.off('filesSubmitted', this.filesSubmitted)
+    this.uploader = null
+  },
+  components: {
+    UploaderBtn,
+    UploaderDrop,
+    UploaderUnsupport,
+    UploaderList
+  }
+}
+</script>
+
+<style lang="scss">
+.uploader {
+  .close {
+    position: absolute;
+    right: 5px;
+    top: 3px;
+    cursor: pointer;
+  }
+}
+</style>
diff --git a/src/components/subComponents/IPInput.vue b/src/components/subComponents/IPInput.vue
new file mode 100644
index 0000000..4f59322
--- /dev/null
+++ b/src/components/subComponents/IPInput.vue
@@ -0,0 +1,231 @@
+<template>
+  <div class="ip-input-container">
+    <div class="ip-segment" v-for="(segment, index) in segments" :key="index">
+      <input
+        type="text"
+        maxlength="3"
+        class="ip-segment-input"
+        :value="segment"
+        :placeholder="placeholder"
+        :disabled="disabled"
+        v-on:keydown="onInputKeydown($event, index)"
+        v-on:input="onInput($event, index)"
+        v-on:blur="onInputBlur()"
+        v-on:paste="onPaste($event, index)"
+      />
+      <i v-show="index != segments.length - 1">.</i>
+    </div>
+  </div>
+</template>
+
+<script>
+/* global document*/
+/**
+ * get the cursor position of the element
+ * @param  {Element} el the element
+ * @return {Integer}    the position fo the cursor
+ */
+function getRange(el) {
+  var cuRange;
+  var tbRange;
+  var headRange;
+  var range;
+  var dupRange;
+  var ret = {};
+  if (el.setSelectionRange) {
+    // standard
+    ret.begin = el.selectionStart;
+    ret.end = el.selectionEnd;
+    ret.result = el.value.substring(ret.begin, ret.end);
+  } else if (document.selection) {
+    // ie
+    if (el.tagName.toLowerCase() === "input") {
+      cuRange = document.selection.createRange();
+      tbRange = el.createTextRange();
+      tbRange.collapse(true);
+      tbRange.select();
+      headRange = document.selection.createRange();
+      headRange.setEndPoint("EndToEnd", cuRange);
+      ret.begin = headRange.text.length - cuRange.text.length;
+      ret.end = headRange.text.length;
+      ret.result = cuRange.text;
+      cuRange.select();
+    } else if (el.tagName.toLowerCase() === "textarea") {
+      range = document.selection.createRange();
+      dupRange = range.duplicate();
+      dupRange.moveToElementText(el);
+      dupRange.setEndPoint("EndToEnd", range);
+      ret.begin = dupRange.text.length - range.text.length;
+      ret.end = dupRange.text.length;
+      ret.result = range.text;
+    }
+  }
+  el.focus();
+  return ret;
+}
+export default {
+  props: {
+    ip: {
+      type: String,
+      defalut: ""
+    },
+    item: {},
+    placeholder: String,
+    onChange: Function,
+    onBlur: Function,
+    onItemChange: Function,
+    disabled: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      segments: ["", "", "", ""]
+    };
+  },
+  watch: {
+    ip(ip) {
+      this.syncIp(ip);
+    }
+  },
+  methods: {
+    onInputKeydown(event, index) {
+      var keyCode = event.keyCode || event.which;
+      var value = event.target.value;
+      if (keyCode === 8 || keyCode === 37) {
+        // move the cursor to previous input if backspace and left arrow is pressed at the begin of one input
+        if (
+          (value.length === 0 || getRange(event.target).end === 0) &&
+          index > 0
+        ) {
+          this.$el.getElementsByTagName("input")[index - 1].focus();
+          // When jump to pre input(enter "backspace"), thr cursor should in the end.
+          // before fix: 127.|0.0.0  =>   12|7.0.0.1
+          // after fix: 127.|0.0.0 = >   127|.0.0.0
+          // notes: "|" mean the cursor position.
+          event.preventDefault();
+        }
+      } else if (keyCode === 39 && keyCode === 110) {
+        if (getRange(event.target).end === value.length && index < 3) {
+          // move to cursor to the next input if right arrow is pressed at the end of one input
+          this.$el.getElementsByTagName("input")[index + 1].focus();
+        }
+      }
+    },
+    onInput(event, index) {
+      var value = event.target.value;
+      event.target.value = this.segments[index];
+      var segment = Number(value);
+      if (isNaN(segment)) {
+        return;
+      } else if (value === "") {
+        this.segments.splice(index, 1, "");
+      } else if (segment > 255 || segment < 0) {
+        // set the segment to 255 if out of ip range
+        this.segments.splice(index, 1, 255);
+      } else {
+        this.segments.splice(index, 1, segment);
+      }
+      // jump to next input
+      if (
+        (value.length === 3 && index < 3) ||
+        value[value.length - 1] === "."
+      ) {
+        this.$el.getElementsByTagName("input")[index + 1].focus();
+      }
+    },
+    onInputBlur() {
+      setTimeout(() => {
+        this.$emit("on-blur", this.segments.join("."));
+        if (this.onBlur) {
+          this.onBlur(this.segments.join("."));
+        }
+        if (this.onItemChange) {
+          this.onItemChange(this.segments.join("."), this.item)
+        }
+      }, 50);
+    },
+    onPaste(e, index) {
+      var pasteText = e.clipboardData.getData("text/plain");
+      var segments = pasteText.split(".");
+      segments.forEach((segment, i) => {
+        if (
+          index + i < 4 &&
+          !isNaN(segment) &&
+          segment >= 0 &&
+          segment <= 255
+        ) {
+          this.segments.splice(index + i, 1, segment);
+        }
+      });
+      e.preventDefault();
+    },
+    syncIp(ip) {
+      if (ip && ip.indexOf(".") !== -1) {
+        ip.split(".").map((segment, index) => {
+          if (isNaN(segment) || segment < 0 || segment > 255) {
+            segment = 255;
+          }
+          this.segments.splice(index, 1, segment);
+          return segment;
+        });
+      }
+    }
+  },
+  mounted() {
+    this.syncIp(this.ip);
+    this.$watch(
+      () => {
+        return this.segments.join(".");
+      },
+      (val, oldValue) => {
+        if (val !== oldValue) {
+          if (val === "...") {
+            val = "";
+          }
+          if (this.onChange) {
+            this.onChange(val);
+          }
+        }
+      }
+    );
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.ip-input-container {
+  display: inline-block;
+  width: 100%;
+  height: 32px;
+  line-height: normal;
+  border: 1px solid #dcdfe6;
+  box-sizing: border-box;
+  background-color: #fff;
+  text-align: left;
+  max-width: 360px;
+}
+.ip-segment {
+  display: inline-block;
+  width: 25%;
+  height: 32px;
+  line-height: normal;
+  input {
+    width: 90%;
+    height: 32px;
+    line-height: normal;
+    border: none;
+    outline: none;
+    text-align: center;
+    text-indent: 0px;
+    margin: 0px;
+    padding: 0px;
+    background-color: transparent;
+  }
+  i {
+    display: inline-block;
+    font-size: 18px;
+  }
+}
+</style>
\ No newline at end of file
diff --git a/src/components/subComponents/LocalVedioCard.vue b/src/components/subComponents/LocalVedioCard.vue
new file mode 100644
index 0000000..a1c5bd1
--- /dev/null
+++ b/src/components/subComponents/LocalVedioCard.vue
@@ -0,0 +1,139 @@
+<template>
+  <div class="board-card flex-center">
+    <div style="width:40%;">
+      <div class="top-text">
+        <em>{{title}}</em>
+      </div>
+      <div class="mid-text">
+        <em>{{total}}</em>
+      </div>
+    </div>
+    <div style="height:86px;">
+      <el-divider class="divider-css" direction="vertical"></el-divider>
+    </div>
+    <div style="width:59%;height:100%;" class="flex-center">
+      <div class="out-div-33">
+        <div class="txt-css">
+          <span>瑙嗛</span>
+        </div>
+        <el-tooltip v-if="total" effect="dark" placement="top" content="蹇欑">
+          <div class="icon-css">
+            <i class="iconfont iconmanglu"></i>
+          </div>
+        </el-tooltip>
+        <el-tooltip v-else effect="dark" placement="top" content="绛夊緟">
+          <div class="icon-css">
+            <i class="iconfont icondengdai1"></i>
+          </div>
+        </el-tooltip>
+      </div>
+      <div style="height:86px;">
+        <el-divider class="divider-css" direction="vertical"></el-divider>
+      </div>
+      <div class="out-div-33">
+        <div class="txt-css">
+          <span>鍥剧墖</span>
+        </div>
+        <el-tooltip effect="dark" placement="top" content="绛夊緟">
+          <div class="icon-css">
+            <i class="iconfont icondengdai1"></i>
+          </div>
+        </el-tooltip>
+      </div>
+      <div style="height:86px;">
+        <el-divider class="divider-css" direction="vertical"></el-divider>
+      </div>
+      <div class="out-div-33">
+        <div class="txt-css">
+          <span>闊抽</span>
+        </div>
+        <el-tooltip effect="dark" placement="top" content="绛夊緟">
+          <div class="icon-css">
+            <i class="iconfont icondengdai1"></i>
+          </div>
+        </el-tooltip>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "BoardCard",
+  props: {
+    title: { type: String, default: "" },
+    total: { type: String, default: "" },
+    success: { type: String, default: "" },
+    warning: { type: String, default: "" }
+  }
+}
+</script>
+<style lang="scss">
+.board-card {
+  height: 120px;
+  width: 100%;
+  display: inline-block;
+  margin: 10px;
+  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;
+  }
+  hr {
+    background: rgb(226, 226, 226);
+    border: 0;
+    height: 1px;
+  }
+  i {
+    font-size: 20px;
+  }
+  .divider-css{
+    height: 100%;
+    margin: 0;
+  }
+  .el-divider--horizontal {
+    display: block;
+    height: 1px;
+    width: 100%;
+    margin: 3px 0;
+  }
+  .out-div-33{
+    width: 33%;
+    height: 100%;
+    .txt-css{
+      width: 100%;
+      height: 50%;
+      position: relative;
+      top: 30px;
+    }
+    .icon-css{
+      width: 100%;
+      height: 30%;
+      margin-top: 10px;
+      position: relative;
+    }
+  } 
+}
+</style>
\ No newline at end of file
diff --git a/src/components/subComponents/LocalVedioList.vue b/src/components/subComponents/LocalVedioList.vue
new file mode 100644
index 0000000..511f87c
--- /dev/null
+++ b/src/components/subComponents/LocalVedioList.vue
@@ -0,0 +1,129 @@
+<template>
+  <div id="realTimeList" class="out-div-rt">
+    <div class="top-menu">
+      <span class="iconfont iconku" style="font-size:20px;"></span>
+      <span style="font-size:14px; margin-left: 5px;font-weight: 600;">鏁版嵁鏍�</span>
+    </div>
+    <ul>
+      <li
+        v-for="(item,index) in DataStackPool.dirs"
+        :key="index"
+        @click="handleClick(item)"
+        :class="DataStackPool.selectedDir.id == item.id ? 'bg' : ''"
+      >
+        <!-- 鏂囦欢澶瑰浘鏍� -->
+        <span class="iconfont iconshipinwenjianjia-new folder" v-if="item.type === 1"></span>
+        <span class="iconfont icontupianwenjianjia-copy folder" v-else-if="item.type === 2"></span>
+        <span class="iconfont iconshipinwenjianjia1 folder" v-else-if="item.type === 3"></span>
+        <span class="iconfont iconwenjian folder" v-else></span>
+
+        <span class="folder-name">{{item.name}}</span>
+
+        <!-- 绠楁硶閰嶇疆涓嶅叏 -->
+        <i class="iconfont iconicon-test6 folder-status" v-if="item.status === 0"></i>
+        <!-- 姝e湪澶勭悊 -->
+        <i class="iconfont iconicon-test11 folder-status" v-else-if="item.status === 2"></i>
+        <!-- 绛夊緟澶勭悊 -->
+        <i class="iconfont iconicon-test5 folder-status" v-else-if="item.status === 1"></i>
+        <!-- 鏈煡鍘熷洜 -->
+        <i class="iconfont iconicon-test5 folder-status" v-else></i>
+        <!-- <i class="iconfont iconicon-test11 folder-status"></i> -->
+        <el-switch
+          size="mini"
+          style="float:right; margin:2px 5px;"
+          v-model="item.enable"
+          @change="switchEnable(item)"
+        ></el-switch>
+      </li>
+    </ul>
+  </div>
+</template>
+<script>
+import { switchDir } from "@/api/localVedio"
+
+export default {
+  name: 'localVedioList',
+  props: {
+    isMutl: {
+      type: Boolean,
+      default: true
+    }
+  },
+  data() {
+    return {
+      list: [],
+      checkedVedio: [],
+      isShow: true,
+      dateMill: new Date(),
+      showCheckBox: false,
+    }
+  },
+  methods: {
+    handleClick(item) {
+      this.DataStackPool.selectedDir = item;
+    },
+    switchEnable(item) {
+      switchDir({ enable: item.enable, id: item.id }).then(rsp => {
+        console.log(rsp)
+      })
+    }
+  }
+}
+</script>
+<style lang="scss">
+.out-div-rt {
+  width: 100%;
+  height: 100%;
+  .top-menu {
+    text-align: left;
+  }
+
+  .folder {
+    color: #3d68e1;
+    font-size: 20px;
+    float: left;
+    line-height: 25px;
+  }
+  .folder-name {
+    font-size: 14px;
+    margin-left: 5px;
+    float: left;
+    line-height: 27px;
+  }
+  .folder-status {
+    color: #3d68e1;
+    font-size: 18px;
+    float: right;
+    line-height: 25px;
+  }
+
+  ul {
+    margin: 10px 25px;
+  }
+  li {
+    width: 100%;
+    height: 25px;
+    margin-top: 2px;
+    cursor: pointer;
+    .el-switch__core {
+      width: 27px !important;
+      height: 14px;
+    }
+    .el-switch__core:after {
+      width: 10px;
+      height: 10px;
+    }
+    .el-switch.is-checked .el-switch__core::after {
+      left: 100%;
+      margin-left: -11px;
+    }
+  }
+}
+
+.bg {
+  background: #e1e1e1;
+}
+.clickStatus {
+  background: #e1e1e1;
+}
+</style>
diff --git a/src/components/subComponents/ModelCard.vue b/src/components/subComponents/ModelCard.vue
new file mode 100644
index 0000000..febadaf
--- /dev/null
+++ b/src/components/subComponents/ModelCard.vue
@@ -0,0 +1,583 @@
+<template>
+  <div class="model-card-box" :style="`height:${height};width:${width};`">
+    <el-tabs style="height: 100%;" @before-leave="changeTabs" v-model="VideoPhotoData.activeName">
+      <el-tab-pane label="澶у浘" name="pic">
+        <div
+          class="model-card-box-left"
+          :style="data.targetInfo !== null && data.targetInfo[0].picSmUrl !== ''
+          ? 'width: 65%;padding: 5px;box-sizing: border-box'
+          : 'width: 100%;padding: 5px;box-sizing: border-box'"
+        >
+          <div class="img-box">
+            <p class="img-box-title">
+              <b>鍏ㄦ櫙鍥�</b>
+            </p>
+            <img-down
+              v-if="data.targetInfo !== null && data.targetInfo[0].picSmUrl !== ''"
+              :url="data.picMaxUrl[0]"
+            ></img-down>
+            <!-- 浜鸿劯绫诲瀷 -->
+            <img-down
+              v-else-if="(data.targetInfo == null || data.targetInfo[0].picSmUrl == '') && data.picMaxUrl.length == 1"
+              :url="data.picMaxUrl[0]"
+            ></img-down>
+            <!-- 鏅�歽olo绫� -->
+            <el-carousel
+              v-else-if="(data.targetInfo == null || data.targetInfo[0].picSmUrl == '') && data.picMaxUrl.length > 1"
+              trigger="click"
+              height="100%"
+              :autoplay="false"
+            >
+              <el-carousel-item v-for="(item, index) in data.picMaxUrl" :key="index">
+                <img-down :url="item"></img-down>
+              </el-carousel-item>
+            </el-carousel>
+            <!-- 鎸佺画鏃堕棿yolo绫� -->
+            <div
+              class="describe"
+              v-if="data.targetInfo == null || data.targetInfo[0].picSmUrl == ''"
+            >
+              <p>
+                <span class="fontStyleForModel">{{ data.picDate }}</span>
+              </p>
+              <p>
+                <span class="fontStyleForModel">{{ data.cameraAddr }}</span>
+              </p>
+              <p style="width:100%">
+                <span v-for="(item,index) in data.alarmRules" :key="index+'rule'">
+                  <span class="fontStyleForModel">{{data.taskName}}</span>&nbsp;&nbsp;
+                  <span
+                    v-if="item.alarmLevel !== '鎾ら槻'"
+                    class="fontStyleForModel"
+                  >{{item.alarmLevel}}</span>&nbsp;
+                  <span v-if="item.isLink" class="fontStyleForModel">鑱斿姩浠诲姟</span>
+                  <span v-if="index < data.alarmRules.length-1">/&nbsp;</span>
+                </span>
+              </p>
+            </div>
+            <!-- yolo绫诲ぇ鍥� -->
+            <div class="describeBigImage" v-else>
+              <p>
+                <span class="fontStyleForModel">{{ data.picDate }}</span>
+              </p>
+              <p>
+                <span class="fontStyleForModel">{{ data.cameraAddr }}</span>
+              </p>
+              <p style="width:100%">
+                <span v-for="(item,index) in data.alarmRules" :key="index+'rule'">
+                  <span class="fontStyleForModel">{{data.taskName}}</span>&nbsp;&nbsp;
+                  <span
+                    v-if="item.alarmLevel !== '鎾ら槻'"
+                    class="fontStyleForModel"
+                  >{{item.alarmLevel}}</span>&nbsp;
+                  <span v-if="item.isLink" class="fontStyleForModel">鑱斿姩浠诲姟</span>
+                  <span v-if="index < data.alarmRules.length-1">/&nbsp;</span>
+                </span>
+              </p>
+              <p style="width:100%">
+                <span class="fontStyleForModel">{{data.showLabels}}</span>
+              </p>
+            </div>
+            <!-- 浜鸿劯绫诲ぇ鍥�  -->
+          </div>
+        </div>
+        <div
+          v-if="data.targetInfo && data.targetInfo !== null && data.targetInfo[0].picSmUrl !== ''"
+          class="model-card-box-right"
+          :style="data.targetInfo && data.targetInfo !== null && data.targetInfo[0].picSmUrl !== ''
+          ? 'width: 35%;box-sizing: border-box;'
+          : ''"
+        >
+          <p class="img-box-title">
+            <b>鎶撴媿鍥�</b>
+          </p>
+          <!-- 宸﹀彸涓ゅ紶鐨勪汉鑴稿姣旀ā寮� -->
+          <div class="img-box" v-if="data.baseInfo && data.baseInfo.length >= 1" ref="picSmBox">
+            <div class="card-img-box-compear-left">
+              <!-- <img :src="'/httpImage/'+data.targetInfo[0].picSmUrl" ref="picSm" /> -->
+              <img-down :url="data.targetInfo[0].picSmUrl" :isPreview="false"></img-down>
+            </div>
+            <el-carousel
+              @change="changeInitialIndex"
+              :initial-index="initialIndex"
+              :autoplay="false"
+              indicator-position="none"
+              :arrow="data.baseInfo.length > 1 ? 'always' : 'never'"
+              v-if="data.baseInfo[0].targetPicUrl != ''"
+              class="card-img-box-compear-right"
+            >
+              <el-carousel-item v-for="(item, index) in data.baseInfo" :key="index">
+                <!-- <img :src="'/httpImage/'+item.targetPicUrl" /> -->
+                <img-down :url="item.targetPicUrl" :isPreview="false"></img-down>
+              </el-carousel-item>
+            </el-carousel>
+            <div
+              class="img-compareScore"
+              v-if="data.baseInfo[0].targetPicUrl != ''"
+              :style="
+                data.baseInfo[initialIndex].bwType === '1'
+                  ? `background: red;`
+                  : `background: green;`
+              "
+            >
+              <b>{{ data.baseInfo[initialIndex].compareScore | percentage }}</b>
+            </div>
+          </div>
+          <!-- 娌℃湁姣斿鐨勪汉鑴歌瘑鍒ā寮� -->
+          <div class="img-box" v-if="!data.baseInfo && data.targetInfo[0].picSmUrl !== '' ">
+            <div class="card-img-box-compear-left" style="width:60%;margin-top:5px">
+              <!-- <img :src="'/httpImage/'+data.targetInfo[0].picSmUrl" /> -->
+              <img-down :url="data.targetInfo[0].picSmUrl" :isPreview="false"></img-down>
+            </div>
+          </div>
+          <div class="baseInfo" v-if="data.baseInfo && data.baseInfo[0].targetPicUrl != ''">
+            <div class="baseInfo_left">
+              <p>
+                <span class="labelInfo">搴曞簱</span>
+              </p>
+              <p>
+                <span class="labelInfo">濮撳悕</span>
+              </p>
+              <p>
+                <span class="labelInfo">鎬у埆</span>
+              </p>
+              <p>
+                <span class="labelInfo">韬唤璇佸彿</span>
+              </p>
+              <p>
+                <span class="labelInfo">鎵嬫満鍙�</span>
+              </p>
+              <p>
+                <span class="labelInfo">浜哄憳绛夌骇</span>
+              </p>
+            </div>
+            <div class="baseInfo_right">
+              <p class="valueInfo">
+                <span
+                  :title="data.baseInfo[initialIndex].tableName"
+                >{{ data.baseInfo[initialIndex].tableName }}</span>
+              </p>
+              <p class="valueInfo">
+                <span
+                  :title="data.baseInfo[initialIndex].targetName"
+                >{{ data.baseInfo[initialIndex].targetName }}</span>
+              </p>
+              <p class="valueInfo">
+                <span
+                  :title="data.baseInfo[initialIndex].labels.split('/')[1]"
+                >{{ data.baseInfo[initialIndex].labels.split("/")[1] }}</span>
+              </p>
+              <p class="valueInfo">
+                <span
+                  :title="data.baseInfo[initialIndex].labels.split('/')[2]"
+                >{{ data.baseInfo[initialIndex].labels.split("/")[2] }}</span>
+              </p>
+              <p class="valueInfo">
+                <span
+                  :title="data.baseInfo[initialIndex].labels.split('/')[0]"
+                >{{ data.baseInfo[initialIndex].labels.split("/")[0] }}</span>
+              </p>
+              <p class="valueInfo">
+                <span
+                  :title="data.baseInfo[initialIndex].monitorLevel"
+                >{{ data.baseInfo[initialIndex].monitorLevel }}</span>
+              </p>
+            </div>
+          </div>
+        </div>
+      </el-tab-pane>
+      <el-tab-pane label="瑙嗛" name="video" class="video-tabs">
+        <div
+          class="model-card-box-left"
+          :style="data.targetInfo !== null && data.targetInfo[0].picSmUrl !== ''
+          ? 'width: 65%;padding: 5px;box-sizing: border-box'
+          : 'width: 70%;padding: 5px;box-sizing: border-box;margin-left:15%'"
+        >
+          <div class="img-box">
+            <video
+              :src="'/httpImage/' + data.videoUrl"
+              controls
+              style="margin-top: 12px;"
+            >鎮ㄧ殑娴忚鍣ㄤ笉鏀寔 video 鏍囩銆�</video>
+          </div>
+          <!-- <div class="merge">
+            <el-button type="primary" @click="mergeVideo">鍚堝苟瑙嗛</el-button>
+            <a name="download" @click="downloadfile">涓嬭浇</a>
+            <a href="/httpImage/192.168.20.112:6081/31,02c86c199cd9b1" download="panlei.mp4">涓嬭浇2</a>
+          </div>-->
+        </div>
+        <div
+          v-if="data.targetInfo !== null && data.targetInfo[0].picSmUrl !== ''"
+          class="model-card-box-right"
+          :style="data.targetInfo !== null &&  data.targetInfo[0].picSmUrl !== ''
+          ? 'width: 35%;box-sizing: border-box;'
+          : ''"
+        >
+          <p class="img-box-title">
+            <b>鎶撴媿鍥�</b>
+          </p>
+          <!-- 宸﹀彸涓ゅ紶鐨勪汉鑴稿姣旀ā寮� -->
+          <div class="img-box" v-if="data.baseInfo && data.baseInfo.length >= 1" ref="picSmBox">
+            <div class="card-img-box-compear-left">
+              <img-down :url="data.targetInfo[0].picSmUrl" :isPreview="false"></img-down>
+            </div>
+            <el-carousel
+              @change="changeInitialIndex"
+              :initial-index="initialIndex"
+              :autoplay="false"
+              indicator-position="none"
+              v-if="data.baseInfo[0].targetPicUrl != ''"
+              class="card-img-box-compear-right"
+              :arrow="data.baseInfo.length > 1 ? 'always' : 'never'"
+            >
+              <el-carousel-item v-for="(item, index) in data.baseInfo" :key="index">
+                <!-- <img :src="'/httpImage/'+item.targetPicUrl" /> -->
+                <img-down :url="item.targetPicUrl" :isPreview="false"></img-down>
+              </el-carousel-item>
+            </el-carousel>
+            <div
+              class="img-compareScore"
+              v-if="data.baseInfo[0].targetPicUrl != ''"
+              :style="
+                data.baseInfo[initialIndex].bwType === '1'
+                  ? `background: red;`
+                  : `background: green;`
+              "
+            >
+              <b>{{ data.baseInfo[initialIndex].compareScore | percentage }}</b>
+            </div>
+          </div>
+          <!-- 娌℃湁姣斿鐨勪汉鑴歌瘑鍒ā寮� -->
+          <div class="img-box" v-if="!data.baseInfo && data.picMaxUrl ">
+            <div class="card-img-box-compear-left" style="width:60%;margin-top:5px">
+              <!-- <img :src="'/httpImage/'+data.targetInfo[0].picSmUrl" /> -->
+              <img-down :url="data.targetInfo[0].picSmUrl" :isPreview="false"></img-down>
+            </div>
+          </div>
+          <div class="baseInfo" v-if="data.baseInfo && data.baseInfo[0].targetPicUrl != ''">
+            <div class="baseInfo_left">
+              <p>
+                <span class="labelInfo">搴曞簱</span>
+              </p>
+              <p>
+                <span class="labelInfo">濮撳悕</span>
+              </p>
+              <p>
+                <span class="labelInfo">鎬у埆</span>
+              </p>
+              <p>
+                <span class="labelInfo">韬唤璇佸彿</span>
+              </p>
+              <p>
+                <span class="labelInfo">鎵嬫満鍙�</span>
+              </p>
+              <p>
+                <span class="labelInfo">浜哄憳绛夌骇</span>
+              </p>
+            </div>
+            <div class="baseInfo_right">
+              <p class="valueInfo">
+                <span
+                  :title="data.baseInfo[initialIndex].tableName"
+                >{{ data.baseInfo[initialIndex].tableName }}</span>
+              </p>
+              <p class="valueInfo">
+                <span
+                  :title="data.baseInfo[initialIndex].targetName"
+                >{{ data.baseInfo[initialIndex].targetName }}</span>
+              </p>
+              <p class="valueInfo">
+                <span
+                  :title="data.baseInfo[initialIndex].labels.split('/')[1]"
+                >{{ data.baseInfo[initialIndex].labels.split("/")[1] }}</span>
+              </p>
+              <p class="valueInfo">
+                <span
+                  :title="data.baseInfo[initialIndex].labels.split('/')[2]"
+                >{{ data.baseInfo[initialIndex].labels.split("/")[2] }}</span>
+              </p>
+              <p class="valueInfo">
+                <span
+                  :title="data.baseInfo[initialIndex].labels.split('/')[0]"
+                >{{ data.baseInfo[initialIndex].labels.split("/")[0] }}</span>
+              </p>
+              <p class="valueInfo">
+                <span
+                  :title="data.baseInfo[initialIndex].monitorLevel"
+                >{{ data.baseInfo[initialIndex].monitorLevel }}</span>
+              </p>
+            </div>
+          </div>
+        </div>
+      </el-tab-pane>
+    </el-tabs>
+  </div>
+</template>
+<script>
+/* eslint-disable */
+import CameraPlayer from "@/components/player";
+import imgDown from "@/components/subComponents/imgDown"
+export default {
+  components: {
+    CameraPlayer,
+    imgDown
+  },
+  props: {
+    height: {
+      type: String,
+      default: "100%"
+    },
+    width: {
+      type: String,
+      default: "100%"
+    },
+    data: ""
+  },
+  filters: {
+    percentage(score) {
+      return score.toFixed(2) + "%"
+    }
+  },
+  mounted() {
+    this.VideoPhotoData.activeName = "pic"
+  },
+  data() {
+    return {
+      initialIndex: 0,
+    };
+  },
+  methods: {
+    changeTabs(activeName, oldActiveName) {
+      console.log(activeName, oldActiveName);
+    },
+    changeInitialIndex(index) {
+      this.initialIndex = index;
+    },
+    downloadfile() {
+      this.filecontent = "this is my file content";
+      let a = document.createElement('a');
+
+      a.href = "data:text/json;charset=utf-8," + this.filecontent;
+      // a.url = "http://192.168.20.112:6154/93,02c5aea4fc614e";
+      a.download = "video.mp4";
+      a.click();
+    }
+  },
+};
+</script>
+<style lang="scss">
+.fontStyleForModel {
+  font-family: PingFangSC-Medium;
+  font-size: 14px;
+  color: #222222;
+  font-weight: 600;
+  letter-spacing: 0.28px;
+}
+.model-card-box {
+  box-sizing: border-box;
+  padding: 5px;
+  .el-tabs {
+    .el-tabs__item {
+      font-size: 16px !important;
+    }
+  }
+  .el-tabs__content {
+    height: calc(100% - 55px);
+    .el-tab-pane {
+      height: 100%;
+    }
+    .model-card-box-left,
+    .model-card-box-right {
+      height: 100%;
+      float: left;
+      .baseInfo {
+        margin-top: 5px;
+        text-align: left;
+        .baseInfo_left {
+          float: left;
+          width: 30%;
+          text-align: left;
+          font-family: PingFangSC-Regular;
+          font-size: 12px;
+          color: #999999;
+          letter-spacing: 0.28px;
+        }
+        .baseInfo_right {
+          float: left;
+          width: 70%;
+          text-align: left;
+          font-family: PingFangSC-Regular;
+          font-size: 12px;
+          color: #101010;
+          letter-spacing: 0.28px;
+          line-height: 20px;
+          .valueInfo {
+            overflow: hidden;
+            text-overflow: ellipsis;
+            white-space: nowrap;
+            max-width: 130px;
+          }
+        }
+        p {
+          line-height: 20px;
+        }
+      }
+    }
+    .model-card-box-left {
+      width: 60%;
+      .img-box {
+        .el-carousel__arrow {
+          bottom: inherit !important;
+          top: 50% !important;
+        }
+        .el-carousel__arrow--right {
+          right: 10px !important;
+        }
+        .el-carousel__arrow--left {
+          left: 10px !important;
+        }
+        .img-box-title {
+          text-align: left;
+        }
+        height: calc(100% - 100px);
+        .el-carousel {
+          width: 100%;
+          height: 100%;
+          float: left;
+        }
+        img {
+          float: left;
+          width: 100%;
+          height: 100%;
+          object-fit: contain;
+        }
+        .describe {
+          width: 100%;
+          height: 50px;
+          float: left;
+          margin-left: 15%;
+          margin-top: 5px;
+          p {
+            b {
+              //color: #e43933;
+            }
+            width: 40%;
+            text-align: left;
+            float: left;
+            margin: 4px 0px;
+          }
+        }
+        .describeBigImage {
+          width: 100%;
+          height: 50px;
+          float: left;
+          margin-top: 5px;
+          p {
+            b {
+              //color: #e43933;
+            }
+            width: 50%;
+            text-align: left;
+            float: left;
+            margin: 4px 0px;
+          }
+        }
+      }
+      .merge {
+        margin-top: 30px;
+        float: left;
+      }
+    }
+    .model-card-box-right {
+      padding-left: 5px;
+      box-sizing: border-box;
+      width: 40%;
+      overflow: auto;
+      height: 100%;
+      .img-box-title {
+        text-align: left;
+        margin: 5px;
+      }
+      .img-box {
+        height: 32%;
+        width: 100%;
+        position: relative;
+        .card-img-box-compear-left {
+          float: left;
+          width: 50%;
+          height: 100%;
+          img {
+            width: 100%;
+            height: 100%;
+            object-fit: contain;
+            //border: 1px solid rgb(92, 91, 91);
+            padding: 0px 4px;
+            box-sizing: border-box;
+            border-radius: 5px;
+          }
+        }
+        .card-img-box-compear-right {
+          float: right;
+          width: 50%;
+          height: 100%;
+          .el-carousel__container {
+            height: 100% !important;
+            .el-carousel__arrow {
+              top: 50% !important;
+            }
+            .el-carousel__arrow {
+              height: 20px;
+              width: 20px;
+            }
+            .el-carousel__arrow--right {
+              right: 10px !important;
+            }
+            .el-carousel__arrow--left {
+              left: 10px !important;
+            }
+          }
+          img {
+            width: 100%;
+            height: 100%;
+            object-fit: contain;
+            //border: 1px solid rgb(92, 91, 91);
+            padding: 0px 4px;
+            box-sizing: border-box;
+            border-left: none;
+            border-radius: 5px;
+          }
+        }
+        .img-compareScore {
+          bottom: 0px;
+          width: 60px;
+          height: 20px;
+          line-height: 20px;
+          background-color: #e43933;
+          position: absolute;
+          left: calc(50% - 30px);
+          border-top-right-radius: 5px;
+          border-top-left-radius: 5px;
+          color: #ebeef5;
+          font-weight: 700;
+          z-index: 2;
+        }
+        .imgs {
+          width: 50%;
+          height: 50%;
+          float: left;
+          display: flex;
+          justify-content: center;
+          align-items: center;
+          overflow: hidden;
+          padding-right: 5px;
+          box-sizing: border-box;
+          background-color: #ebeef5;
+          img {
+            width: 100%;
+          }
+        }
+      }
+    }
+  }
+}
+</style>
diff --git a/src/components/subComponents/MultiRangeSlider.vue b/src/components/subComponents/MultiRangeSlider.vue
new file mode 100644
index 0000000..5b8c0ac
--- /dev/null
+++ b/src/components/subComponents/MultiRangeSlider.vue
@@ -0,0 +1,761 @@
+<template>
+  <div class="timeRangeSliderBox">
+    <canvas :id="mainId" :ref="mainId" width="700px" height="260px">鎶辨瓑,鎮ㄧ殑娴忚鍣ㄤ笉鏀寔canvas!璇锋洿鎹㈡祻瑙堝櫒</canvas>
+    <canvas
+      :id="`${mainId}Dummy`"
+      :ref="`${mainId}Dummy`"
+      width="700px"
+      height="260px"
+      @dblclick="handlerClick"
+      @mouseout="mouseout($event)"
+      @mousedown="mouseDown($event)"
+      @mousemove="mousemove($event)"
+      @mouseup="mouseup($event)"
+    >鎶辨瓑,鎮ㄧ殑娴忚鍣ㄤ笉鏀寔canvas!璇锋洿鎹㈡祻瑙堝櫒</canvas>
+    <div class="popup-box" :style="`top:${popPos.y + 10}px;left:${popPos.x - 70}px`" v-if="isPopup">
+      <div>
+        <b>寮�濮嬫椂闂�:</b>
+        <input
+          v-model="changeTime.startHour"
+          :min="0"
+          :max="changeTime.endHour"
+          type="number"
+          placeholder="鏃�"
+        />
+        <b>:</b>
+        <input v-model="changeTime.startMin" type="number" placeholder="鍒�" />
+      </div>
+      <div>
+        <b>缁撴潫鏃堕棿:</b>
+        <input
+          v-model="changeTime.endHour"
+          :min="changeTime.startHour"
+          :max="24"
+          type="number"
+          placeholder="鏃�"
+        />
+        <b>:</b>
+        <input v-model="changeTime.endMin" type="number" placeholder="鍒�" />
+      </div>
+      <div style="margin-top:5px;">
+        <el-button @click="deleteRange">鍒犻櫎</el-button>
+        <el-button @click="cancalPop">鍙栨秷</el-button>
+        <el-button @click="timeAck">纭畾</el-button>
+      </div>
+    </div>
+  </div>
+</template>
+ 
+<script>
+export default {
+  mounted() {
+
+    this.initMain();
+    this.initMainDummy();
+  },
+  data() {
+    return {
+      x: "",
+      y: "",
+      isMouseDown: false,
+      isCreate: false,
+      isResizeLeft: false,
+      isResizeRight: false,
+      actRange: "",
+      actGrid: "",
+      rangeArr: [],
+      gridArr: [],
+      currentPointX: "",
+      actRangeIndex: "",
+      noLimit: 0,
+      isPopup: false,
+      popPos: {
+        x: "",
+        y: ""
+      },
+      changeTime: {
+        startHour: "",
+        startMin: "",
+        endHour: "",
+        endMin: ""
+      },
+      rangeArrBackup: "",
+      styleClass: {
+        weekTextColor: "",
+        minutePerColor: "#cdcdcd",
+        minutePerTextColor: "#808080"
+      }
+    };
+  },
+  props: {
+    timeData: {
+      default: () => { },
+      type: Array
+    },
+    mainId: {
+      type: String,
+      default: ""
+    },
+    itemId: {
+      type: String,
+      default: ""
+    },
+    itemName: {
+      type: String,
+      default: ""
+    },
+    edit: {
+      type: Boolean,
+      default: false
+    }
+  },
+  watch: {
+    changeTime: {
+      handler(newVal, oldVal) {
+        if (newVal.startHour >= 24) {
+          newVal.startHour = 24;
+          newVal.startMin = 0;
+        }
+
+        if (newVal.endHour >= 24) {
+          newVal.endHour = 24;
+          newVal.endMin = 0;
+        }
+
+        if (newVal.startHour < 0) {
+          newVal.startHour = 0;
+        }
+
+        if (newVal.endHour < 0) {
+          newVal.endHour = newVal.startHour;
+        }
+
+        if (newVal.startMin > 60) {
+          newVal.startMin = 0
+        }
+        if (newVal.startMin < 0) {
+          newVal.startMin = 60
+        }
+        if (newVal.endMin > 60) {
+          newVal.endMin = 0
+        }
+        if (newVal.endMin < 0) {
+          newVal.endMin = 0
+        }
+
+        if (parseInt(newVal.startHour) == parseInt(newVal.endHour) && parseInt(newVal.startMin) > parseInt(newVal.endMin)) {
+          newVal.startMin = 0
+        }
+      },
+      deep: true
+    }
+  },
+  methods: {
+    timeAck() {
+      let rangeInfo = this.actRange.rangeInfo;
+      let perH = 600 / 24;
+      let perM = perH / 60;
+
+      let tempRangeInfo = this.rangeArr[rangeInfo.ownedIndex].rangeInfo;
+      tempRangeInfo.maxX = this.changeTime.endHour * perH + this.changeTime.endMin * perM + 50.5;
+      tempRangeInfo.minX = this.changeTime.startHour * perH + this.changeTime.startMin * perM + 50.5;
+      tempRangeInfo.width = tempRangeInfo.maxX - tempRangeInfo.minX;
+      for (let i = 0; i < this.gridArr.length; i++) {
+        let num = 0;
+        for (let j = 0; j < this.rangeArr.length; j++) {
+          if (this.gridArr[i].posIndex === this.rangeArr[j].rangeInfo.posIndex) {
+            this.gridArr[i].rangeList.splice(num, 1, this.rangeArr[j].rangeInfo);
+            num++;
+          }
+        }
+      }
+      this.cancalPop();
+      this.redraw(false);
+      this.export();
+    },
+    deleteRange() {
+      this.rangeArr.splice(this.actRangeIndex, 1);
+      for (let i = 0; i < this.rangeArr.length; i++) {
+        this.rangeArr[i].rangeInfo.ownedIndex = i;
+      }
+      for (let i = 0; i < this.gridArr.length; i++) {
+        let num = 0;
+        for (let j = 0; j < this.rangeArr.length; j++) {
+          if (
+            this.gridArr[i].posIndex === this.rangeArr[j].rangeInfo.posIndex
+          ) {
+            this.gridArr[i].rangeList.splice(
+              num,
+              1,
+              this.rangeArr[j].rangeInfo
+            );
+            num++;
+          }
+        }
+      }
+      this.cancalPop();
+      this.redraw(false);
+      this.export();
+    },
+    getPopTime() {
+      let rangeInfo = this.actRange.rangeInfo;
+      if (!rangeInfo) {
+        return false;
+      }
+      let hourStart = parseInt((rangeInfo.minX - 50.5) / (600 / 24));
+      let minutetStart = Math.round(
+        ((rangeInfo.minX - 50.5) % (600 / 24)) / (600 / 24 / 60)
+      );
+      let hourEnd = parseInt((rangeInfo.maxX - 50.5) / (600 / 24));
+      let minuteEnd = Math.round(
+        ((rangeInfo.maxX - 50.5) % (600 / 24)) / (600 / 24 / 60)
+      );
+      minuteEnd = minuteEnd < 10 ? "0" + minuteEnd : minuteEnd;
+      this.changeTime.startHour = hourStart < 10 ? "0" + hourStart : hourStart;
+      this.changeTime.startMin = minutetStart === 60 ? "00" : minutetStart;
+      this.changeTime.endHour = hourEnd < 10 ? "0" + hourEnd : hourEnd;
+      this.changeTime.endMin = minuteEnd === 60 ? "00" : minuteEnd;
+      return true;
+    },
+    cancalPop() {
+      this.isPopup = false;
+      this.actRange = "";
+      this.actGrid = "";
+      this.actRangeIndex = "";
+    },
+    handlerClick() {
+      if (this.getPopTime()) {
+        this.isPopup = true;
+        this.popPos.x = Number(JSON.stringify(this.x));
+        this.popPos.y = Number(JSON.stringify(this.y >= 180 ? 170 : this.y));
+      }
+    },
+    mouseout(e) {
+      this.isMouseDown = false;
+      this.isCreate = false;
+      this.noLimit = 0;
+    },
+    mouseup(e) {
+      this.isMouseDown = false;
+      this.isCreate = false;
+      // this.actRange = ''
+      // this.actGrid = ''
+      // this.actRangeIndex = ''
+      this.noLimit = 0;
+      if (this.rangeArrBackup !== JSON.stringify(this.rangeArr)) {
+        this.rangeArrBackup = JSON.stringify(this.rangeArr);
+        this.export();
+      }
+
+      this.redraw(false);
+    },
+    mouseDown(e) {
+      this.isPopup = false;
+      this.isMouseDown = true;
+      this.currentPointX = e.offsetX;
+      this.noLimit++;
+      for (let i = 0; i < this.rangeArr.length; i++) {
+        let rangeItem = this.rangeArr[i].rangeInfo;
+        if (
+          this.x > rangeItem.minX &&
+          this.x < rangeItem.maxX &&
+          this.y > rangeItem.minY &&
+          this.y < rangeItem.maxY
+        ) {
+          this.actRange = this.rangeArr[i];
+          this.actRangeIndex = i;
+          return;
+        }
+      }
+      for (let i = 0; i < this.gridArr.length; i++) {
+        if (
+          this.x > this.gridArr[i].minX &&
+          this.x < this.gridArr[i].maxX &&
+          this.y > this.gridArr[i].minY &&
+          this.y < this.gridArr[i].maxY
+        ) {
+          this.actGrid = this.gridArr[i];
+          return;
+        }
+      }
+    },
+    mousemove(e) {
+      if (!this.edit) {
+        return;
+      }
+
+      if (this.isPopup) {
+        return;
+      }
+      // let canvas = document.getElementById(`${this.mainId}Dummy`);
+      let canvas = this.$refs[`${this.mainId}Dummy`];
+      let ctx = canvas.getContext("2d");
+      this.x = e.offsetX;
+      this.y = e.offsetY;
+      if (
+        this.actRange &&
+        this.isMouseDown &&
+        !this.isCreate &&
+        !this.isResizeLeft &&
+        !this.isResizeRight
+      ) {
+        // console.log("move", this.actRange);
+        let diff = e.offsetX - this.currentPointX;
+        let tempMinxX = this.actRange.rangeInfo.minX + diff;
+        let limit = this.limit(this.actRange);
+        if (
+          tempMinxX <= limit.limitLeft ||
+          tempMinxX + this.actRange.rangeInfo.width >= limit.limitRight
+        ) {
+          return;
+        }
+        this.actRange.rangeInfo.minX = tempMinxX;
+        this.actRange.rangeInfo.maxX = tempMinxX + this.actRange.rangeInfo.width;
+        this.currentPointX = e.offsetX;
+        let tempRangeList = this.gridArr[this.actRange.rangeInfo.posIndex].rangeList;
+        this.redraw();
+        // console.log("move-ed");
+      } else if (
+        this.actGrid &&
+        this.isMouseDown &&
+        !this.isResizeLeft &&
+        !this.isResizeRight
+      ) {
+        // console.log("create");
+        if (this.isCreate) {
+          let limit = this.limit(this.actRange);
+          if (
+            this.actRange.rangeInfo.minX <= limit.limitLeft ||
+            this.actRange.rangeInfo.minX + this.actRange.rangeInfo.width >=
+            limit.limitRight
+          ) {
+            return;
+          }
+          let tempX
+          if (this.x < 50) {
+            tempX = 50
+          } else if (this.x > 650) {
+            tempX = 650
+          } else {
+            tempX = this.x
+          }
+          let temp = tempX - this.currentPointX > 0 ? true : false;
+          let newWith = 0;
+          if (temp) {
+            newWith = tempX - this.currentPointX;
+            this.actRange.rangeInfo.maxX = tempX;
+          } else {
+            newWith = this.currentPointX - tempX;
+            this.actRange.rangeInfo.maxX = this.currentPointX;
+            this.actRange.rangeInfo.minX = tempX;
+          }
+          this.actRange.rangeInfo.width = newWith;
+          this.redraw();
+          return;
+        }
+        let tempRangeList = this.actGrid.rangeList;
+        if (tempRangeList) {
+          let rangeObj = {
+            end: "",
+            start: "",
+            rangeInfo: {
+              minX: this.currentPointX,
+              minY: this.actGrid.minY,
+              maxX: this.currentPointX + 10,
+              maxY: this.actGrid.maxY,
+              width: 10,
+              height: 14,
+              posIndex: this.actGrid.posIndex,
+              ownedIndex: 0
+            }
+          };
+          let actRangeIndex = 0;
+          for (let i = 0; i < tempRangeList.length; i++) {
+            if (this.currentPointX > tempRangeList[i].minX) {
+              actRangeIndex++;
+            }
+          }
+          this.actRangeIndex = actRangeIndex;
+          this.rangeArr.splice(this.actRangeIndex, 0, rangeObj);
+          for (let i = 0; i < this.rangeArr.length; i++) {
+            this.rangeArr[i].rangeInfo.ownedIndex = i;
+          }
+          for (let i = 0; i < this.gridArr.length; i++) {
+            let num = 0;
+            for (let j = 0; j < this.rangeArr.length; j++) {
+              if (
+                this.gridArr[i].posIndex === this.rangeArr[j].rangeInfo.posIndex
+              ) {
+                this.gridArr[i].rangeList.splice(
+                  num,
+                  1,
+                  this.rangeArr[j].rangeInfo
+                );
+                num++;
+              }
+            }
+          }
+          this.actGrid.rangeList = this.gridArr[
+            this.actGrid.posIndex
+          ].rangeList;
+          this.actRange = this.rangeArr[this.actRangeIndex];
+          this.isCreate = true;
+        }
+      } else if (
+        this.isMouseDown &&
+        (this.isResizeLeft || this.isResizeRight) &&
+        this.actRange !== "" &&
+        this.actRangeIndex !== ""
+      ) {
+        // console.log("resize");
+        let limit = this.limit(this.actRange);
+        if (
+          (this.actRange.rangeInfo.minX <= limit.limitLeft ||
+            this.actRange.rangeInfo.minX + this.actRange.rangeInfo.width >=
+            limit.limitRight) &&
+          this.noLimit > 5
+        ) {
+          this.isResizeRight = false;
+          this.isResizeLeft = false;
+          this.actRange = "";
+          this.actRangeIndex = "";
+          return;
+        }
+        if (this.isResizeLeft) {
+          if (
+            this.x >
+            this.actRange.rangeInfo.width / 2 + this.actRange.rangeInfo.minX - 5
+          ) {
+            return;
+          }
+          this.actRange.rangeInfo.minX = this.x < 50 ? 50 : this.x;
+          this.actRange.rangeInfo.width = this.actRange.rangeInfo.maxX - this.x;
+          this.noLimit++;
+          this.redraw();
+          return;
+        } else if (this.isResizeRight) {
+          if (
+            this.x <
+            this.actRange.rangeInfo.width / 2 + this.actRange.rangeInfo.minX + 5
+          ) {
+            return;
+          }
+          this.actRange.rangeInfo.maxX = this.x > 650 ? 650 : this.x;
+          this.actRange.rangeInfo.width = this.actRange.rangeInfo.maxX - this.actRange.rangeInfo.minX;
+          this.noLimit++;
+          this.redraw();
+          return;
+        }
+      } else {
+        for (let i = 0; i < this.rangeArr.length; i++) {
+          let rangeItem = this.rangeArr[i].rangeInfo;
+          if (
+            this.x > rangeItem.minX &&
+            this.x < rangeItem.minX + 6 &&
+            this.y > rangeItem.minY &&
+            this.y < rangeItem.maxY
+          ) {
+            this.isResizeLeft = true;
+            document.documentElement.style.cursor = "col-resize";
+            this.actRange = this.rangeArr[i];
+            this.actRangeIndex = i;
+            return;
+          } else if (
+            this.x > rangeItem.maxX - 6 &&
+            this.x < rangeItem.maxX &&
+            this.y > rangeItem.minY &&
+            this.y < rangeItem.maxY
+          ) {
+            this.isResizeRight = true;
+            document.documentElement.style.cursor = "col-resize";
+            this.actRange = this.rangeArr[i];
+            this.actRangeIndex = i;
+            return;
+          } else {
+            this.isResizeRight = false;
+            this.isResizeLeft = false;
+            this.actRange = "";
+            this.actRangeIndex = "";
+            document.documentElement.style.cursor = "default";
+          }
+        }
+      }
+    },
+    limit(rangeObj) {
+      let before = this.rangeArr[this.actRangeIndex - 1];
+      let behind = this.rangeArr[this.actRangeIndex + 1];
+      let obj = {
+        limitLeft: 50,
+        limitRight: 650
+      };
+      if (before === undefined && behind === undefined) {
+        return obj;
+      }
+      if (before === undefined) {
+        obj.limitLeft = 50;
+        obj.limitRight =
+          behind.rangeInfo.posIndex === rangeObj.rangeInfo.posIndex
+            ? behind.rangeInfo.minX
+            : 650;
+        return obj;
+      } else if (behind === undefined) {
+        obj.limitLeft =
+          before.rangeInfo.posIndex === rangeObj.rangeInfo.posIndex
+            ? before.rangeInfo.maxX
+            : 50;
+        obj.limitRight = 650;
+        return obj;
+      }
+      if (
+        before.rangeInfo.posIndex === rangeObj.rangeInfo.posIndex &&
+        behind.rangeInfo.posIndex === rangeObj.rangeInfo.posIndex
+      ) {
+        obj.limitLeft = before.rangeInfo.maxX;
+        obj.limitRight = behind.rangeInfo.minX;
+      } else if (
+        before.rangeInfo.posIndex !== rangeObj.rangeInfo.posIndex &&
+        behind.rangeInfo.posIndex === rangeObj.rangeInfo.posIndex
+      ) {
+        obj.limitLeft = 50;
+        obj.limitRight = behind.rangeInfo.minX;
+      } else if (
+        before.rangeInfo.posIndex === rangeObj.rangeInfo.posIndex &&
+        behind.rangeInfo.posIndex !== rangeObj.rangeInfo.posIndex
+      ) {
+        obj.limitLeft = before.rangeInfo.maxX;
+        obj.limitRight = 650;
+      } else {
+        obj.limitLeft = 50;
+        obj.limitRight = 650;
+      }
+      return obj;
+    },
+    weekString(n) {
+      let base = "鏄熸湡";
+      switch (n) {
+        case 1:
+          return base + "涓�";
+        case 2:
+          return base + "浜�";
+        case 3:
+          return base + "涓�";
+        case 4:
+          return base + "鍥�";
+        case 5:
+          return base + "浜�";
+        case 6:
+          return base + "鍏�";
+        case 7:
+          return base + "鏃�";
+      }
+    },
+    initMain() {
+      // let canvas = document.getElementById(`${this.mainId}`);
+      let canvas = this.$refs[`${this.mainId}`];
+      let ctx = canvas.getContext("2d");
+      ctx.font = "12px Arial";
+      let height = 260;
+      let width = canvas.offsetWidth;
+      let per = height / 7;
+      for (let i = 0; i < 7; i++) {
+        // let weekText = `鏄熸湡${this.timeData[i].day}:`;
+        let weekText = this.weekString(this.timeData[i].day);
+        let mid = per * i + per / 2 + 6.5;
+        ctx.strokeStyle = this.styleClass.minutePerColor;
+        ctx.fillText(weekText, 10, mid);
+        let startX = 50.5;
+        let startY = mid - 10;
+        ctx.save();
+        ctx.strokeStyle = "#DCDFE6";
+        ctx.fillStyle = "#DCE9FF";
+        ctx.fillRect(startX, startY, 600, 14);
+        ctx.strokeRect(startX, startY, 600, 14);
+        ctx.restore();
+        let tempGrid = {
+          minX: startX,
+          minY: startY,
+          maxX: startX + 600,
+          maxY: startY + 14,
+          width: 600,
+          height: 14,
+          posIndex: i,
+          rangeList: []
+        };
+        this.gridArr.push(tempGrid);
+        let timePer = 600 / 24;
+        for (let j = 0; j < 25; j++) {
+          let x = startX + timePer * j;
+          let y = startY;
+          let delVar = j % 2 === 0 ? 6.5 : 3.5;
+          ctx.save();
+          ctx.moveTo(x, y - delVar);
+          ctx.lineTo(x, y);
+          ctx.stroke();
+          ctx.font = "10px Arial";
+          ctx.fillStyle = this.styleClass.minutePerTextColor;
+          ctx.fillText(j, x - (j > 9 ? 4.5 : 2.5), y - 8.5);
+          ctx.restore();
+        }
+      }
+    },
+    initMainDummy() {
+      let canvas = document.getElementById(`${this.mainId}Dummy`);
+      let ctx = canvas.getContext("2d");
+      let height = 260;
+      let startX = 50.5;
+      let per = height / 7;
+      let hourPer = 600 / 24;
+      let minutePer = hourPer / 60;
+      for (let i = 0; i < this.timeData.length; i++) {
+        let mid = per * i + per / 2 + 6.5;
+        let startY = mid - 10;
+        let rang = this.timeData[i].time_range;
+        for (let j = 0; j < rang.length; j++) {
+          let start = rang[j].start.split(":");
+          let end = rang[j].end.split(":");
+          let startRange =
+            hourPer * Number(start[0]) + minutePer * Number(start[1]);
+          let endRange = hourPer * Number(end[0]) + minutePer * Number(end[1]);
+          let diffRange = Math.abs(endRange - startRange);
+          let rectStartX =
+            (startRange > endRange ? endRange : startRange) + 50.5;
+          ctx.fillStyle = "#6B9EFF";
+          ctx.fillRect(rectStartX, startY, diffRange, 14);
+          let rangeInfo = {
+            minX: rectStartX,
+            minY: startY,
+            maxX: rectStartX + diffRange,
+            maxY: startY + 14,
+            width: diffRange,
+            height: 14,
+            posIndex: i,
+            ownedIndex: this.rangeArr.length
+          };
+          rang[j].rangeInfo = rangeInfo;
+          this.gridArr[i].rangeList.push(rangeInfo);
+          this.rangeArr.push(rang[j]);
+        }
+      }
+
+      this.rangeArrBackup = JSON.stringify(this.rangeArr);
+    },
+    redraw(onlyDraw = true) {
+      let canvas = document.getElementById(`${this.mainId}Dummy`);
+      let ctx = canvas.getContext("2d");
+      ctx.clearRect(0, 0, 700, 260);
+      if (onlyDraw) {
+        let rangeInfo = this.actRange.rangeInfo;
+        let hourStart = parseInt((rangeInfo.minX - 50) / (600 / 24));
+        let minutetStart = Math.round(
+          ((rangeInfo.minX - 50) % (600 / 24)) / (600 / 24 / 60)
+        );
+        let hourEnd = parseInt((rangeInfo.maxX - 50) / (600 / 24));
+        let minuteEnd = Math.round(
+          ((rangeInfo.maxX - 50) % (600 / 24)) / (600 / 24 / 60)
+        );
+        minuteEnd = minuteEnd < 10 ? "0" + minuteEnd : minuteEnd;
+        let textStart = `${hourStart < 10 ? "0" + hourStart : hourStart}:${
+          minutetStart === 60 ? "00" : minutetStart
+          }`;
+        let textEnd = `${hourEnd < 10 ? "0" + hourEnd : hourEnd}:${
+          minuteEnd === 60 ? "00" : minuteEnd
+          }`;
+        let startPointX = rangeInfo.minX - 14;
+        let startPointY = rangeInfo.maxY + 10;
+        let endPointX = rangeInfo.maxX - 13;
+        let endPointY = rangeInfo.maxY + 10;
+        ctx.fillStyle = "#303133";
+        ctx.fillText(textStart, startPointX, startPointY);
+        ctx.fillText(textEnd, endPointX, endPointY);
+      }
+      for (let i = 0; i < this.rangeArr.length; i++) {
+        ctx.fillStyle = "#6B9EFF";
+        ctx.fillRect(
+          this.rangeArr[i].rangeInfo.minX,
+          this.rangeArr[i].rangeInfo.minY,
+          this.rangeArr[i].rangeInfo.width,
+          this.rangeArr[i].rangeInfo.height
+        );
+      }
+    },
+    export() {
+      let timeRule = [];
+      for (let i = 0; i < 7; i++) {
+        timeRule.push({
+          day: i + 1,
+          time_range: (() => {
+            let range = [];
+            this.rangeArr.forEach(item => {
+              if (item.rangeInfo.posIndex === i) {
+                let rangeInfo = item.rangeInfo;
+                let hourStart = parseInt((rangeInfo.minX - 50.5) / (600 / 24));
+                let minutetStart = Math.round(
+                  ((rangeInfo.minX - 50.5) % (600 / 24)) / (600 / 24 / 60)
+                );
+                let hourEnd = parseInt((rangeInfo.maxX - 50.5) / (600 / 24));
+                let minuteEnd = Math.round(
+                  ((rangeInfo.maxX - 50.5) % (600 / 24)) / (600 / 24 / 60)
+                );
+                hourStart = hourStart < 10 ? "0" + hourStart : hourStart;
+                minutetStart =
+                  minutetStart < 10 ? "0" + minutetStart : minutetStart;
+                hourEnd = hourEnd < 10 ? "0" + hourEnd : hourEnd;
+                minuteEnd = minuteEnd < 10 ? "0" + minuteEnd : minuteEnd;
+                range.push({
+                  start: hourStart + ":" + minutetStart,
+                  end: hourEnd + ":" + minuteEnd
+                });
+              }
+            });
+            return range;
+          })()
+        });
+      }
+
+      let obj = {
+        id: this.itemId,
+        name: this.itemName,
+        time_rule: timeRule
+      };
+      this.$emit("range-update", obj);
+    }
+  }
+};
+</script>
+ 
+<style lang="scss">
+.timeRangeSliderBox {
+  width: 700px;
+  height: 260px;
+  text-align: left;
+  margin: 10px auto;
+  position: relative;
+  canvas {
+    position: absolute;
+    top: 0px;
+    left: 0px;
+    width: 700px;
+    height: 260px;
+  }
+  .popup-box {
+    width: 160px;
+    height: 80px;
+    background-color: rgba(0, 0, 0, 0.6);
+    border-radius: 5px;
+    position: relative;
+    padding: 5px;
+    box-sizing: border-box;
+    color: #fff;
+    input {
+      width: 33px;
+    }
+    div {
+      margin: 3px auto;
+      text-align: center;
+    }
+    button {
+      padding: 3px;
+    }
+  }
+}
+</style>
\ No newline at end of file
diff --git a/src/components/subComponents/ParticleNetwork.vue b/src/components/subComponents/ParticleNetwork.vue
new file mode 100644
index 0000000..1989781
--- /dev/null
+++ b/src/components/subComponents/ParticleNetwork.vue
@@ -0,0 +1,351 @@
+<template>
+  <div class="particle-network-animation" :style="`height:${height}px;width:${width}px`">
+    <div style="display:none">
+      <img ref="conf0" src="../../assets/img/login/0.png" />
+      <img ref="conf1" src="../../assets/img/login/1.png" />
+      <img ref="conf2" src="../../assets/img/login/2.png" />
+      <img ref="conf3" src="../../assets/img/login/3.png" />
+      <img ref="conf4" src="../../assets/img/login/4.png" />
+      <img ref="conf5" src="../../assets/img/login/5.png" />
+      <img ref="conf6" src="../../assets/img/login/6.png" />
+      <img ref="conf7" src="../../assets/img/login/7.png" />
+      <img ref="conf8" src="../../assets/img/login/8.png" />
+      <img ref="conf9" src="../../assets/img/login/9.png" />
+      <img ref="conf10" src="../../assets/img/login/10.png" />
+      <img ref="conf11" src="../../assets/img/login/11.png" />
+      <img ref="conf12" src="../../assets/img/login/12.png" />
+      <img ref="conf13" src="../../assets/img/login/13.png" />
+      <img ref="conf14" src="../../assets/img/login/14.png" />
+      <img ref="conf15" src="../../assets/img/login/15.png" />
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "particleNetwork",
+  data() {
+    return {
+      imgNumber: 0,
+      destoryed: false
+    };
+  },
+  props: {
+    height: {
+      type: Number,
+      default: 800
+    },
+    width: {
+      type: Number,
+      default: 1000
+    }
+  },
+  mounted() {
+    this.createCavas();
+  },
+  beforeDestroy() {
+    this.destoryed = true
+  },
+  methods: {
+    createCavas() {
+      let that = this;
+      var ParticleNetworkAnimation, PNA;
+      ParticleNetworkAnimation = PNA = function () { };
+
+      PNA.prototype.init = function (element) {
+        // this.$el = $(element);
+
+        this.container = element;
+        this.canvas = document.createElement("canvas");
+        this.sizeCanvas();
+        this.container.appendChild(this.canvas);
+        this.ctx = this.canvas.getContext("2d");
+        this.particleNetwork = new ParticleNetwork(this);
+
+        return this;
+      };
+
+      PNA.prototype.sizeCanvas = function () {
+        this.canvas.width = this.container.offsetWidth;
+        this.canvas.height = this.container.offsetHeight;
+      };
+
+      var Particle = function (parent, x, y) {
+        this.network = parent;
+        this.imgNumber = that.imgNumber++;
+        this.canvas = parent.canvas;
+        this.ctx = parent.ctx;
+        this.particleColor = returnRandomArrayitem(
+          this.network.options.particleColors
+        );
+        // 鎺у埗澶у皬
+        this.radius = getLimitedRandom(10, 30);
+        this.opacity = 0;
+        // this.x = x || Math.random() * this.canvas.width;
+        // this.y = y || Math.random() * this.canvas.height;
+
+        // 鎺у埗鍒濆鍧愭爣锛屼笉瑕佽秴鍑鸿寖鍥�
+        this.x = x || getLimitedRandom(50, this.canvas.width - 50);
+        this.y = y || getLimitedRandom(50, this.canvas.height - 50);
+
+        this.velocity = {
+          x: (Math.random() - 0.5) * parent.options.velocity,
+          y: (Math.random() - 0.5) * parent.options.velocity
+        };
+      };
+
+      Particle.prototype.update = function () {
+        if (this.opacity < 0.8) {
+          this.opacity += 0.01;
+        } else {
+          this.opacity = 0.8;
+        }
+        // 绉诲姩鍒拌竟缂樻椂鍙嶅悜
+        if (this.x > this.canvas.width - 50 || this.x < 50) {
+          this.velocity.x = -this.velocity.x;
+        }
+        if (this.y > this.canvas.height - 50 || this.y < 50) {
+          this.velocity.y = -this.velocity.y;
+        }
+
+        // 鏇存柊鍧愭爣
+        this.x += this.velocity.x;
+        this.y += this.velocity.y;
+      };
+
+      Particle.prototype.draw = function () {
+        // Draw particle
+        if (that.destoryed) {
+          return;
+        }
+        this.ctx.beginPath();
+        this.ctx.fillStyle = this.particleColor;
+        this.ctx.globalAlpha = this.opacity;
+        this.ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
+        this.ctx.fill();
+        var prop = this.radius;
+        // let imgOdr = parseInt(Math.random() * 16, 10);
+        var img = that.$refs["conf" + this.imgNumber];
+        // img.src = "../../assets/img/login/" + imgOdr + ".png";
+        this.ctx.drawImage(
+          img,
+          this.x - this.radius * 0.8,
+          this.y - this.radius * 0.8,
+          this.radius * 1.6,
+          this.radius * 1.6
+        );
+      };
+
+      var ParticleNetwork = function (parent) {
+        this.options = {
+          velocity: 1, // the higher the faster
+          density: 1500, // the lower the denser
+          netLineDistance: 300,
+          netLineColor: "#477bec",
+          particleColors: ["#7E8BFA"] // ['#6D4E5C', '#aaa', '#FFC458' ]
+        };
+        this.canvas = parent.canvas;
+        this.ctx = parent.ctx;
+
+        this.init();
+      };
+
+      ParticleNetwork.prototype.init = function () {
+        // Create particle objects
+        this.createParticles(true);
+
+        // Update canvas
+        this.animationFrame = requestAnimationFrame(this.update.bind(this));
+      };
+
+      ParticleNetwork.prototype.createParticles = function (isInitial) {
+        // Initialise / reset particles
+        var me = this;
+        this.particles = [];
+        // var quantity = this.canvas.width * this.canvas.height / this.options.density;
+        var quantity = 17;
+
+        if (isInitial) {
+          var counter = 0;
+          clearInterval(this.createIntervalId);
+          this.createIntervalId = setInterval(
+            function () {
+              if (counter < quantity - 1) {
+                // Create particle object
+                this.particles.push(new Particle(this));
+              } else {
+                clearInterval(me.createIntervalId);
+              }
+              counter++;
+            }.bind(this),
+            250
+          );
+        } else {
+          // Create particle objects
+          for (var i = 0; i < quantity; i++) {
+            this.particles.push(new Particle(this));
+          }
+        }
+      };
+
+      ParticleNetwork.prototype.destory = function (isInitial) {
+        clearInterval(this.createIntervalId);
+      };
+      ParticleNetwork.prototype.update = function () {
+        if (this.canvas) {
+          this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+          this.ctx.globalAlpha = 1;
+
+          // Draw connections
+          for (var i = 0; i < this.particles.length; i++) {
+            for (var j = this.particles.length - 1; j > i; j--) {
+              var distance,
+                p1 = this.particles[i],
+                p2 = this.particles[j];
+
+              // check very simply if the two points are even a candidate for further measurements
+              distance = Math.min(Math.abs(p1.x - p2.x), Math.abs(p1.y - p2.y));
+              if (distance > this.options.netLineDistance) {
+                continue;
+              }
+
+              // the two points seem close enough, now let's measure precisely
+              distance = Math.sqrt(
+                Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2)
+              );
+              if (distance > this.options.netLineDistance) {
+                continue;
+              }
+
+              this.ctx.beginPath();
+              this.ctx.strokeStyle = this.options.netLineColor;
+              this.ctx.globalAlpha =
+                ((this.options.netLineDistance - distance) /
+                  this.options.netLineDistance) *
+                p1.opacity *
+                p2.opacity;
+              this.ctx.lineWidth = 1.7;
+              this.ctx.moveTo(p1.x, p1.y);
+              this.ctx.lineTo(p2.x, p2.y);
+              this.ctx.stroke();
+            }
+          }
+
+          // Draw particles
+          for (var i = 0; i < this.particles.length; i++) {
+            this.particles[i].update();
+            this.particles[i].draw();
+          }
+
+          if (this.options.velocity !== 0) {
+            this.animationFrame = requestAnimationFrame(this.update.bind(this));
+          }
+        } else {
+          cancelAnimationFrame(this.animationFrame);
+        }
+      };
+
+      var getLimitedRandom = function (min, max, roundToInteger) {
+        var number = Math.random() * (max - min) + min;
+        if (roundToInteger) {
+          number = Math.round(number);
+        }
+        return number;
+      };
+
+      var returnRandomArrayitem = function (array) {
+        return array[Math.floor(Math.random() * array.length)];
+      };
+
+      var elm = document.getElementsByClassName(
+        "particle-network-animation"
+      )[0];
+
+      this.pna = new ParticleNetworkAnimation();
+      this.pna.init(elm);
+    }
+  }
+};
+</script>
+
+<style lang="scss">
+.particle-network-animation {
+  position: fixed;
+  top: 20%;
+  left: 0;
+  right: 0;
+  // background-color: #171717;
+}
+.particle-network-animation::before {
+  z-index: -3;
+  content: "";
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  background-size: cover;
+  opacity: 0.2;
+}
+
+.glow {
+  z-index: -2;
+  position: fixed;
+  top: 50%;
+  left: 50%;
+  background-image: radial-gradient(
+    circle closest-side,
+    rgba(255, 255, 255, 0.025),
+    transparent
+  );
+}
+
+.glow-1 {
+  width: 150vw;
+  height: 150vh;
+  margin-top: -75vh;
+  margin-left: -75vw;
+  animation: glow-1-move 25s linear infinite both;
+}
+
+@keyframes glow-1-move {
+  from {
+    transform: translate(-100%, 100%);
+  }
+  to {
+    transform: translate(100%, -100%);
+  }
+}
+.glow-2 {
+  width: 100vw;
+  height: 100vh;
+  margin-top: -50vh;
+  margin-left: -50vw;
+  animation: glow-2-move 25s linear 8.3333333333s infinite both;
+}
+
+@keyframes glow-2-move {
+  from {
+    transform: translate(-100%, 0%);
+  }
+  to {
+    transform: translate(100%, 100%);
+  }
+}
+.glow-3 {
+  width: 120vw;
+  height: 120vh;
+  margin-top: -60vh;
+  margin-left: -60vw;
+  animation: glow-3-move 25s linear 16.6666666667s infinite both;
+}
+
+@keyframes glow-3-move {
+  from {
+    transform: translate(100%, 100%);
+  }
+  to {
+    transform: translate(0%, -100%);
+  }
+}
+</style>
\ No newline at end of file
diff --git a/src/components/subComponents/RuleEditor.vue b/src/components/subComponents/RuleEditor.vue
new file mode 100644
index 0000000..2f54f55
--- /dev/null
+++ b/src/components/subComponents/RuleEditor.vue
@@ -0,0 +1,811 @@
+<template>
+  <div class="edit-rules-box">
+    <p style="padding: 0">
+      <b style="font-size: 14px; line-height: 28px;">绛栫暐閰嶇疆</b>
+      <span class="btn" @click="createRule" v-if="groupRules.length === 0">
+        <i class="iconfont iconhebingxingzhuang" style="font-size:16px"></i>
+        鏂板
+      </span>
+
+      <span class="btn" @click="cleanRule" v-if="groupRules.length > 0">
+        <i class="iconfont iconshanchu11" style="font-size:16px"></i>
+        娓呯┖
+      </span>
+    </p>
+    <div class="sub-task-rules-box">
+      <span class="task-blank" v-show="groupRules.length == 0 ">鏆傛棤瑙勫垯锛岃閫夋嫨鏂板瑙勫垯閰嶇疆</span>
+      <div style=" text-align: left;" v-for="(rule, index) in groupRules" :key="index">
+        <div style="margin-left:10px;margin-top: 4px;" v-show="index > 0">
+          <el-select v-model="rule.rule_with_pre" placeholder="骞跺垪鍏崇郴" size="mini">
+            <el-option
+              v-for="subitem in VideoManageData.Dictionary.RULECOMPUTEBETWEEN"
+              :key="subitem.id"
+              :label="subitem.name"
+              :value="subitem.value"
+              :title="subitem.name"
+            ></el-option>
+          </el-select>
+        </div>
+
+        <div style="margin-left:10px;">
+          <!-- 閫夋嫨鍖哄煙 -->
+          <el-select
+            v-model="rule.polygonObj"
+            v-if="!isTemplate"
+            value-key="polygonId"
+            placeholder="閫夋嫨鍖哄煙"
+            size="mini"
+            @change="selectPolygonOption(rule)"
+          >
+            <el-option
+              v-for="subitem in allPolygonData"
+              :key="subitem.id"
+              :label="subitem.name"
+              :value="subitem"
+              :title="subitem.name"
+            ></el-option>
+          </el-select>
+
+          <!-- 閫夋嫨绠楁硶 -->
+          <el-select
+            v-model="rule.sdkObj"
+            value-key="id"
+            placeholder="閫夋嫨绠楁硶"
+            size="mini"
+            @change="selectSDKOption(rule, true)"
+          >
+            <el-option
+              v-for="subitem in rule.sdksOptions"
+              :key="subitem.id"
+              :label="subitem.sdk_name"
+              :value="subitem"
+              :title="subitem.sdk_name"
+              v-show="!subitem.delete"
+            ></el-option>
+          </el-select>
+
+          <!-- 閫夋嫨绫诲瀷 -->
+          <el-select
+            v-model="rule.sdk_arg_type"
+            placeholder="鐩爣"
+            size="mini"
+            style="width:90px;"
+            @change="selectArgTypeOption(rule)"
+          >
+            <el-option value="target" label="鐩爣"></el-option>
+            <el-option value="label" label="鏍囩"></el-option>
+          </el-select>
+
+          <!-- 閫夋嫨瑙勫垯 -->
+          <el-select
+            v-model="rule.argObj"
+            value-key="alias"
+            placeholder="閫夋嫨瑙勫垯"
+            size="mini"
+            @change="selectArgsOption(rule, true)"
+          >
+            <el-option
+              v-for="subitem in rule.argsOptions"
+              :key="subitem.alias"
+              :label="subitem.name"
+              :value="subitem"
+              :title="subitem.name"
+            ></el-option>
+          </el-select>
+
+          <!-- 閫夋嫨鏉′欢 -->
+          <el-select
+            v-model="rule.operatorObj"
+            value-key="value"
+            placeholder="閫夋嫨鏉′欢"
+            size="mini"
+            style="min-width:100px;width:8%"
+            @change="setOperator(rule)"
+          >
+            <el-option
+              v-for="subitem in VideoManageData.Dictionary.RULECOMPUTE"
+              :key="subitem.value"
+              :label="subitem.name"
+              :value="subitem"
+            ></el-option>
+          </el-select>
+
+          <!-- 鍊肩被鍨� -->
+          <el-select
+            v-show="false"
+            v-model="rule.operator_type"
+            placeholder="鍊肩被鍨�"
+            size="mini"
+            style="min-width:100px;width:8%"
+            @change="selectValueOption(rule)"
+          >
+            <el-option value="value" label="鍊�" :disabled="rule.argType === 'option'"></el-option>
+            <el-option value="option" label="琚�夐」" :disabled="rule.argType !== 'option'"></el-option>
+            <el-option value label="绌�" :disabled="rule.argType === 'option'"></el-option>
+          </el-select>
+
+          <!-- 鍊� -->
+          <el-input
+            v-if="rule.operator_type !== 'option'"
+            size="mini"
+            v-model="rule.sdk_arg_value"
+            :style="rule.valid ? `margin:3px 5px;min-width:100px;width:7%` : `margin:3px 5px;min-width:100px;width:7%;border:1px solid red`"
+            @change="setValue(rule)"
+          ></el-input>
+
+          <!-- 閫夐」鍊� -->
+          <el-select
+            v-else
+            v-model="rule.valueObj"
+            value-key="value"
+            size="mini"
+            style="width:8%;min-width:100px"
+            @change="setValue(rule)"
+          >
+            <el-option
+              v-for="subitem in rule.valueOptions"
+              :key="subitem.value"
+              :label="subitem.name"
+              :value="subitem"
+              :title="subitem.name"
+            ></el-option>
+          </el-select>
+
+          <!-- 鍗曚綅 -->
+          <span style="display:inline-block;width:15px;margin-right:10px;">{{ rule.unit }}</span>
+
+          <!-- 鏂板銆佸垹闄� 鎸夐挳 -->
+          <el-button type="text" @click="addRule(index)" class="iconfont iconhebingxingzhuang"></el-button>
+          <el-button
+            type="text"
+            style="color: #F53D3D;"
+            class="iconfont iconshanchu11"
+            @click="groupRules.splice(index, 1)"
+          ></el-button>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import {
+  deleteCameraRules,
+  updateRuleDefence,
+  updateAlarmLevel
+} from "@/api/camera";
+
+export default {
+  name: "SceneRuleEditor",
+  props: {
+    Cameras: {
+      type: Array,
+      default: () => {
+        return []
+      }
+    },
+    isTemplate: {
+      type: Boolean,
+      default: false
+    },
+    isLinkRule: {
+      type: Boolean,
+      default: false
+    },
+    includeSdks: {
+      type: Array
+    },
+    ruleList: {
+      type: String,
+      default: "{}"
+    },
+    onSubmitRule: {
+      type: Function,
+      default: () => false
+    }
+  },
+  computed: {
+    allPolygonData() {
+      let polygon = [];
+      let cameras = [...this.Cameras];
+
+      for (let i = 0; i < cameras.length; i++) {
+        let polyOpt = cameras[i].polygonData.map(p => {
+          return {
+            defence_state: p.defence_state,
+            polygonId: p.id,
+            name: this.isLinkRule
+              ? cameras[i].cameraName + ":" + p.name
+              : p.name,
+
+            cameraId: cameras[i].cameraId
+          };
+        });
+
+        polygon = polygon.concat(polyOpt);
+      }
+      return polygon;
+    }
+  },
+  watch: {
+    ruleList: {
+      handler(newVal, oldVal) {
+        this.editHandle(newVal);
+      },
+      deep: true
+    },
+  },
+  mounted() {
+    this.editHandle(this.ruleList);
+  },
+  data() {
+    return {
+      tasksTable: {},
+      groupRules: [],
+      sdksOption: [],
+      baseRule: {
+        camera_id: "",
+        id: "",
+        operator: "",
+        operator_type: "",
+        polygon_id: "",
+        rule_with_pre: "",
+        sdk_id: "",
+        sdk_arg_alias: "",
+        sdk_arg_value: "",
+        sdk_arg_defaultValue: "",
+        select_time_rule: "",
+        sdk_arg_type: "",
+        // task_id: "",
+
+        polygonObj: {},
+        taskObj: "",
+
+        sdkObj: {},
+        argObj: {},
+        operatorObj: {},
+        valueObj: {},
+
+        sdksOptions: [],
+        argsOptions: [],
+        argType: "",
+        computeOptions: [],
+        valueOptions: [],
+
+        sdkDesc: "",
+        argDesc: "",
+        operatorDesc: "",
+        typeDesc: "",
+        valueDesc: "",
+
+        unit: "",
+        value: "",
+        valid: true
+      },
+    };
+  },
+  methods: {
+    setSdksOptions(rule) {
+      rule.sdksOptions = this.includeSdks;
+    },
+    setOperator(rule) {
+      rule.operator = rule.operatorObj.value;
+      rule.operatorDesc = rule.operatorObj.name;
+    },
+    setValue(rule) {
+      rule.valid = true
+
+      if (rule.operator_type === "option") {
+        rule.sdk_arg_value = rule.valueObj.value ? rule.valueObj.value : "";
+        rule.typeDesc = "琚�夐」";
+        rule.valueDesc = rule.valueObj.name ? rule.valueObj.name : "";
+      } else {
+        rule.typeDesc = "鍊�";
+        rule.valueDesc = rule.sdk_arg_value;
+      }
+      this.valideArgValue(rule)
+    },
+    selectPolygonOption(rule) {
+      rule.polygon_id = rule.polygonObj.polygonId ? rule.polygonObj.polygonId : rule.polygon_id;
+      rule.camera_id = rule.polygonObj.cameraId ? rule.polygonObj.cameraId : rule.camera_id;
+      rule.group_id = this.group_id;
+    },
+    selectSDKOption(rule, resetArgs) {
+      rule.sdk_id = rule.sdkObj.id;
+      rule.sdkDesc = `<span style="background-color:RGB(183,183,183);">${rule.sdkObj.sdk_name}</span>`;
+
+      // 閫夐」鍒囨崲鏃堕渶瑕佸埛鏂癮rg鑿滃崟椤�
+      this.selectArgTypeOption(rule, resetArgs)
+    },
+    selectArgTypeOption(rule, resetAlias) {
+      if (rule.sdk_arg_type == "") {
+        return
+      }
+
+      if (resetAlias) {
+        rule.sdk_arg_alias = "";
+      }
+
+      rule.argsOptions = rule.sdkObj.args;
+
+      // 鏍规嵁arg绫诲瀷鏄剧ず鍙傛暟, 褰撳墠鍏ㄩ儴褰掍负 target
+      // if (rule.sdkObj.args) {
+      //   rule.argsOptions = rule.sdkObj.args.filter(ele => {
+      //     return ele.arg_type === rule.sdk_arg_type
+      //   });
+      // } else {
+      //   rule.argsOptions = [];
+      // }
+
+      rule.argObj = {};
+    },
+    selectArgsOption(rule, resetArgValue) {
+      // rule.operator_type = "";
+      // console.log(rule, '閫夋嫨绠楁硶鍙傛暟')
+      rule.sdk_arg_alias = rule.argObj.alias;
+      rule.argDesc = rule.argObj.name;
+      rule.sdk_arg_defaultValue = rule.argObj.default_value
+      rule.unit = rule.argObj.unit ? rule.argObj.unit : "";
+      //rule.default_value = rule.argObj.default_value ? Number(rule.argObj.default_value) : 0;
+
+      //console.log("缃俊搴︾殑榛樿鍊间负",rule.sdk_arg_defaultValue)
+      // 淇濆瓨鍊肩被鍨�
+      rule.argType = rule.argObj.type;
+      if (rule.argType === "option") {
+        rule.operator_type = "option";
+        // 璁剧疆榛樿鏉′欢鍊�
+        this.VideoManageData.Dictionary.RULECOMPUTE.forEach(opt => {
+          if (opt.value == "==") {
+            rule.operatorObj = opt;
+          }
+        });
+
+        this.setOperator(rule);
+
+        this.selectValueOption(rule);
+      } else {
+        // 璁剧疆榛樿鏉′欢鍊�
+        rule.operator_type = "value";
+        if (resetArgValue) {
+          rule.sdk_arg_value = ""
+
+          this.VideoManageData.Dictionary.RULECOMPUTE.forEach(opt => {
+            if (opt.value == ">=") {
+              rule.operatorObj = opt;
+            }
+          });
+        } else {
+          // 缂栬緫瑙勫垯鍖归厤
+          this.VideoManageData.Dictionary.RULECOMPUTE.forEach(opt => {
+            if (opt.value == rule.operator) {
+              rule.operatorObj = opt;
+            }
+          });
+        }
+        this.setOperator(rule);
+      }
+    },
+    selectValueOption(rule) {
+      if (rule.sdk_arg_alias === "time_rule") {
+        rule.valueOptions = this.VideoManageData.TimeRules.map(r => {
+          return {
+            name: r.name,
+            value: r.id
+          };
+        });
+      } else if (rule.sdk_arg_alias === "compareBase") {
+        rule.valueOptions = this.VideoManageData.TagList.map(r => {
+          return {
+            name: r.tableName,
+            value: r.id
+          };
+        });
+      } else {
+        let ops = this.VideoManageData.Dictionary[rule.sdk_arg_alias]
+        if (ops && ops instanceof (Array)) {
+          rule.valueOptions = ops.map(r => {
+            return {
+              name: r.name,
+              value: r.value
+            }
+          })
+        }
+      }
+    },
+    valideArgValue(rule) {
+      if (rule.sdk_arg_value == "") {
+        this.$notify({
+          type: 'warning',
+          message: "鍙傛暟璁惧畾鍊间笉鑳戒负绌�!"
+        })
+        rule.valid = false
+        return false
+      }
+
+      if (rule.argObj && rule.argObj.range) {
+        // 濡傛灉璁剧疆浜嗙畻娉曢粯璁ゅ�硷紝鍒欏垽鏂笉鑳藉皬浜庤鍊�
+        if (rule.argObj.default_value) {
+          if (parseInt(rule.sdk_arg_value) < parseInt(rule.sdk_arg_defaultValue)) {
+            rule.valid = false
+            this.$notify({
+              type: "warning",
+              message: "鍙傛暟璁惧畾鍊间笉鑳藉皬浜庣畻娉曞弬鏁伴粯璁ゅ�� " + rule.sdk_arg_defaultValue
+            })
+            rule.valueDesc = rule.sdk_arg_value = rule.argObj.default_value;
+            rule.valid = false
+            return false;
+          }
+        }
+
+        // let re = /(?<=,).*?(?=]|\))/
+        let re = /.*,(\d+)/
+        let max = rule.argObj.range.match(re)[1]
+        // console.log(max,'鑾峰彇鑼冨洿鏈�澶у��')
+        if (Number(rule.sdk_arg_value) > Number(max)) {
+          rule.valid = false
+          this.$notify({
+            type: 'warning',
+            message: "鍙傛暟璁惧畾鍊间笉鑳藉ぇ浜�" + max
+          })
+          return false
+        }
+      }
+
+      return true;
+    },
+    parataxis(rule_with_pre) {
+      let relation = "";
+      this.VideoManageData.Dictionary.RULECOMPUTEBETWEEN.forEach(pre => {
+        if (pre.value === rule_with_pre) {
+          relation = pre.name;
+        }
+      });
+
+      return relation;
+    },
+
+    generatDescription() {
+      let desc = "";
+      this.groupRules.forEach((r, index) => {
+        // console.log(r,index,'鎷兼帴')
+        if (index === 0) {
+          desc +=
+
+            r.sdkDesc +
+            r.argDesc +
+            r.operatorDesc +
+            r.valueDesc +
+            r.unit
+        } else {
+          desc +=
+            '&nbsp;&nbsp;&nbsp;' + this.parataxis(r.rule_with_pre) + '&nbsp;&nbsp;&nbsp;' +
+            r.sdkDesc +
+            r.argDesc +
+            r.operatorDesc +
+            r.valueDesc +
+            r.unit
+        }
+      });
+      // console.log(desc,'鎷兼帴')
+      return desc;
+    },
+    createRule() {
+      if (!this.isTemplate && this.Cameras.length > 0) {
+        // 鏈�変腑鎽勫儚鏈烘垨鑰呮湭閫変腑鎽勫儚鏈轰换鍔★紝涓嶆墽琛屽垱寤�
+        if (!this.Cameras[0].cameraId)
+          return false;
+      }
+
+      if (this.isLinkRule && this.TreeDataPool.selectedNodes.length < 2) {
+        this.$notify({
+          type: "warning",
+          message: "璇烽�夋嫨鑷冲皯2涓憚鍍忔満!"
+        })
+        return false;
+      }
+
+      this.group_id = "";
+
+      this.addRule(0);
+    },
+    cleanRule() {
+      this.groupRules.splice(0, this.groupRules.length);
+    },
+    addRule(index) {
+      let newRule = JSON.parse(JSON.stringify(this.baseRule));
+      newRule.sdksOptions = this.includeSdks;
+      if (!this.isLinkRule) {
+        // 璁剧疆榛樿鍏ㄩ儴鍖哄煙
+        // if (!this.isTemplate) {
+        //   newRule.polygonObj = this.allPolygonData[0];
+        //   this.selectPolygonOption(newRule)
+        // }
+
+        // 璁剧疆绠楁硶
+        // newRule.sdksOptions = this.includeSdks;
+        // 璁剧疆榛樿绠楁硶
+        // newRule.sdkObj = newRule.sdksOptions[0]
+        // this.selectSDKOption(newRule, false)
+
+        // newRule.sdk_arg_type = "target"
+        // this.selectArgTypeOption(newRule, true)
+      }
+
+      // this.groupRules.push(newRule);
+      // 鎻掑叆鍒版寚瀹氫綅缃�
+      this.groupRules.splice(index + 1, 0, newRule);
+    },
+    editHandle(ruleTxt) {
+      if (ruleTxt.length < 1) {
+        return;
+      }
+      let ruleInfo = JSON.parse(ruleTxt);
+      this.editRule(ruleInfo)
+      // 濡傛灉鏄仈鍔ㄤ换鍔�, 鏌ヨ鑱斿姩鎽勫儚鏈哄垪琛�, 灏嗘爲閫変腑鐨勫垪琛ㄦ洿鏀逛负璇ユ潯瑙勫垯鎵�闇�瑕佺殑鎽勫儚鏈�, 骞跺浠藉綋鍓嶇殑閫変腑鐘舵��, 瑙勫垯淇濆瓨鍚庢仮澶�
+      // if (this.isLinkRule) {
+      //   this.VideoRuleData.treeSelectedNodesBackupOnEditLinkRule = [...this.TreeDataPool.selectedNodes]
+      //   this.VideoRuleData.editLinkRuleRow = { ...ruleInfo }
+
+      //   this.TreeDataPool.selectedNodes = ruleInfo.group_rules.map(r => {
+      //     return r.camera_id
+      //   })
+      //   this.$nextTick(() => {
+      //     setTimeout(() => {
+      //       this.editRule(ruleInfo)
+      //     }, 1000)
+      //   })
+      // } else {
+      //   this.editRule(ruleInfo)
+      // }
+    },
+    editRule(ruleGroup) {
+      this.group_id = "";
+
+      ruleGroup.forEach(rule => {
+        if (rule.group_id && rule.group_id != "") {
+          this.group_id = rule.group_id;
+        }
+
+        // 濉厖鍖哄煙閫夐」鍒楄〃
+        this.allPolygonData.forEach(p => {
+          if (p.polygonId === rule.polygon_id) {
+            rule.polygonObj = p;
+          }
+        });
+
+        if (!rule.polygonObj) {
+          rule.polygonObj = {
+            cameraId: rule.camera_id,
+            defence_state: 1,
+            name: "鏈煡鍖哄煙",
+            polygonId: rule.polygon_id,
+          }
+        }
+
+        // 璁剧疆鍖哄煙
+        this.selectPolygonOption(rule);
+
+        // 璁剧疆绠楁硶缁�
+        this.setSdksOptions(rule);
+
+        // 濉厖绠楁硶閫夐」鍒楄〃
+        if (rule.sdksOptions) {
+          rule.sdksOptions.forEach(s => {
+            if (s.id === rule.sdk_id) {
+              rule.sdkObj = s;
+            }
+          });
+        }
+        if (!rule.sdkObj || Object.keys(rule.sdkObj).length === 0) {
+          rule.sdkObj = {
+            id: rule.sdk_id,
+            sdk_name: "(宸插垹闄�)",
+            args: [],
+            delete: true
+          }
+          rule.sdksOptions.push(rule.sdkObj)
+        }
+
+        this.selectSDKOption(rule, false);
+        // 瑙勫垯淇濆瓨鏃舵暟鎹簱涓嶅瓨鍙傛暟绫诲瀷锛岄渶瑕佹牴鎹�煎弽鏌�
+        // rule.sdk_arg_type = ""
+        // if (rule.sdk_arg_alias === "time_rule") {
+        //   rule.sdk_arg_type = "target"
+        // }
+        rule.sdk_arg_type = "target"
+        // rule.sdkObj.args.forEach(ele => {
+        //   if (ele.alias === rule.sdk_arg_alias) {
+        //     rule.sdk_arg_type = ele.arg_type
+        //   }
+        // });
+        this.selectArgTypeOption(rule, false)
+
+        if (rule.argsOptions) {
+          rule.argsOptions.forEach(arg => {
+            if (arg.alias === rule.sdk_arg_alias) {
+              rule.argObj = arg;
+            }
+          });
+          this.selectArgsOption(rule, false);
+        }
+
+        this.VideoManageData.Dictionary.RULECOMPUTE.forEach(opt => {
+          if (opt.value == rule.operator) {
+            rule.operatorObj = opt;
+          }
+        });
+
+        this.setOperator(rule);
+        this.selectValueOption(rule);
+
+        if (rule.operator_type == "option") {
+          rule.valueOptions.forEach(val => {
+            if (val.value === rule.sdk_arg_value) {
+              rule.valueObj = val;
+            }
+          });
+        }
+        if (!rule.valueObj) {
+          rule.valueObj = {
+            name: rule.sdk_arg_value,
+            value: rule.sdk_arg_value
+          }
+        }
+        this.setValue(rule);
+      });
+      this.$nextTick(() => {
+        this.groupRules = ruleGroup;
+      });
+    },
+    delRule(rule) {
+      this.$confirm("鎻愮ず锛氬垹闄ゅ悗锛岃鏉¤鍒欏皢澶辨晥锛屾槸鍚﹀垹闄わ紵", {
+        center: true,
+        cancelButtonClass: "comfirm-class-cancle",
+        confirmButtonClass: "comfirm-class-sure"
+      })
+        .then(() => {
+          deleteCameraRules({ groupId: rule.group_id }).then(res => {
+            if (res && res.success) {
+              this.$notify({
+                type: "success",
+                message: "鍒犻櫎鎴愬姛"
+              });
+              this.$emit("delete-rule");
+            } else {
+              this.$notify({
+                type: "error",
+                message: "鍒犻櫎澶辫触锛�"
+              });
+            }
+          });
+        })
+        .catch(() => { });
+    },
+    submitRule() {
+      let groupRule = {};
+      let group_text = "";
+
+      if (this.isTemplate) {
+        groupRule.rules = this.groupRules.map(r => {
+          return {
+            sdk_id: r.sdk_id,
+            sdk_arg_alias: r.sdk_arg_alias,
+            operator: r.operator,
+            operator_type: r.operator_type,
+            sdk_arg_value: r.sdk_arg_value,
+            sort: 1,
+            rule_with_pre: r.rule_with_pre
+          };
+        })
+      } else {
+        groupRule.rules = this.groupRules.map(r => {
+          return {
+            camera_id: r.camera_id,
+            group_id: r.group_id,
+            id: r.id,
+            operator: r.operator,
+            operator_type: r.operator_type,
+            polygon_id: r.polygon_id,
+            rule_with_pre: r.rule_with_pre,
+            sdk_arg_alias: r.sdk_arg_alias,
+            sdk_arg_value: r.sdk_arg_value,
+            sdk_id: r.sdk_id,
+          };
+        })
+      }
+
+      groupRule.text = this.generatDescription();
+      groupRule.id = this.group_id;
+      return groupRule;
+
+      // 鏆傛椂鍏堜笉楠岃瘉
+      for (let i in this.groupRules) {
+        let rule = this.groupRules[i]
+        if (!rule.polygon_id || !rule.sdk_id || !rule.operator || !rule.operator_type || rule.sdk_arg_type == "") {
+          this.$notify({
+            type: "error",
+            message: "涓嶅厑璁搁厤缃笉瀹屾暣鐨勮鍒欙紝璇锋鏌ユ槸鍚︽湁鏈�夋嫨椤�"
+          })
+          return;
+        }
+        if (!this.valideArgValue(rule)) {
+          return;
+        }
+      }
+
+      if (this.isLinkRule) {
+        // 鍒ゆ柇瑙勫垯涓嚦灏戝寘鍚袱鎽勫儚鏈�
+        let cameraIds = Array.from(new Set(this.groupRules.map(r => {
+          return r.camera_id
+        })))
+        if (cameraIds.length < 2) {
+          this.$notify({
+            type: "error",
+            message: "闇�瑕�2涓笉鍚屾憚鍍忔満鎵嶈兘缁勬垚鑱斿姩瑙勫垯"
+          })
+          return
+        }
+
+        // 鑱斿姩瑙勫垯缂栬緫鍚庯紝鎭㈠涔嬪墠閫変腑鐨勬憚鍍忔満
+        // if (this.VideoRuleData.treeSelectedNodesBackupOnEditLinkRule.length) {
+        //   this.TreeDataPool.selectedNodes = this.VideoRuleData.treeSelectedNodesBackupOnEditLinkRule
+        //   this.VideoRuleData.treeSelectedNodesBackupOnEditLinkRule = []
+        // }
+      }
+
+      this.onSubmitRule(payload);
+    }
+  }
+};
+</script>
+
+<style lang="scss">
+.edit-rules-box {
+  width: 100%;
+  padding: 0px;
+  box-sizing: border-box;
+  .sub-task-rules-box {
+    width: 100%;
+    min-height: 50px;
+    border-top: 1px solid #eee;
+    padding-top: 7px;
+
+    box-sizing: border-box;
+    padding-bottom: 38px;
+    .task-rules-button {
+      text-align: right;
+      margin: 15px;
+    }
+
+    .el-select {
+      margin: 3px 8px;
+      min-width: 130px;
+      width: 12%;
+    }
+  }
+
+  .el-button--text {
+    text-decoration: unset;
+  }
+
+  p {
+    text-align: left;
+    // padding: 10px;
+    box-sizing: border-box;
+  }
+
+  .task-blank {
+    float: left;
+    font-family: PingFangSC-Regular;
+    font-size: 12px;
+    color: #cccccc;
+    margin-top: 5px;
+  }
+
+  .btn {
+    cursor: pointer;
+    color: #3d68e1;
+    margin-left: 10px;
+    font-size: 14px;
+  }
+}
+</style>
\ No newline at end of file
diff --git a/src/components/subComponents/VueCron.vue b/src/components/subComponents/VueCron.vue
new file mode 100644
index 0000000..d5d59a0
--- /dev/null
+++ b/src/components/subComponents/VueCron.vue
@@ -0,0 +1,194 @@
+<template>
+  <div>
+    <b style="padding-right:30px;">瀹氭椂閲嶅惎:</b>
+    <el-select v-model="every" placeholder="璇烽�夋嫨" size="small" @change="changeEvery">
+      <el-option label="鍏抽棴" value="never"></el-option>
+      <el-option label="姣忓ぉ" value="day"></el-option>
+      <el-option label="姣忓懆" value="week"></el-option>
+      <el-option label="姣忔湀" value="month"></el-option>
+    </el-select>
+
+    <el-select
+      v-show="every == 'month'"
+      v-model="cronValueObj.day"
+      placeholder="璇烽�夋嫨"
+      size="small"
+      style="margin-left: 20px"
+      @change="updateExpression"
+    >
+      <el-option v-for="item in days" :key="item.value" :label="item.label" :value="item.value"></el-option>
+    </el-select>
+
+    <el-select
+      v-show="every == 'week'"
+      v-model="cronValueObj.week"
+      placeholder="璇烽�夋嫨"
+      size="small"
+      style="margin-left: 20px"
+      @change="updateExpression"
+    >
+      <el-option label="鏄熸湡涓�" value="1"></el-option>
+      <el-option label="鏄熸湡浜�" value="2"></el-option>
+      <el-option label="鏄熸湡涓�" value="3"></el-option>
+      <el-option label="鏄熸湡鍥�" value="4"></el-option>
+      <el-option label="鏄熸湡浜�" value="5"></el-option>
+      <el-option label="鏄熸湡鍏�" value="6"></el-option>
+      <el-option label="鏄熸湡鏃�" value="7"></el-option>
+    </el-select>
+
+    <el-time-picker
+      v-show="every !== 'never'"
+      v-model="time"
+      :picker-options="{selectableRange: '00:00:00 - 23:59:59'}"
+      value-format="HH:mm"
+      format="HH:mm"
+      placeholder="浠绘剰鏃堕棿鐐�"
+      size="small"
+      style="margin-left: 20px"
+      @change="updateExpression"
+    ></el-time-picker>
+
+    <el-button
+      v-show="saveBtn"
+      type="primary"
+      size="small"
+      style="margin-left: 20px"
+      @click="save"
+    >淇濆瓨</el-button>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "VueCrontab",
+  props: ["expression"],
+  computed: {
+    days: () => {
+      let arr = []
+      for (let i = 1; i < 32; i++) {
+        arr.push({
+          label: i + "鏃�",
+          value: i + ""
+        })
+      }
+
+      return arr
+    }
+  },
+  watch: {
+    expression: function () {
+      this.resolveExp()
+    }
+  },
+  data() {
+    return {
+      saveBtn: false,
+      every: "never",
+      time: "",
+      cronValueObj: {
+        min: "*",
+        hour: "*",
+        day: "*",
+        month: "*",
+        week: "*"
+      },
+      cronText: ""
+    }
+  },
+  mounted() {
+    this.resolveExp()
+  },
+  methods: {
+    resolveExp() {
+      //鍙嶈В鏋� 琛ㄨ揪寮�
+      "鍑嗗鍙嶈В鏋�", this.expression;
+      if (this.expression.length) {
+        let arr = this.expression.split(" ");
+        if (arr.length >= 5) {
+          //6 浣嶄互涓婃槸鍚堟硶琛ㄨ揪寮�
+          this.cronValueObj.min = arr[0]
+          this.cronValueObj.hour = arr[1]
+          this.cronValueObj.day = arr[2]
+          // this.cronValueObj.month = arr[3],
+          this.cronValueObj.month = "*"
+          this.cronValueObj.week = arr[4]
+        }
+
+        if (this.cronValueObj.week != "*") {
+          this.every = "week"
+        } else if (this.cronValueObj.day != "*") {
+          this.every = "month"
+        } else {
+          this.every = "day"
+        }
+        this.time = this.cronValueObj.hour + ":" + this.cronValueObj.min
+      } else {
+        //娌℃湁浼犲叆鐨勮〃杈惧紡 鍒欒繕鍘�
+        this.clearCron();
+      }
+    },
+    changeEvery() {
+      this.saveBtn = true;
+      if (this.every === "never") {
+        this.cronText = ""
+        return
+      }
+      if (this.every === "month") {
+        this.cronValueObj.week = "*"
+        this.cronValueObj.day = "1"
+        if (!this.time.length) {
+          this.time = "00:00"
+        }
+      }
+      if (this.every === "week") {
+        this.cronValueObj.day = "*"
+        this.cronValueObj.week = "1"
+        if (!this.time.length) {
+          this.time = "00:00"
+        }
+      }
+      if (this.every === "day") {
+        this.cronValueObj.day = "*"
+        this.cronValueObj.week = "*"
+      }
+      this.updateExpression()
+    },
+    updateExpression() {
+      this.saveBtn = true;
+      if (this.time.length) {
+        let arr = this.time.split(":");
+        this.cronValueObj.hour = arr[0]
+        this.cronValueObj.min = arr[1]
+      }
+      this.crontabValueString()
+    },
+    clearCron() {
+      this.cronValueObj.second = "*"
+      this.cronValueObj.min = "*"
+      this.cronValueObj.hour = "*"
+      this.cronValueObj.day = "*"
+      this.cronValueObj.month = "*"
+      this.cronValueObj.week = "*"
+    },
+    crontabValueString: function () {
+      let obj = this.cronValueObj;
+      this.cronText =
+        obj.min +
+        " " +
+        obj.hour +
+        " " +
+        obj.day +
+        " " +
+        obj.month +
+        " " +
+        obj.week
+    },
+    save() {
+      this.$emit("update", this.cronText)
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+</style>
\ No newline at end of file
diff --git a/src/components/subComponents/chartLiquid.vue b/src/components/subComponents/chartLiquid.vue
new file mode 100644
index 0000000..4d7cdf5
--- /dev/null
+++ b/src/components/subComponents/chartLiquid.vue
@@ -0,0 +1,141 @@
+<template>
+  <div ref="ball" :style="{width: size + 'px', height: size + 'px', marginLeft: '10px'}"></div>
+</template>
+
+<script>
+import echarts from "echarts";
+import echartsLiquidfill from "echarts-liquidfill";
+
+export default {
+  name: "EchartsLiquidFill",
+  props: {
+    title: {
+      type: String,
+      defalut: ""
+    },
+    value: {
+      type: Number,
+      defalut: 0
+    },
+    size: {
+      type: Number,
+      defalut: 100
+    }
+  },
+  computed: {
+    fillColor() {
+      if (this.PollData.Thresholds.length > 0) {
+        for (let i = 0; i < this.PollData.Thresholds.length; i++) {
+          if (this.value <= this.PollData.Thresholds[i].Value) {
+            return this.PollData.Thresholds[i].Color;
+          }
+        }
+      }
+
+      if (this.value <= 60) {
+        return "#13ce66"
+      } else if (this.value > 60 && this.value <= 80) {
+        return "#FF9C4A"
+      } else if (this.value > 80 && this.value <= 95) {
+        return "#f53d3d"
+      } else {
+        return "#5d0000"
+      }
+    }
+  },
+  mounted() {
+    this.initChart()
+  },
+  watch: {
+    value: function (newVal, oldVal) {
+      if (newVal !== oldVal) {
+        this.initChart()
+      }
+    }
+  },
+  methods: {
+    initChart() {
+      let options = {
+        title: {
+          // 鏍囬
+          text: this.title,
+          textStyle: {
+            // 鏍囬鐨勬牱寮�
+            color: "#222", // 瀛椾綋棰滆壊
+            fontFamily: "Microsoft YaHei", // 瀛椾綋
+            fontSize: 14,
+            fontWeight: "800",
+            align: "center", // 鏂囧瓧鐨勬按骞虫柟寮�
+            baseline: "middle",
+            position: "inside",
+            verticalAlign: "middle" // 鏂囧瓧鐨勫瀭鐩存柟寮�
+          },
+          left: "center", // 瀹氫綅
+          top: "14%"
+        },
+
+        grid: {
+          left: 50,
+        },
+        series: [
+          {
+            type: "liquidFill",
+            radius: "95%",
+            waveAnimation: true,
+            data: [
+              {
+                value: this.value / 100,
+                direction: "left",
+                itemStyle: {
+                  normal: {
+                    color: this.fillColor
+                  }
+                }
+              }
+            ],
+            outline: {
+              // show: true , //鏄惁鏄剧ず杞粨 甯冨皵鍊�
+              borderDistance: 1, // 澶栭儴杞粨涓庡浘琛ㄧ殑璺濈 鏁板瓧
+              itemStyle: {
+                borderColor: this.fillColor, // 杈规鐨勯鑹�
+                borderWidth: 3, // 杈规鐨勫搴�
+                shadowBlur: 1, //澶栭儴杞粨鐨勯槾褰辫寖鍥� 涓�鏃﹁缃簡鍐呭閮芥湁闃村奖
+                shadowColor: '#fff' //澶栭儴杞粨鐨勯槾褰遍鑹�
+              }
+            },
+            itemStyle: {
+              opacity: 0.9, // 娉㈡氮鐨勯�忔槑搴�
+              shadowBlur: 0 // 娉㈡氮鐨勯槾褰辫寖鍥�
+            },
+            backgroundStyle: {
+              color: "#fff" // 鍥捐〃鐨勮儗鏅鑹�
+            },
+            label: {
+              // 鏁版嵁灞曠ず鏍峰紡
+              show: true,
+              color: "#000",
+              insideColor: "#fff",
+              fontSize: 14,
+              fontWeight: 400,
+              align: "center",
+              baseline: "middle",
+              position: "inside",
+              normal: {
+                formatter: (this.value).toFixed(2) + '%',
+                textStyle: {
+                  fontSize: 14,
+                  fontWeight: 400,
+                  color: "#000",
+                }
+              }
+            }
+
+          }
+        ]
+      }
+      let chart = echarts.init(this.$refs.ball);
+      chart.setOption(options);
+    }
+  }
+};
+</script>
\ No newline at end of file
diff --git a/src/components/subComponents/eChartsBar.vue b/src/components/subComponents/eChartsBar.vue
new file mode 100644
index 0000000..4cd7a99
--- /dev/null
+++ b/src/components/subComponents/eChartsBar.vue
@@ -0,0 +1,174 @@
+<template>
+  <div ref="cpuMenery" style="height:100%;"></div>
+</template>
+
+<script>
+import echarts from "echarts";
+
+export default {
+  name: "eChartsCpu",
+  props: {
+    title: {
+      type: String,
+      defalut: ""
+    },
+    value: {
+      type: Number,
+      defalut: 0
+    },
+    yAxisData: {
+      type: Array,
+      default: () => {
+        return ["纭洏", "CPU", "绠楀姏", "鍐呭瓨"]
+      }
+    },
+    xAxisData: {
+      type: Array,
+      default: () => {
+        return []
+      }
+    },
+    width: {
+      type: Number,
+      default: 500
+    },
+    size: {
+      type: Number,
+      defalut: 145
+    }
+  },
+  computed: {
+
+  },
+  data() {
+    return {
+      eChartsObj: {}
+    }
+  },
+  mounted() {
+    // console.log(this.$refs.cpuMenery.offsetWidth,'this.$refs.cpuMenery',this.$refs.cpuMenery.offsetHeight)
+    if (this.$refs.cpuMenery.offsetWidth && this.$refs.cpuMenery.offsetHeight) {
+      this.initChart()
+    }
+    window.addEventListener('resize', this.windowSizeChange)
+  },
+  watch: {
+    value: function (newVal, oldVal) {
+      if (newVal !== oldVal) {
+        this.initChart()
+      }
+    }
+  },
+  methods: {
+    initChart() {
+      let options = {
+        title: {
+          // 鏍囬
+          text: this.title
+        },
+        tooltip: {
+          formatter: (data) => {
+            return data.value + '%'
+          }
+        },
+        grid: {
+          top: 10,
+          right: 30,
+          bottom: 20,
+          left: 40,
+        },
+        xAxis: {
+          show: false,
+          type: 'value',
+          max: 100,
+          splitLine: {
+            show: false
+          },
+          axisLine: {
+            lineStyle: {
+              color: '#dfe6ec'
+            }
+          },
+          axisTick: {
+            lineStyle: {
+              color: '#606266'
+            }
+          },
+          axisLabel: {
+            color: '#606266'
+          },
+        },
+        yAxis: {
+          show: true,
+          type: 'category',
+          data: this.yAxisData,
+          axisLabel: {
+            interval: 0,
+            rotate: 0
+          },
+          axisLine: {
+            show: false,
+            lineStyle: {
+              color: '#dfe6ec'
+            }
+          },
+          axisTick: {
+            show: false,
+            lineStyle: {
+              color: '#606266'
+            }
+          },
+          axisLabel: {
+            color: '#606266',
+            align: 'right'
+          },
+        },
+        series: [
+          {
+            type: 'bar',
+            stack: 'chart',
+            z: 3,
+            itemStyle: {
+              normal: {
+                color: '#3D68E1'
+              },
+              emphasis: {
+                color: '#3D68E1'
+              }
+            },
+            data: this.xAxisData,
+            label: {
+              show: true,
+              position: 'right',
+              formatter: (data) => {
+                return data.value + '%'
+              }
+            },
+          },
+          {
+            type: 'bar',
+            stack: 'chart',
+            silent: true,
+            itemStyle: {
+              normal: {
+                color: 'rgb(248, 248, 248)'
+              }
+            },
+            data: this.xAxisData.map(function (i) {
+              return 100 - i;
+            }),
+            barMaxWidth: 15
+          }
+        ]
+      }
+      this.eChartsObj = echarts.init(this.$refs.cpuMenery);
+      this.eChartsObj.setOption(options);
+    },
+    windowSizeChange() {
+      this.eChartsObj.resize();
+    },
+  }
+};
+</script>
+<style lang="scss">
+</style>
\ No newline at end of file
diff --git a/src/components/subComponents/imgDown.vue b/src/components/subComponents/imgDown.vue
new file mode 100644
index 0000000..5b988c3
--- /dev/null
+++ b/src/components/subComponents/imgDown.vue
@@ -0,0 +1,93 @@
+<template>
+    <div class="imgBox">
+        <img 
+          :src="'/httpImage/'+url" 
+          class="cursor-pointer"
+          v-if="isPreview"
+          preview
+        />
+        <img 
+          :src="'/httpImage/'+url" 
+          v-if="!isPreview"
+        />
+        <el-button class="btn" @click="downloadIamge('/httpImage/'+url)">
+          <i class="iconfont iconxiazai"></i>
+        </el-button>
+    </div>
+</template>
+<script>
+import axios from "axios"
+export default {
+   props:{
+      url: {
+          default: "",
+          type: String
+      },
+      isPreview: {
+        default: true,
+        type: Boolean
+      }
+   },
+   methods:{
+    downloadIamge(url) {
+      axios({
+        method: "get",
+        url: url,
+        responseType: 'blob'
+      }).then(res => {
+        if (res.status == 200) {
+          var a = document.createElement('a')
+          var strs = url.split('/')
+          var href = new Blob([res.data],{type: 'image/jpeg'})
+          a.href = URL.createObjectURL(href);
+          a.download  = strs[strs.length - 1]+'.jpg'
+          a.click()
+        }
+      }).catch(err => {
+        this.$notify({
+          type: "error",
+          message: "涓嬭浇澶辫触锛�"+err+"璇烽噸璇曪紒",
+        })
+      })
+    },
+   } 
+   
+}
+</script>
+<style lang="scss" scoped>
+.imgBox{
+    width: 100%;
+    height: 100%;
+    position: relative;
+    img {
+        width: 100%;
+        height: 100%;
+        object-fit: contain
+    }
+    .btn {
+        width: 30px;
+        height: 30px;
+        position: absolute;
+        padding: 0;
+        right: 20%;
+        opacity: 1;
+        bottom: 10px;
+        -webkit-animation: fadenum 0.7s ease;
+        display: none;
+        i {
+          font-size: 20px
+        }
+    }
+}
+.imgBox:hover .btn {
+  display: inline;
+}
+@-webkit-keyframes fadenum{ /*璁剧疆鍐呭鐢辨樉绀哄彉涓洪殣钘�*/
+
+    0%{opacity: 0;}
+
+    100%{opacity: 1;}
+
+}
+
+</style>
\ No newline at end of file
diff --git a/src/pages/algorithmManage/index/App.vue b/src/pages/algorithmManage/index/App.vue
new file mode 100644
index 0000000..34488d2
--- /dev/null
+++ b/src/pages/algorithmManage/index/App.vue
@@ -0,0 +1,861 @@
+<template>
+  <div class="s-task-manage">
+    <div style="height:100%;">
+      <div class="flex-box task-manage">
+        <div class="installModel" v-if="isInstall">
+          <div class="progress-bar">
+            <div class="inner-bar"></div>
+          </div>
+        </div>
+        <!-- 瓒呯骇绠$悊鍛樺彲瑙� -->
+        <div class="super" v-if="isSuperUser">
+          <div class="left-box">
+            <!-- <div class="title">
+          <label>绠楁硶搴�</label>
+            </div>-->
+            <el-tabs
+              v-model="activeName"
+              type="border-card"
+              @tab-click="handleTabClick"
+              style="height: calc(100% - 20px);"
+            >
+              <el-tab-pane label="鎴戠殑绠楁硶" name="myAlgorithm">
+                <div class="width-new-line task-list" v-show="activeName === 'myAlgorithm'">
+                  <div class="flex-list">
+                    <!-- <draggable
+                :list="installedList"
+                :group="{ name: 'article', pull: 'clone', put: false }"
+                :sort="false"
+                @start="startRight"
+                @end="endLeft"
+                style="display:inline"
+                    >-->
+
+                    <div class="wrap-box" v-for="item in ungradeList" :key="item.id">
+                      <div class="list-choose-item-left">
+                        <div class="mask">
+                          <el-button type="primary" class="bot-btn" @click="donwload(item)">鍗囩骇</el-button>
+                        </div>
+
+                        <div class="list-complete-item-handle">
+                          <div class="svg-wrap">
+                            <svg class="icon" aria-hidden="true" style="font-size:7rem;">
+                              <use :xlink:href="`#${item.icon}`" />
+                            </svg>
+                          </div>
+                          <div class="alg-name">
+                            <div style="padding:0px 10px 0px 10px;">
+                              <span>{{ item.sdk_name }}</span>
+                            </div>
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+                    <div class="wrap-box" v-for="(item) in installedList" :key="item.id">
+                      <div class="list-choose-item-left">
+                        <div class="mask" v-if="!item.isEdit">
+                          <el-button
+                            @click="commandAlgLib(item)"
+                            type="primary"
+                            class="bot-btn"
+                          >缂栬緫鍚嶇О</el-button>
+                        </div>
+                        <div class="list-complete-item-handle">
+                          <!-- <span :class="`iconfont ${item.icon}`" style="font-size:3rem;"></span> -->
+                          <div class="svg-wrap">
+                            <svg class="icon" aria-hidden="true" style="font-size:7rem;">
+                              <use :xlink:href="`#${item.icon}`" />
+                            </svg>
+                          </div>
+                          <div class="alg-name">
+                            <div style="padding:0px 10px 0px 10px;">
+                              <span v-if="!item.isEdit">{{ item.sdk_name }}</span>
+
+                              <el-input
+                                size="small"
+                                v-model="item.sdk_name"
+                                v-if="item.isEdit"
+                                v-focus
+                                :maxlength="15"
+                                @blur="inputBlur(item)"
+                              ></el-input>
+                            </div>
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+                    <!-- </draggable> -->
+                    <div class="wrap-box" v-for="(item) in notInstalledList" :key="item.id">
+                      <div
+                        class="list-choose-item-left list-choose-item-left-uninstal"
+                        v-loading="downloading && downloadItem == item.id"
+                      >
+                        <div class="mask">
+                          <el-button type="primary" class="bot-btn" @click="donwload(item)">瀹夎</el-button>
+                        </div>
+                        <div class="click-download" title="涓嬭浇">
+                          <span class="iconfont iconxiazai1"></span>
+                        </div>
+                        <div class="list-complete-item-handle">
+                          <!-- <span :class="`iconfont ${item.icon}`" style="font-size:3rem;"></span> -->
+                          <div class="svg-wrap">
+                            <svg class="icon" aria-hidden="true" style="font-size:7rem;">
+                              <use :xlink:href="`#${item.icon}`" />
+                            </svg>
+                          </div>
+                          <div class="alg-name">
+                            <div style="padding:0px 10px 0px 10px;">
+                              <span class="list-choose-item-left-uninstal">{{ item.sdk_name }}</span>
+                            </div>
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+                  </div>
+                  <!-- 鏈笅杞� -->
+                </div>
+              </el-tab-pane>
+
+              <el-tab-pane
+                label="绂荤嚎鍗囩骇/瀹夎"
+                name="upgradeOrInstallation"
+                v-show="activeName==='upgradeOrInstallation'"
+              >
+                <div class="tab-content">
+                  <div class="action-bar">
+                    <file-uploader
+                      single
+                      tip
+                      tipWords="涓婁紶绠楁硶"
+                      uploadPlaceholder="绂荤嚎瀹夎绠楁硶"
+                      url="/data/api-v/sdk/upload"
+                      @complete="onFileUpload"
+                      @file-added="onFileAdded"
+                    />
+                  </div>
+                </div>
+              </el-tab-pane>
+              <el-tab-pane label="绠楁硶鍟嗗煄" name="algorithmMall" v-show="activeName==='algorithmMall'">
+                <div class="tab-content">
+                  <div class="store-list">
+                    <div class="wrap-box">
+                      <div class="inner">
+                        <div class="mask" @click="actDrawerShow=true">
+                          <svg class="icon" aria-hidden="true" style="font-size:2rem;">
+                            <use xlink:href="#iconyunxiazai" />
+                          </svg>
+                        </div>
+                        <div class="alg-icon">
+                          <svg class="icon" aria-hidden="true" style="font-size:7rem;">
+                            <use xlink:href="#iconrenyuanyidong" />
+                          </svg>
+                        </div>
+                        <div class="alg-name">name</div>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+                <el-drawer title="涓嬭浇" :visible.sync="actDrawerShow" :direction="direction">
+                  <div class="drawer-content">
+                    <div class="current-step">
+                      <el-steps align-center :active="actStep" finish-status="success">
+                        <el-step title="娣诲姞婵�娲荤爜"></el-step>
+                        <el-step title="婵�娲绘垚鍔�"></el-step>
+                      </el-steps>
+                    </div>
+
+                    <div v-if="actStep==0">
+                      <div class="act-code">
+                        <p>浣跨敤婵�娲荤爜灏嗘柊鐨勭畻娉曟坊鍔犲埌鎮ㄧ殑璐︽埛</p>
+                        <el-input
+                          v-model="activeCode"
+                          placeholder="00000-00000-00000-00000-00000"
+                          @blur="getCodeDetail"
+                        ></el-input>
+                      </div>
+                      <div class="text-right">
+                        <el-button type="primary" @click="actived">婵�娲�</el-button>
+                      </div>
+                    </div>
+                    <div v-else-if="actStep==1">
+                      <ul class="desc">
+                        <li>
+                          <label>婵�娲荤爜:</label>
+                          <span>YUAAA-AAAEU-QJQE3-ZRRXD-K9MWR</span>
+                        </li>
+                        <li>
+                          <label>浜у搧鍚嶇О:</label>
+                          <span>浜哄憳璺熻釜SDK</span>
+                        </li>
+                        <li>
+                          <label>閰嶇疆璇︽儏:</label>
+                          <span>鏃�</span>
+                        </li>
+                        <li>
+                          <label>鏈嶅姟鍒版湡鏃�:</label>
+                          <span>2021-03-04</span>
+                        </li>
+                        <li>
+                          <label>璁稿彲璇�:</label>
+                          <span>鏈澶�</span>
+                        </li>
+                        <li>
+                          <label>璁惧ID:</label>
+                          <span>3342-235f-ret55-fdsg</span>
+                        </li>
+                      </ul>
+                      <div class="text-right">
+                        <el-button type="primary" @click="checkMyAlgorith">纭畾</el-button>
+                        <p class="tip">鎻愮ず锛氳鍦ㄢ�滄垜鐨勭畻娉曗�濅腑鏌ョ湅骞跺畨瑁呯畻娉�</p>
+                      </div>
+                    </div>
+                  </div>
+                </el-drawer>
+              </el-tab-pane>
+            </el-tabs>
+          </div>
+
+          <!-- 绠楁硶绠$悊 -->
+          <!-- <div class="right-box" style="width:58%">
+        <div class="title">
+          <label>绠楁硶绠$悊</label>
+          <el-button size="small" type="primary" @click="addTask" style="float:right">娣诲姞浠诲姟</el-button>
+        </div>
+        <div id="taskArea" class="width-new-line task-manage-table">
+          <div
+            v-for="(row, Index) in TaskMange.list2"
+            :key="Index"
+            class="dic-border mb10 width-new-line"
+          >
+            <div class="flex-box" style="height:100%;">
+              <div class="task-name-google">
+                <div class="mask" v-if="!row.isSetting">
+                  <el-tooltip
+                    content="缂栬緫鍚嶇О"
+                    transition="none"
+                    placement="left"
+                    popper-class="atooltip"
+                  >
+                    <i
+                      class="iconfont iconbianji1"
+                      style="font-size:30px; left:14px; top:30px;"
+                      @click="clickSet(row)"
+                    ></i>
+                  </el-tooltip>
+                  <el-tooltip
+                    content="鍒犻櫎浠诲姟"
+                    transition="none"
+                    placement="right"
+                    popper-class="atooltip"
+                  >
+                    <i
+                      class="iconfont iconshanchu4"
+                      style="font-size:30px; color:red; top:30px; left:28px;"
+                      @click="clickDel(row, Index)"
+                    ></i>
+                  </el-tooltip>
+                  <el-tooltip
+                    :content="`${row.enable ? '鍏抽棴浠诲姟' : '寮�鍚换鍔�'}`"
+                    placement="left"
+                    popper-class="atooltip"
+                    transition="none"
+                    style="left: -45px; top: 65px;"
+                  >
+                    <el-switch
+                      :active-value="true"
+                      :inactive-value="false"
+                      v-model="row.enable"
+                      @change="updateTaskStatus(row)"
+                    ></el-switch>
+                  </el-tooltip>
+                  <el-tooltip
+                    content="淇敼鍥炬爣"
+                    transition="none"
+                    placement="right"
+                    popper-class="atooltip"
+                  >
+                    <i class="iconfont icontupian1" style="font-size:12px; left:-20px; top:65px;"></i>
+                  </el-tooltip>
+                </div>
+                <div class="list-choose-header flex-center">
+                  <span class="iconfont iconrenwu" style="font-size:3rem;color:#fff;"></span>
+                </div>
+                <div class="task-name-div">
+                  <span :title="row.name" v-if="!row.isSetting">{{ row.name }}</span>
+                  <el-input
+                    size="small"
+                    v-model="row.name"
+                    v-if="row.isSetting"
+                    v-focus
+                    :maxlength="15"
+                    style="width:120px"
+                    @blur="updateTaskName(row)"
+                  ></el-input>
+                </div>
+              </div>
+
+              <div id="child" class="overflow-x">
+                <draggable
+                  :id="row.id"
+                  :list="row.child"
+                  group="article"
+                  filter=".mask"
+                  class="dragAreaR flex-box"
+                  @start="startRight"
+                  @end="endLeft"
+                >
+                  <div
+                    v-for="(item, index) in row.child"
+                    :key="index"
+                    :title="item.sdk_name"
+                    :class="
+                        item.isSelect
+                          ? 'list-choose-item alg-shadow'
+                          : 'list-choose-item'
+                      "
+                  >
+                    <div class="mask">
+                      <el-tooltip
+                        content="璁剧疆"
+                        transition="none"
+                        placement="top"
+                        popper-class="atooltip"
+                      >
+                        <i
+                          class="iconfont iconshezhi"
+                          style="font-size:15px; top:43px;"
+                          @click="clickSetAlgo(row, item)"
+                        ></i>
+                      </el-tooltip>
+                      <el-tooltip
+                        content="鍒犻櫎绠楁硶"
+                        transition="none"
+                        placement="top"
+                        popper-class="atooltip"
+                      >
+                        <i
+                          class="iconfont iconshanchu4"
+                          style="font-size: 30px; color:red; left:12px;"
+                          @click="clickDelSdk(row, item)"
+                        ></i>
+                      </el-tooltip>
+                    </div>
+                    <div class style="height:100%;padding: 20px 10px 10px 10px;">
+                      <div class="flex-center" style>
+                        <span
+                          :class="`iconfont ${item.icon}`"
+                          style="font-size:3rem;margin-left:5px;"
+                        ></span>
+                      </div>
+                      <div
+                        :class="item.isSelect?'select-color text-css':'task-name text-css'"
+                        style
+                      >{{ item.sdk_name }}</div>
+                    </div>
+                  </div>
+                  <div style class="tc drag-info flex-center">
+                    <div class="drag-info-text">
+                      <span>鎷栧姩绠楁硶鍥炬爣鍒拌繖閲�</span>
+                    </div>
+                  </div>
+                </draggable>
+              </div>
+            </div>
+
+            <div class v-if="row.isShowSetAlgo">
+              <div class="b-top">
+                <div class="flex-box mt10">
+                  <span class="alg-t ml10 mr10 fb">绠楁硶閰嶇疆</span>
+                </div>
+                <div style="border: 1px solid #EBEBEB;"></div>
+                <div>
+                  <div class="p5">
+                    <div v-for="(temp, index) in TaskMange.argsList" :key="index" class="p5 ml50">
+                      <el-row :gutter="2">
+                        <el-col :span="4">
+                          <el-select
+                            v-model="temp.value1"
+                            placeholder="璇烽�夋嫨"
+                            width="200px"
+                            disabled
+                            @change="selectChange($event, 'options1', temp)"
+                          >
+                            <el-option
+                              v-for="item in temp.options1"
+                              :key="item.id"
+                              :label="item.name"
+                              :value="item.value"
+                            ></el-option>
+                          </el-select>
+                        </el-col>
+                        <el-col :span="4">
+                          <el-select
+                            v-model="temp.value2"
+                            placeholder="璇烽�夋嫨"
+                            @change="selectChange($event, 'options2', temp)"
+                          >
+                            <el-option
+                              v-for="item in temp.options2"
+                              :key="item.id"
+                              :label="item.name"
+                              :value="item.value"
+                            ></el-option>
+                          </el-select>
+                        </el-col>
+                        <el-col :span="12">
+                          <div v-if="temp.value2 === 'is'">
+                            <el-select
+                              v-model="temp.value3"
+                              placeholder="璇烽�夋嫨"
+                              @change="selectChange($event, 'options3', temp)"
+                            >
+                              <el-option
+                                v-for="item in temp.options3"
+                                :key="item.id"
+                                :label="item.name"
+                                :value="item.value"
+                              ></el-option>
+                            </el-select>
+                          </div>
+                          <div v-else class="flex-row-left">
+                            <div>
+                              <el-input
+                                v-model="temp.value3"
+                                placeholder="璇疯緭鍏�"
+                                @blur="valiNum(temp.value3)"
+                              ></el-input>
+                            </div>
+                            <div v-if="temp.unit" class="unit-class">
+                              <span>(鍗曚綅锛歿{ temp.unit }})</span>
+                            </div>
+                          </div>
+                        </el-col>
+                      </el-row>
+                    </div>
+                  </div>
+                </div>
+                <div class="flex-row-right" style="margin: 0px 25px 5px 0px;">
+                  <a
+                    style="font-family: PingFangSC-Medium;line-height: 32px;
+                              font-size: 13px;text-decoration:underline;
+                              color: #3D68E1;margin-right: 28px;"
+                    @click="getDefault"
+                  >鎭㈠榛樿鍊�</a>
+                  <el-button type="info" size="small" class="mb10" @click="cancle(row)">鍙栨秷</el-button>
+                  <el-button type="primary" size="small" class="mr50 mb10" @click="save">淇濆瓨</el-button>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+          </div>-->
+        </div>
+        <!-- 涓�鑸敤鎴峰彲瑙� -->
+        <div class="common" v-if="!isSuperUser">
+          <!-- 绠楁硶绠$悊 -->
+          <!-- <div class="right-box" style="width:84%;margin:auto 8%">
+            <div class="title">
+              <label>绠楁硶绠$悊</label>
+              <el-button
+                size="small"
+                type="primary"
+                @click="addTask"
+                style="float:right"
+                v-show="isSuperUser"
+              >娣诲姞浠诲姟</el-button>
+            </div>
+            <div id="taskArea" class="width-new-line task-manage-table">
+              <div
+                v-for="(row, Index) in TaskMange.list2"
+                :key="Index"
+                class="dic-border mb10 width-new-line"
+              >
+                <div class="flex-box" style="height:100%;">
+                  <div class="task-name-google">
+                    <div class="mask" v-if="row.isSetting">
+                      <el-tooltip
+                        content="缂栬緫鍚嶇О"
+                        transition="none"
+                        placement="left"
+                        popper-class="atooltip"
+                      >
+                        <i
+                          class="iconfont iconbianji1"
+                          style="font-size:30px; left:14px; top:30px;"
+                          @click="clickSet(row)"
+                        ></i>
+                      </el-tooltip>
+                      <el-tooltip
+                        content="鍒犻櫎浠诲姟"
+                        transition="none"
+                        placement="right"
+                        popper-class="atooltip"
+                      >
+                        <i
+                          class="iconfont iconshanchu4"
+                          style="font-size:30px; color:red; top:30px; left:28px;"
+                          @click="clickDel(row, Index)"
+                        ></i>
+                      </el-tooltip>
+                      <el-tooltip
+                        :content="`${row.enable ? '鍏抽棴浠诲姟' : '寮�鍚换鍔�'}`"
+                        placement="left"
+                        popper-class="atooltip"
+                        transition="none"
+                        style="left: -45px; top: 65px;"
+                      >
+                        <el-switch
+                          :active-value="true"
+                          :inactive-value="false"
+                          v-model="row.enable"
+                          @change="updateTaskStatus(row)"
+                        ></el-switch>
+                      </el-tooltip>
+                      <el-tooltip
+                        content="淇敼鍥炬爣"
+                        transition="none"
+                        placement="right"
+                        popper-class="atooltip"
+                      >
+                        <i
+                          class="iconfont icontupian1"
+                          style="font-size:12px; left:-20px; top:65px;"
+                        ></i>
+                      </el-tooltip>
+                    </div>
+                    <div class="list-choose-header flex-center">
+                      <span class="iconfont iconrenwu" style="font-size:3rem;color:#fff;"></span>
+                    </div>
+                    <div class="task-name-div">
+                      <span :title="row.name" v-if="!row.isSetting">{{ row.name }}</span>
+                      <el-input
+                        size="small"
+                        v-model="row.name"
+                        v-if="row.isSetting"
+                        v-focus
+                        :maxlength="15"
+                        style="width:120px"
+                        @blur="updateTaskName(row)"
+                      ></el-input>
+                    </div>
+                  </div>
+
+                  <div id="child" class="overflow-x">
+                    <div
+                      :id="row.id"
+                      :list="row.child"
+                      group="article"
+                      filter=".child"
+                      class="dragAreaR flex-box"
+                      @start="startRight"
+                      @end="endLeft"
+                    >
+                      <div
+                        v-for="(item, index) in row.child"
+                        :key="index"
+                        :title="item.sdk_name"
+                        :class="
+                        item.isSelect
+                          ? 'list-choose-item alg-shadow'
+                          : 'list-choose-item'
+                      "
+                      >
+                        <div class="mask">
+                          <el-tooltip
+                            content="璁剧疆"
+                            transition="none"
+                            placement="top"
+                            popper-class="atooltip"
+                          >
+                            <i
+                              class="iconfont iconshezhi"
+                              style="font-size:15px; top:43px;"
+                              @click="clickSetAlgo(row, item)"
+                            ></i>
+                          </el-tooltip>
+                          <el-tooltip
+                            content="鍒犻櫎绠楁硶"
+                            transition="none"
+                            placement="top"
+                            popper-class="atooltip"
+                            v-show="isSuperUser"
+                          >
+                            <i
+                              class="iconfont iconshanchu4"
+                              style="font-size: 30px; color:red; left:12px;"
+                              @click="clickDelSdk(row, item)"
+                            ></i>
+                          </el-tooltip>
+                        </div>
+                        <div class style="height:100%;padding: 20px 10px 10px 10px;">
+                          <div class="flex-center" style>
+                            <span
+                              :class="`iconfont ${item.icon}`"
+                              style="font-size:3rem;margin-left:5px;"
+                            ></span>
+                          </div>
+                          <div
+                            :class="item.isSelect?'select-color text-css':'task-name text-css'"
+                            style
+                          >{{ item.sdk_name }}</div>
+                        </div>
+                      </div>
+                      <div style class="tc drag-info flex-center" v-show="isSuperUser">
+                        <div class="drag-info-text">
+                          <span>鎷栧姩绠楁硶鍥炬爣鍒拌繖閲�</span>
+                        </div>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+
+                <div class v-if="row.isShowSetAlgo">
+                  <div class="b-top">
+                    <div class="flex-box mt10">
+                      <span class="alg-t ml10 mr10 fb">绠楁硶閰嶇疆</span>
+                    </div>
+                    <div style="border: 1px solid #EBEBEB;"></div>
+                    <div>
+                      <div class="p5">
+                        <div
+                          v-for="(temp, index) in TaskMange.argsList"
+                          :key="index"
+                          class="p5 ml50"
+                        >
+                          <el-row :gutter="2">
+                            <el-col :span="4">
+                              <el-select
+                                v-model="temp.value1"
+                                placeholder="璇烽�夋嫨"
+                                width="200px"
+                                disabled
+                                @change="selectChange($event, 'options1', temp)"
+                              >
+                                <el-option
+                                  v-for="item in temp.options1"
+                                  :key="item.id"
+                                  :label="item.name"
+                                  :value="item.value"
+                                ></el-option>
+                              </el-select>
+                            </el-col>
+                            <el-col :span="4">
+                              <el-select
+                                v-model="temp.value2"
+                                placeholder="璇烽�夋嫨"
+                                disabled
+                                @change="selectChange($event, 'options2', temp)"
+                              >
+                                <el-option
+                                  v-for="item in temp.options2"
+                                  :key="item.id"
+                                  :label="item.name"
+                                  :value="item.value"
+                                ></el-option>
+                              </el-select>
+                            </el-col>
+                            <el-col :span="12">
+                              <div v-if="temp.value2 === 'is'">
+                                <el-select
+                                  v-model="temp.value3"
+                                  placeholder="璇烽�夋嫨"
+                                  @change="selectChange($event, 'options3', temp)"
+                                >
+                                  <el-option
+                                    v-for="item in temp.options3"
+                                    :key="item.id"
+                                    :label="item.name"
+                                    :value="item.value"
+                                  ></el-option>
+                                </el-select>
+                              </div>
+                              <div v-else class="flex-row-left">
+                                <div>
+                                  <el-input
+                                    v-model="temp.value3"
+                                    placeholder="璇疯緭鍏�"
+                                    :disabled="temp.value1 !== 'score'"
+                                    @blur="valiNum(temp.value3)"
+                                  ></el-input>
+                                </div>
+                                <div v-if="temp.unit" class="unit-class">
+                                  <span>(鍗曚綅锛歿{ temp.unit }})</span>
+                                </div>
+                              </div>
+                            </el-col>
+                          </el-row>
+                        </div>
+                      </div>
+                    </div>
+                    <div class="flex-row-right" style="margin: 0px 25px 5px 0px;">
+                      <a
+                        style="font-family: PingFangSC-Medium;line-height: 32px;
+                              font-size: 13px;text-decoration:underline;
+                              color: #3D68E1;margin-right: 28px;"
+                        @click="getDefault"
+                        v-show="isSuperUser"
+                      >鎭㈠榛樿鍊�</a>
+                      <el-button type="info" size="small" class="mb10" @click="cancle(row)">鍙栨秷</el-button>
+                      <el-button type="primary" size="small" class="mr50 mb10" @click="save">淇濆瓨</el-button>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div> -->
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+
+import {
+  findAllSdk,
+  findAll,
+  addTaskSdk,
+  delTaskSdk,
+  deleteTask,
+  updateTaskStatus,
+  updateTaskName,
+  getSdkArgs,
+  saveTaskSdkRule,
+  addTask,
+  getRulesByTaskSdk,
+  deleteTaskSdkRule,
+  findByType,
+  getTagList,
+  downloadSdk,
+  installSdk
+} from "./api";
+import FileUploader from "@/components/subComponents/FileUpload/index";
+
+export default {
+  name: "algorithmManage",
+  props: {},
+  components: {
+    FileUploader
+  },
+  
+  data() {
+    return {
+      activeName: "myAlgorithm",
+      patchUpdateStatus: "",
+      dragging: false,
+      list1: [
+        {
+          sdk_name: "浜鸿劯鎻愬彇"
+        }
+      ],
+      list2: [
+        {
+          id: "001",
+          name: "浠诲姟1",
+          child: [
+            {
+              id: "1",
+              sdk_name: "浜鸿劯妫�娴�",
+              isSelect: false
+            },
+            {
+              id: "2",
+              sdk_name: "浜鸿劯瀵规瘮",
+              isSelect: false
+            }
+          ],
+          isSetting: false,
+          isShowSetAlgo: false
+        }
+      ],
+      argsList: [],
+      baseObject: {
+        id: "",
+        algoId: "",
+        options1: [],
+        options2: [],
+        options3: [],
+        value1: "",
+        value2: "",
+        value3: "",
+        unit: ""
+      },
+      currentAlgoId: "",
+      currentTaskId: "",
+      isSuperUser: false,
+      downloadItem: "",
+      downloading: false,
+      sceneDialogVisible: false,
+      dialogTitle: '',
+      direction: "rtl",
+      actDrawerShow: false,
+      actStep: 0,
+      activeCode: "",
+      sceneTemplates: [],
+      appSceneForm: {
+        id: "",
+        name: "",
+        desc: "",
+        rules: "",
+        txt: ""
+      },
+      sceneSdks: [],
+      sceneRuleList: "",
+      isInstall: false,
+      installPercentage: 0
+    }
+  },
+  methods: {},
+  mounted() {}
+};
+</script>
+<style lang="scss">
+.s-task-manage {
+  width: 100% !important;
+  height: 100%;
+  
+  box-sizing: border-box;
+  background-color: rgb(233, 235, 242);
+  padding: 10px;
+  text-align: left;
+  // background-color: #f2f6fc;
+  .s-video-manage-breadcrumb {
+    height: 5%;
+    -webkit-box-sizing: border-box;
+    border: 1px solid #e4e7ed;
+    background-color: rgb(255, 255, 255);
+    -webkit-box-shadow: #e4e7ed 0px 0px 9px inset;
+    box-shadow: #e4e7ed 0px 0px 9px inset;
+    border-radius: 5px;
+  }
+  .el-tabs {
+    height: calc(100% - 50px);
+    // margin-top: 5px !important;
+  }
+  .el-tabs--border-card > .el-tabs__header {
+    border: none;
+  }
+  .el-tabs__item.is-top {
+    height: 50px;
+    padding: 5px 50px !important;
+    font-size: 15px;
+    border: none !important;
+  }
+  .el-tabs__item.is-top.is-active {
+    font-weight: bold;
+  }
+  .el-tabs__content {
+    width: 100%;
+    height: calc(100% - 34px);
+    box-sizing: border-box;
+  }
+  .el-tab-pane {
+    width: 100%;
+    height: 100%;
+  }
+}
+.el-breadcrumb__inner {
+  font-weight: bold;
+  color: #606266;
+  cursor: pointer;
+}
+</style>
diff --git a/src/pages/algorithmManage/index/api.ts b/src/pages/algorithmManage/index/api.ts
new file mode 100644
index 0000000..64ecdad
--- /dev/null
+++ b/src/pages/algorithmManage/index/api.ts
@@ -0,0 +1,145 @@
+import request from '@/scripts/httpRequest'
+import qs from "qs";
+
+// 鏌ヨ鎵�鏈夌畻娉�
+export const findAllSdk = (query: any) => {
+  return request({
+    url: "/data/api-v/sdk/findAllSdk",
+    method: "get",
+    params: query
+  });
+};
+
+// 鏌ユ壘鎵�鏈変换鍔★紝鍖呭惈浠诲姟淇℃伅鍜屽搴旂殑绠楁硶淇℃伅
+export const findAll = (query: any) => {
+  return request({
+    url: "/data/api-v/task/findAll",
+    method: "get",
+    params: query
+  });
+};
+
+// 缁欎换鍔℃坊鍔犵畻娉�
+export const addTaskSdk = (query: any) => {
+  return request({
+    url: "/data/api-v/task/addTaskSdk",
+    method: "post",
+    data: query
+  })
+}
+
+// 缁欎换鍔″垹闄ょ畻娉�
+export const delTaskSdk = (query: any) => {
+  return request({
+    url: "/data/api-v/task/delTaskSdk",
+    method: 'get',
+    params: query
+  })
+}
+
+// 鍒犻櫎浠诲姟
+export const deleteTask = (query: any) => {
+  return request({
+    url: '/data/api-v/task/delete',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鏇存柊浠诲姟鐘舵��
+export const updateTaskStatus = (query: any) => {
+  return request({
+    url: '/data/api-v/task/updateTaskStatus',
+    method: 'post',
+    data: query
+  })
+}
+
+// 鏇存柊浠诲姟鍚嶇О
+export const updateTaskName = (query: any) => {
+  return request({
+    url: '/data/api-v/task/updateTaskName',
+    method: 'post',
+    data: qs.stringify(query)
+  })
+}
+
+// 鑾峰彇绠楁硶鍙傛暟
+export const getSdkArgs = (query: any) => {
+  return request({
+    url: '/data/api-v/sdkArg/getSdkArgs',
+    method: 'get',
+    params: query
+  })
+}
+
+// 绠楁硶鍙傛暟淇濆瓨
+export const saveTaskSdkRule = (query: any) => {
+  return request({
+    url: '/data/api-v/task/saveTaskSdkRule',
+    method: 'post',
+    data: query
+  })
+}
+
+// 娣诲姞浠诲姟
+export const addTask = (query: any) => {
+  return request({
+    url: '/data/api-v/task/addTask',
+    method: 'post',
+    data: query
+  })
+}
+
+// 鏌ヨ绠楁硶瑙勫垯
+export const getRulesByTaskSdk = (query: any) => {
+  return request({
+    url: '/data/api-v/task/getRulesByTaskSdk',
+    method: 'get',
+    params: query
+  })
+}
+
+// 鎭㈠榛樿
+export const deleteTaskSdkRule = (query: any) => {
+  return request({
+    url: '/data/api-v/task/deleteTaskSdkRule',
+    method: 'post',
+    data: qs.stringify(query)
+  })
+}
+
+// 鏍规嵁绫诲瀷鏌ユ壘瀛楀吀
+export const findByType = (query: any) => {
+  return request({
+    url: '/data/api-v/dictionary/findByType',
+    method: "get",
+    params: query
+  })
+}
+
+// 鏌ヨ妫�绱㈡爣绛�
+export const getTagList = (query: any) => {
+  return request({
+    url: '/data/api-v/es/tagList',
+    method: 'post',
+    data: query
+  })
+}
+
+export const downloadSdk = (query: any) => {
+  return request({
+    url: '/data/api-v/sdk/sdkDownload',
+    method: 'get',
+    params: query
+  })
+}
+
+//瀹夎宸蹭笂浼犵殑绠楁硶鎺ュ彛
+export const installSdk = (file: any) => {
+  return request({
+    url: '/data/api-v/sdk/install',
+    method: 'post',
+    params: file
+  })
+}
\ No newline at end of file
diff --git a/src/pages/algorithmManage/index/main.ts b/src/pages/algorithmManage/index/main.ts
new file mode 100644
index 0000000..264f7e4
--- /dev/null
+++ b/src/pages/algorithmManage/index/main.ts
@@ -0,0 +1,11 @@
+import Vue from 'vue'
+import ElementUI from 'element-ui'
+import 'element-ui/lib/theme-chalk/index.css'
+import App from './App.vue'
+
+Vue.use(ElementUI)
+
+new Vue({
+  el: '#app',
+  render: h => h(App)
+})
diff --git a/src/pages/desktop/index/App.vue b/src/pages/desktop/index/App.vue
index b58209a..aaa21d5 100644
--- a/src/pages/desktop/index/App.vue
+++ b/src/pages/desktop/index/App.vue
@@ -3,6 +3,7 @@
     <tools></tools>
     <preference></preference>
     <desktop></desktop>
+    <tools-entry></tools-entry>
     <dock ref="dock_model"></dock>
     <notice-tip ref="notice_tip_model"></notice-tip>
     <notification-center></notification-center>
@@ -16,12 +17,13 @@
 import NotificationCenter from './components/NotificationCenter';
 import NoticeTip from './components/NoticeTip';
 import Tools from './components/Tools';
+import ToolsEntry from './components/ToolsEntry';
 import axios from 'axios'
 
 export default {
   name: 'app',
   components: {
-    Desktop, Dock, Preference, NotificationCenter, NoticeTip, Tools
+    Desktop, Dock, Preference, NotificationCenter, NoticeTip, Tools, ToolsEntry
   },
   mounted() {
     document.getElementById('app').style.backgroundImage = process.env.VUE_APP_MAIN_URL;
@@ -113,6 +115,14 @@
   width: 100%;
   height: 100%;
   background-size: 100% 100%;
-  background-image: url("../../../assets/img/desktop/main.jpg");
+  background-image: url("../../../assets/img/desktop/desktop.png");
+  background-attachment: fixed;
+}
+
+.clearFix:after{
+  content: '';
+  display: block;
+  height: 0;
+  clear: both;
 }
 </style>
diff --git a/src/pages/desktop/index/components/Dock.vue b/src/pages/desktop/index/components/Dock.vue
index 4a6bcd3..68e3d4a 100644
--- a/src/pages/desktop/index/components/Dock.vue
+++ b/src/pages/desktop/index/components/Dock.vue
@@ -10,10 +10,10 @@
           <span>{{dock.alt}}</span>
           <img class="dock-item" :src="dock.src" :alt="dock.alt" />
         </a>
-        <img v-show="dock.isOpen" class="dock-item-dot" src="images/circle.png" />
+        <img v-show="dock.isOpen" class="dock-item-dot" :src="`${publicPath}images/circle.png`" />
       </div>
       <a class="dock-item-split">
-        <img src="images/split.jpg" alt="split" />
+        <img :src="`${publicPath}images/split.jpg`" alt="split" />
       </a>
       <div v-for="dock in this.$store.state.desktop.minDocks" :key="dock.id" class="dock-item-wrap">
         <a @click="dockClick(dock)">
@@ -24,7 +24,7 @@
       <div class="dock-item-wrap">
         <a>
           <span>trash</span>
-          <img class="dock-item" src="images/trash.png" alt="trash" />
+          <img class="dock-item" :src="`${publicPath}images/trash.png`" alt="trash" />
         </a>
       </div>
     </div>
@@ -35,6 +35,14 @@
 
 export default {
   name: "Dock",
+  data(){
+    return {
+      publicPath: process.env.BASE_URL
+    }
+  },
+  mounted(){
+    console.log(this.publicPath)
+  },
   methods: {
     getOffsetTop: function (el) {
       if (el.offsetParent == null) {
diff --git a/src/pages/desktop/index/components/Tools.vue b/src/pages/desktop/index/components/Tools.vue
index ea2a2b0..385e1d2 100644
--- a/src/pages/desktop/index/components/Tools.vue
+++ b/src/pages/desktop/index/components/Tools.vue
@@ -1,36 +1,53 @@
 <template>
   <div class="tools">
-    <div class="tools-left">
-      <div
-        :class="['tools-icon', {clicked:this.$store.state.desktop.preferenceVisiable}]"
-        @click="togglePreference()"
-      >
-        <span class="fa fa-apple"></span>
+    <div class="center">
+      <div class="tools-left">
+        <div
+          :class="['tools-icon', {clicked:this.$store.state.desktop.preferenceVisiable}]"
+          @click="togglePreference()"
+        >
+          <img class="system" :src="`${publicPath}images/header-icon/system.png`" />
+          <!-- <span class="fa fa-apple"></span> -->
+        </div>
+        <div class="tools-icon" @click="openSafari()">
+          <!-- <span class="fa fa-safari"></span> -->
+          <img class="smart-ai" :src="`${publicPath}images/header-icon/SmartAI.png`" alt="">
+        </div>
       </div>
-      <div class="tools-icon" @click="openSafari()">
-        <span class="fa fa-safari"></span>
-      </div>
-    </div>
-    <div class="tools-middle"></div>
-    <div class="tools-right">
-      <div class="tools-icon">
-        <span class="fa fa-battery-full"></span>
-      </div>
-      <timer></timer>
-      <div class="tools-icon tools-notification-center" @click="notificationCenterClick()">
-        <span
-          :class="['fa', {'fa-list-ul':notificationCenterNoMessage()}, {'fa-comment-o on-new-msg':!notificationCenterNoMessage()},{'fa-commenting-o':notificationCenterMessageFlicker()}]"
-        ></span>
-      </div>
-      <div class="tools-icon tools-show-desktop">
-        <span>&nbsp;</span>
+      <div class="tools-middle"></div>
+      <div class="tools-right">
+        <div class="tools-icon">
+          <!-- <span class="fa fa-battery-full"></span> -->
+          <img :src="`${publicPath}images/header-icon/search.png`" alt="">
+        </div>
+        <div class="tools-icon">
+          <!-- <span class="fa fa-battery-full"></span> -->
+          <img :src="`${publicPath}images/header-icon/help.png`" alt="">
+        </div>
+        <div class="tools-icon">
+          <!-- <span class="fa fa-battery-full"></span> -->
+          <img :src="`${publicPath}images/header-icon/notice.png`" alt="">
+        </div>
+        <div class="tools-icon">
+          <!-- <span class="fa fa-battery-full"></span> -->
+          <img :src="`${publicPath}images/header-icon/user.png`" alt="">
+        </div>
+        <!-- <timer></timer> -->
+        <div class="tools-icon tools-notification-center" @click="notificationCenterClick()">
+          <span
+            :class="['fa', {'fa-list-ul':notificationCenterNoMessage()}, {'fa-comment-o on-new-msg':!notificationCenterNoMessage()},{'fa-commenting-o':notificationCenterMessageFlicker()}]"
+          ></span>
+        </div>
+        <div class="tools-icon tools-show-desktop">
+          <span>&nbsp;</span>
+        </div>
       </div>
     </div>
   </div>
 </template>
 
 <script>
-import Timer from './Timer';
+import Timer from "./Timer";
 
 export default {
   name: "Tools",
@@ -39,40 +56,47 @@
   },
   data() {
     return {
+      publicPath: process.env.BASE_URL,
       notificationCenterVisible: false,
-      notificationCenterMessageCount: 0,
-    }
+      notificationCenterMessageCount: 0
+    };
   },
   created() {
     let _that = this;
     if (window.toolIntervalArr) {
       window.toolIntervalArr.forEach(item => clearInterval(item));
     }
-    window.toolIntervalArr = [setInterval(function () {
-      _that.notificationCenterMessageCount += 1;
-    }, 600)];
+    window.toolIntervalArr = [
+      setInterval(function() {
+        _that.notificationCenterMessageCount += 1;
+      }, 600)
+    ];
   },
   methods: {
-    notificationCenterClick: function () {
+    notificationCenterClick: function() {
       this.notificationCenterVisible = !this.notificationCenterVisible;
-      this.$store.commit('desktop/changeNotificationCenterVisible',
-        this.notificationCenterVisible);
+      this.$store.commit(
+        "desktop/changeNotificationCenterVisible",
+        this.notificationCenterVisible
+      );
     },
-    notificationCenterNoMessage: function () {
+    notificationCenterNoMessage: function() {
       return this.$store.state.desktop.messageNotices.length === 0;
     },
-    notificationCenterMessageFlicker: function () {
-      return ((this.notificationCenterMessageCount % 2) === 0)
-        && !this.notificationCenterNoMessage();
+    notificationCenterMessageFlicker: function() {
+      return (
+        this.notificationCenterMessageCount % 2 === 0 &&
+        !this.notificationCenterNoMessage()
+      );
     },
-    openSafari: function () {
+    openSafari: function() {
       this.$store.commit("desktop/openSafari");
     },
-    togglePreference: function () {
+    togglePreference: function() {
       this.$store.commit("desktop/togglePreference");
     }
   }
-}
+};
 </script>
 
 <style scoped>
@@ -80,31 +104,39 @@
   width: 100%;
   position: fixed;
   top: 0;
-  height: 30px;
-  line-height: 30px;
-  background-color: rgba(15, 15, 0, 0.4);
+  height: 40px;
+  line-height: 40px;
+  background-color: #d9e5f1;
+  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
   z-index: 120;
-  color: #fff;
+  color: #000;
 }
-
+.tools .center {
+  width: 1300px;
+  height: 40px;
+  margin: auto;
+}
 .tools .tools-left {
   width: 200px;
   height: 100%;
   float: left;
   margin-left: 8px;
+
 }
 
 .tools-icon {
   text-align: center;
-  width: 30px;
   height: 100%;
   display: inline-block;
+  vertical-align: top;
+  line-height: 56px;
+  margin-right: 28px;
 }
 
 .tools .tools-icon:hover,
 .tools .tools-icon.clicked {
   color: white;
-  background-color: rgba(49, 156, 241, 0.71);
+  background-color: #98aabe;
   cursor: pointer;
 }
 
diff --git a/src/pages/desktop/index/components/ToolsEntry.vue b/src/pages/desktop/index/components/ToolsEntry.vue
new file mode 100644
index 0000000..adbba7c
--- /dev/null
+++ b/src/pages/desktop/index/components/ToolsEntry.vue
@@ -0,0 +1,95 @@
+<template>
+  <div class="tools-entry">
+    <div class="entry-wrap">
+      <div class="app-list clearFix">
+          <div class="app" v-for="(item,index) in applist" :key="index">
+            <div class="wrap">
+              <div class="app-icon">
+                <img :src="item.src" alt="">
+              </div>
+              <div class="app-name">{{item.name}}</div>
+            </div> 
+          </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name:'toolsEntry',
+  data(){
+    return {
+      publicPath: process.env.BASE_URL,
+      applist:[
+        {src: `/images/app-mid/camera-access.png`, name:'鎽勫儚鏈烘帴鍏�'},
+        {src: `/images/app-mid/datastack-config.png`, name:'鏁版嵁鏍堥厤缃�'},
+        {src: `/images/app-mid/DVR-access.png`, name:'纭洏褰曞儚鏈烘帴鍏�'},
+        {src: `/images/app-mid/data-push.png`, name:'鏁版嵁鎺ㄩ��'},
+        {src: `/images/app-mid/GB-config.png`, name:'GB28281閰嶇疆'},
+        {src: `/images/app-mid/scene-config.png`, name:'鍦烘櫙閰嶇疆'},
+        {src: `/images/app-mid/library.png`, name:'姣斿搴撶鐞�'},
+        {src: `/images/app-mid/poll.png`, name:'杞绠$悊'},
+        {src: `/images/app-mid/algorithm-manage.png`, name:'绠楁硶绠$悊'},
+        {src: `/images/app-mid/algorithm-store.png`, name:'绠楁硶鍟嗗煄'},
+        {src: `/images/app-mid/hashrate-manage.png`, name:'绠楀姏绠$悊'},
+        {src: `/images/app-mid/monitor.png`, name:'瀹炴椂鐩戞帶-鍦ㄧ嚎鎾斁'},
+        {src: `/images/app-mid/search.png`, name:'妫�绱�-缁熻鏌ヨ'},
+        {src: `/images/app-mid/360.png`, name:'鍏ㄦ櫙瑙嗛'},
+        {src: `/images/app-mid/log-manage.png`, name:'鏃ュ織绠$悊'},
+        {src: `/images/app-mid/device.png`, name:'璁惧绠$悊'},
+        {src: `/images/app-mid/settings.png`, name:'绯荤粺璁剧疆'},
+        {src: `/images/app-mid/vindicate.png`, name:'绯荤粺缁存姢'}
+      ]
+    }
+  }
+};
+</script>
+
+<style lang="scss">
+  .tools-entry{
+    //margin-top: 130px;
+    position: absolute;
+    top: 142px;
+    left: 50%;
+    transform: translateX(-50%);
+    .entry-wrap{
+      width: 1180px;
+      padding: 0 60px;
+      margin: 0 auto;
+      .app-list{
+        .app{
+          width: 16.6%;
+          margin-bottom: 54px;
+          float: left;
+          .wrap{
+            .app-icon{
+              text-align: center;
+              line-height: 110px;
+              width: 110px;
+              height: 110px;
+              margin: auto;
+              img{
+                vertical-align: middle;
+                margin-right: -3px;
+              }
+            }
+            .app-name{
+              padding-top: 10px;
+              text-align: center;
+              font: Bold 16px/16px Microsoft JhengHei;
+              color: #fff;
+            }
+          }
+          
+          &:hover{
+            .app-icon{
+              background: rgba(0,0,0,.4);
+            }
+          }
+          
+        }
+      }
+    }
+  }
+</style>
\ 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 1260c13..c5040fd 100644
--- a/src/pages/desktop/index/mock/userData.json
+++ b/src/pages/desktop/index/mock/userData.json
@@ -56,6 +56,13 @@
         "alt": "鍒嗗竷寮忚皟搴�",
         "type": "2",
         "url": "http://www.justlive.vip/center/"
+      },
+      {
+        "id": "9",
+        "src": "../../images/gitee.png",
+        "alt": "绠楁硶绠$悊",
+        "type": "2",
+        "url": "/view/algorithmManage"
       }
     ]
   }
diff --git a/src/pages/index/app.vue b/src/pages/index/app.vue
index 26f9550..320b1ab 100644
--- a/src/pages/index/app.vue
+++ b/src/pages/index/app.vue
@@ -138,8 +138,9 @@
           type: 'success',
           message: '鐧诲綍鎴愬姛锛�'
         })
-        await this.getMenuList()
-        this.$router.push('/Layout/Video')
+        // await this.getMenuList()
+        // this.$router.push('/Layout/Video')
+        location.assign("/view/desktop")
         return json
       } else {
         this.$notify({

--
Gitblit v1.8.0