From 1e3e48e3deacb44e9de1097dbf8d6c42aac71835 Mon Sep 17 00:00:00 2001
From: heyujie <516346543@qq.com>
Date: 星期五, 10 十二月 2021 20:30:45 +0800
Subject: [PATCH] 对比库管理2

---
 src/api/helemt.ts                                        |    8 
 src/pages/internetEquipment/module/historyModule.vue     |    4 
 vue.config.js                                            |    4 
 src/pages/index/components/formNet.vue                   |  141 ++
 src/pages/internetEquipment/views/helemetEquipment.vue   |   19 
 src/pages/login/App.vue                                  |  564 +++++++++
 public/images/map/监控.png                                 |    0 
 src/pages/login/main.ts                                  |   18 
 src/pages/index/components/formInfo.vue                  |  259 ++++
 src/pages/internetEquipment/components/telephoneBox.vue  |  122 ++
 public/images/map/video_20210924_101628.mp4              |    0 
 public/images/map/安全帽-绿.png                              |    0 
 src/pages/index/api.ts                                   |  111 
 public/images/init/背景图.png                               |    0 
 public/images/map/安全帽-红.png                              |    0 
 src/pages/login/api.ts                                   |   66 +
 public/images/map/Group 594.png                          |    0 
 src/pages/index/components/formAccount.vue               |  134 ++
 src/pages/internetEquipment/module/realTimeModule.vue    |   51 
 src/pages/internetEquipment/components/headCard.vue      |  114 
 src/pages/internetData/views/helemtTable.vue             |  197 --
 src/pages/internetEquipment/module/mapIndex.vue          |  717 +++++++++++
 /dev/null                                                |    0 
 public/images/login/OS.png                               |    0 
 src/pages/internetEquipment/components/helemetEchart.vue |    3 
 public/images/login/LOGO.png                             |    0 
 public/images/login/背景图.png                              |    0 
 src/pages/internetEquipment/components/helemetHead.vue   |    2 
 src/pages/index/App.vue                                  |  468 +++---
 src/pages/index/components/IPInput.vue                   |  238 +++
 src/pages/internetEquipment/module/elecModule.vue        |    6 
 src/pages/login/ParticleNetwork.vue                      |  348 +++++
 32 files changed, 3,031 insertions(+), 563 deletions(-)

diff --git "a/public/images/init/\350\203\214\346\231\257\345\233\276.png" "b/public/images/init/\350\203\214\346\231\257\345\233\276.png"
new file mode 100644
index 0000000..4ccfa0c
--- /dev/null
+++ "b/public/images/init/\350\203\214\346\231\257\345\233\276.png"
Binary files differ
diff --git a/public/images/login/0.png b/public/images/login/0.png
deleted file mode 100644
index 2a3591c..0000000
--- a/public/images/login/0.png
+++ /dev/null
Binary files differ
diff --git a/public/images/login/1.png b/public/images/login/1.png
deleted file mode 100644
index 1473d0f..0000000
--- a/public/images/login/1.png
+++ /dev/null
Binary files differ
diff --git a/public/images/login/10.png b/public/images/login/10.png
deleted file mode 100644
index 4deae39..0000000
--- a/public/images/login/10.png
+++ /dev/null
Binary files differ
diff --git a/public/images/login/11.png b/public/images/login/11.png
deleted file mode 100644
index 65b81f6..0000000
--- a/public/images/login/11.png
+++ /dev/null
Binary files differ
diff --git a/public/images/login/12.png b/public/images/login/12.png
deleted file mode 100644
index e966939..0000000
--- a/public/images/login/12.png
+++ /dev/null
Binary files differ
diff --git a/public/images/login/13.png b/public/images/login/13.png
deleted file mode 100644
index c4b1707..0000000
--- a/public/images/login/13.png
+++ /dev/null
Binary files differ
diff --git a/public/images/login/14.png b/public/images/login/14.png
deleted file mode 100644
index 81a9916..0000000
--- a/public/images/login/14.png
+++ /dev/null
Binary files differ
diff --git a/public/images/login/15.png b/public/images/login/15.png
deleted file mode 100644
index ff5110c..0000000
--- a/public/images/login/15.png
+++ /dev/null
Binary files differ
diff --git a/public/images/login/2.png b/public/images/login/2.png
deleted file mode 100644
index ef567b2..0000000
--- a/public/images/login/2.png
+++ /dev/null
Binary files differ
diff --git a/public/images/login/3.png b/public/images/login/3.png
deleted file mode 100644
index fea5da6..0000000
--- a/public/images/login/3.png
+++ /dev/null
Binary files differ
diff --git a/public/images/login/4.png b/public/images/login/4.png
deleted file mode 100644
index edcf594..0000000
--- a/public/images/login/4.png
+++ /dev/null
Binary files differ
diff --git a/public/images/login/5.png b/public/images/login/5.png
deleted file mode 100644
index f81bbbc..0000000
--- a/public/images/login/5.png
+++ /dev/null
Binary files differ
diff --git a/public/images/login/6.png b/public/images/login/6.png
deleted file mode 100644
index f8c318a..0000000
--- a/public/images/login/6.png
+++ /dev/null
Binary files differ
diff --git a/public/images/login/7.png b/public/images/login/7.png
deleted file mode 100644
index 3352e3c..0000000
--- a/public/images/login/7.png
+++ /dev/null
Binary files differ
diff --git a/public/images/login/8.png b/public/images/login/8.png
deleted file mode 100644
index bd1ab6d..0000000
--- a/public/images/login/8.png
+++ /dev/null
Binary files differ
diff --git a/public/images/login/9.png b/public/images/login/9.png
deleted file mode 100644
index 04d1128..0000000
--- a/public/images/login/9.png
+++ /dev/null
Binary files differ
diff --git a/public/images/login/LOGO.png b/public/images/login/LOGO.png
new file mode 100644
index 0000000..5f3d0cb
--- /dev/null
+++ b/public/images/login/LOGO.png
Binary files differ
diff --git a/public/images/login/OS.png b/public/images/login/OS.png
new file mode 100644
index 0000000..b97e7e5
--- /dev/null
+++ b/public/images/login/OS.png
Binary files differ
diff --git "a/public/images/login/\350\203\214\346\231\257\345\233\276.png" "b/public/images/login/\350\203\214\346\231\257\345\233\276.png"
new file mode 100644
index 0000000..1e00181
--- /dev/null
+++ "b/public/images/login/\350\203\214\346\231\257\345\233\276.png"
Binary files differ
diff --git a/public/images/map/Group 594.png b/public/images/map/Group 594.png
new file mode 100644
index 0000000..985d824
--- /dev/null
+++ b/public/images/map/Group 594.png
Binary files differ
diff --git a/public/images/map/video_20210924_101628.mp4 b/public/images/map/video_20210924_101628.mp4
new file mode 100644
index 0000000..fa5ec52
--- /dev/null
+++ b/public/images/map/video_20210924_101628.mp4
Binary files differ
diff --git "a/public/images/map/\345\256\211\345\205\250\345\270\275-\347\272\242.png" "b/public/images/map/\345\256\211\345\205\250\345\270\275-\347\272\242.png"
index 356bd7e..1cf6ada 100644
--- "a/public/images/map/\345\256\211\345\205\250\345\270\275-\347\272\242.png"
+++ "b/public/images/map/\345\256\211\345\205\250\345\270\275-\347\272\242.png"
Binary files differ
diff --git "a/public/images/map/\345\256\211\345\205\250\345\270\275-\347\273\277.png" "b/public/images/map/\345\256\211\345\205\250\345\270\275-\347\273\277.png"
index e8c6fec..9cf22ac 100644
--- "a/public/images/map/\345\256\211\345\205\250\345\270\275-\347\273\277.png"
+++ "b/public/images/map/\345\256\211\345\205\250\345\270\275-\347\273\277.png"
Binary files differ
diff --git "a/public/images/map/\347\233\221\346\216\247.png" "b/public/images/map/\347\233\221\346\216\247.png"
new file mode 100644
index 0000000..a6a61ce
--- /dev/null
+++ "b/public/images/map/\347\233\221\346\216\247.png"
Binary files differ
diff --git a/src/api/helemt.ts b/src/api/helemt.ts
index cf1a5e6..34a4820 100644
--- a/src/api/helemt.ts
+++ b/src/api/helemt.ts
@@ -73,4 +73,12 @@
         method: "post",
         data
     })
+}
+
+export const delZones = (data) => {
+    return request({
+        url: `/iotdata/del-zone`,
+        method: "post",
+        data
+    })
 }
\ No newline at end of file
diff --git a/src/pages/index/App.vue b/src/pages/index/App.vue
index 2a3a431..21e780b 100644
--- a/src/pages/index/App.vue
+++ b/src/pages/index/App.vue
@@ -1,138 +1,94 @@
 <template>
-  <div class v-loading="vLoading" :style="`width: ${currentWidth}px;height:${currentHeight}px`">
-    <div class="web-site">
-      <a href="http://www.smartai.com" target="_blank">www.smartai.com</a>
-    </div>
+  <div class="init" v-if="!isWhite">
+    <div class="content">
+      <div class="title">娆㈣繋娉ㄥ唽Smart AI 浜哄伐鏅鸿兘鎿嶄綔绯荤粺</div>
+      <el-steps :active="active" finish-status="success" :align-center="true">
+        <el-step title="鍒涘缓璐﹀彿"></el-step>
+        <el-step title="閰嶇疆缃戠粶"></el-step>
+        <el-step title="娉ㄥ唽淇℃伅"></el-step>
+      </el-steps>
 
-    <!-- 鎺堟潈淇℃伅 -->
-    <lang-select class="lang-select"/>
-    <licence />
-    <div class="right-bg" style>
-      <particle-network />
-    </div>
-    <div class="left-bg">
-      <div class="login-logo">
-        <img src="/images/login-logo.png" alt width="105px" height="105px" />
+      <el-carousel
+        ref="carousel"
+        trigger="click"
+        height="480px"
+        :loop="false"
+        :autoplay="false"
+        :initial-index="active"
+      >
+        <el-carousel-item>
+          <formAccount ref="form0"></formAccount>
+        </el-carousel-item>
+        <el-carousel-item>
+          <formNet ref="form1"></formNet>
+        </el-carousel-item>
+        <el-carousel-item>
+          <formInfo ref="form2"></formInfo>
+        </el-carousel-item>
+      </el-carousel>
+
+      <div class="control">
+        <div class="pre" @click="preForm">涓婁竴姝�</div>
+        <div class="next" @click="nextForm" v-if="active == 0">涓嬩竴姝�</div>
+        <div class="next" @click="nextForm" v-if="active == 1">璺宠繃</div>
+        <div class="next" @click="nextForm" v-if="active == 2">瀹屾垚</div>
       </div>
-      <div class="login-com">
-        <span>{{ $t('login.company') }}</span>
-      </div>
-      <div class="login-form">
-        <el-form
-          :model="user"
-          status-icon
-          :rules="nullRule"
-          :validate-on-rule-change="false"
-          ref="ruleForm"
-          class="demo-ruleForm"
-        >
-          <el-form-item prop="loginName">
-            <el-input v-model="user.loginName" style="width:280px" :placeholder="$t('placeholder.enterUsername')">
-              <i slot="prefix" class="iconfont iconyonghu1"></i>
-            </el-input>
-          </el-form-item>
-          <el-form-item prop="password">
-            <el-input
-              show-password
-              @keyup.enter.native="systemLogin()"
-              v-model="user.password"
-              autocomplete="off"
-              style="width:280px"
-              :placeholder="$t('placeholder.enterPassword')"
-            >
-              <i slot="prefix" class="iconfont iconmima"></i>
-            </el-input>
-          </el-form-item>
-          <el-form-item>
-            <el-button ref="submit" type="warning" @click="systemLogin()" style="width:280px">{{ $t('button.login') }}</el-button>
-          </el-form-item>
-        </el-form>
-      </div>
-      <!-- <p class="gradient-text gradient-text-one">鈥斺�斺�� {{serverTitle || 'SmartAI 鈥� ReID'}} 鈥斺�斺��</p> -->
-      <p class="gradient-text gradient-text-one">
-        鈥斺��
-        <b>SmartAI</b> {{ $t('login.aios') }} 鈥斺��
-      </p>
-      <p
-        class="gradient-text gradient-text-one"
-        style="letter-spacing: 1.8px;font-size:15px;"
-      >V1.0.0</p>
     </div>
   </div>
+  <div class="white" v-else></div>
 </template>
 
 <script>
-import { tologin, getLoginUserData, getServerName } from './api.ts';
-import ParticleNetwork from './ParticleNetwork'
-import Licence from '@/components/licence'
-import LangSelect from '@/components/langSelect'
-import { getMenuListData } from "@/api/utils";
+import formAccount from "@/pages/index/components/formAccount";
+import formNet from "@/pages/index/components/formNet";
+import formInfo from "@/pages/index/components/formInfo";
+import {
+  getInitInfo,
+  savePassword,
+  initNetwork,
+  saveRegInfo,
+  getRegInfo,
+} from "./api";
 
 export default {
-  name: 'login-pgae',
-  metaInfo: {
-    title: '鐧诲綍椤�'
+  created() {
+    this.getInitInfo();
+  },
+  data() {
+    return {
+      active: 0,
+      formData: {},
+      isWhite: true,
+    };
   },
   components: {
-    ParticleNetwork,
-    Licence,
-    LangSelect
-  },
-  computed: {
-    rules() {
-      return {
-        loginName: [{ required: true, message: this.$t('placeholder.enterUsername'), trigger: 'change' } ],
-        password: [{ required: true, message: this.$t('placeholder.enterPassword'), trigger: 'change' }]
-        }
-    },
-  },
-  data: () => ({
-    serverTitle: "",
-    user: {
-      loginName: '',
-      password: '',
-      rememberMe: false
-    },
-    nullRule: {},
-
-    loading: '',
-    vLoading: false,
-    currentHeight: 1057,
-    currentWidth: 1920
-  }),
-  created() {
-    this.getServerName()
-    this.getScreenHeight()
-  },
-  mounted() {
-    // 鑷姩鐧诲綍鎺ュ彛
-    this.loginRobot();
-  },
-  watch: {},
-  beforeDestroy() {
-    window.onresize = null
+    formAccount,
+    formNet,
+    formInfo,
   },
   methods: {
-    loginRobot() {
-      // 瑙f瀽璺敱鍙傛暟锛屽苟缂撳瓨
-      let user = this.getQueryVariable("username");
-      let passwd = this.getQueryVariable("password");
-      if (user.length && passwd.length) {
-        sessionStorage.setItem("autoLogin", JSON.stringify({ username: user, passwd: passwd }));
-
-        this.user.loginName = user;
-        this.user.password = passwd;
-        this.systemLogin();
+    preForm() {
+      if (this.active == 0) {
+        return;
+      }
+      this.active--;
+      this.$refs["carousel"].prev();
+    },
+    async nextForm() {
+      if (this.active == 2) {
+        const data = this.$refs[`form${this.active}`].getFormData();
+        await saveRegInfo(data);
+        location.assign("/login");
         return;
       }
 
-      // 鐧婚檰瓒呮椂鍚庣殑閲嶆柊鐧婚檰
-      let sessionInfo = sessionStorage.getItem('autoLogin');
-      if (sessionInfo) {
-        let authority = JSON.parse(sessionInfo);
-        this.user.loginName = authority.username;
-        this.user.password = authority.passwd;
-        this.systemLogin();
+      if (this.active == 0) {
+        const data = this.$refs[`form${this.active}`].getFormData();
+        if (!data) {
+          return false;
+        }
+        const res1 = await savePassword(data);
+        console.log(data);
       }
     },
     systemLogin() {
@@ -189,136 +145,176 @@
       } else {
         this.$notify.error("鐧诲綍澶辫触锛�")
       }
-    },
 
-    getScreenHeight() {
-      this.currentHeight = document.documentElement.clientHeight
-      this.currentWidth = document.documentElement.clientWidth
-      window.onresize = () => {
-        this.currentHeight = document.documentElement.clientHeight
-        this.currentWidth = document.documentElement.clientWidth
-        this.$forceUpdate()
-      }
+      this.active++;
+      this.$refs["carousel"].next();
     },
-    async getServerName() {
-      let res = await getServerName()
-      if (res && res.success) {
-        this.serverTitle = res.data.serverName
-        window.document.title = res.data.serverName
-          ? res.data.serverName
-          : 'SmartAI'
-        sessionStorage.setItem('title', res.data.serverName)
+    async getInitInfo() {
+      const res = await getInitInfo();
+
+      if (res.data.initPwd && !res.data.initRegInfo) {
+        const res1 = await getRegInfo();
+        this.active = 1;
+        this.$refs["carousel"].setActiveItem(1);
       }
+
+      if (res.data.initPwd && res.data.initRegInfo) {
+        location.assign("/login");
+        return;
+      }
+
+      this.isWhite = false;
     },
-    async getMenuList() {
-      let results = await getMenuListData({});
-      if (results && results.success) {
-        /* 瀛樺偍鏉冮檺 */
-        let buttonAuthoritys = results.data;
-        if (results && results.length && this.$route.query.is_login) {
-          this.$router.replace(results[0].url);
-        }
-        sessionStorage.setItem("buttonAuthoritys", "," + buttonAuthoritys + ",");
-        sessionStorage.setItem("menuInfo", JSON.stringify(results));
-      } else {
-        this.$toast({
-          type: "error",
-          message: "鑿滃崟鑾峰彇澶辫触"
-        });
-      }
-    },
-    getQueryVariable(variable) {
-      var query = window.location.search.substring(1);
-      var vars = query.split("&");
-      for (var i = 0; i < vars.length; i++) {
-        var pair = vars[i].split("=");
-        if (pair[0] == variable) { return pair[1]; }
-      }
-      return (false);
-    }
   },
-}
+};
 </script>
-<style lang="scss">
-.right-bg {
-  position: fixed;
-  top: 0;
-  left: 0;
-  background-image: url("/images/login-net.png");
 
-  width: 100%;
+<style lang="scss" scoped>
+.init {
   height: 100%;
-  min-width: 1000px;
-  z-index: -10;
-  zoom: 1;
-  background-color: #fff;
-  background-repeat: no-repeat;
-  background-size: cover;
-  -webkit-background-size: cover;
-  -o-background-size: cover;
-  background-position: center 0;
-}
-.web-site {
-  position: absolute;
-  top: 55px;
-  left: 41px;
-  font-family: PingFangSC-Medium;
-  font-size: 20px;
-  color: #6170e1;
-  letter-spacing: 6.15px;
-}
-.lang-select {
-  float: right;
-  color: white !important;
-  font-size: 14px;
-  margin: 13px;
-  cursor: pointer;
-}
-.left-bg {
-  position: absolute;
-  top: 29%;
-  right: 18%;
-  width: 390px;
-  height: 426px;
-  background: rgba(146, 208, 255, 0.23);
-  border-radius: 4px;
-  text-align: center;
-  .login-logo {
-    margin-top: -53px;
-  }
+  background-image: url("/images/init/鑳屾櫙鍥�.png");
+  color: #fff;
+  user-select: none;
 
-  .login-com {
-    font-family: PingFangSC-Medium;
-    font-size: 22px;
-    color: #ffffff;
-    letter-spacing: 0.44px;
-    margin: 15px;
-  }
-  .login-form {
-    margin: 40px 10px;
-  }
-  .gradient-text {
-    line-height: 36px;
-    font-size: 17px;
-    font-family: -webkit-pictograph;
-    font-weight: bolder;
-    position: relative;
-    b {
-      font-size: 20px;
+  .content {
+    margin: 0 auto;
+    width: 1000px;
+    padding-top: 80px;
+
+    .title {
+      font-size: 28px;
+      font-weight: 700;
+      margin-bottom: 50px;
+      letter-spacing: 5px;
+    }
+
+    .el-steps ::v-deep {
+      margin-left: 22px;
+      text-align: left;
+
+      .el-step__icon {
+        width: 48px;
+        height: 48px;
+      }
+
+      .el-step__line {
+        left: 210px;
+        right: -110px;
+        border: 0.5px solid #fff;
+        border-bottom: none;
+        border-top: none;
+        opacity: 0.1;
+        top: 22px;
+      }
+
+      .is-success .el-step__icon {
+        background: none;
+        border: 2px solid rgba(255, 255, 255, 0.3);
+
+        .el-icon-check::before {
+          color: #fff;
+          font-size: 24px;
+          font-weight: 700;
+        }
+      }
+
+      .is-process .el-step__icon {
+        background-color: rgba(255, 255, 255, 0.3);
+        border: none;
+
+        .el-step__icon-inner {
+          color: #fff;
+          font-size: 24px;
+          font-weight: 700;
+        }
+      }
+
+      .is-wait .el-step__icon {
+        border: 2px solid rgba(255, 255, 255);
+        opacity: 0.5;
+        background: none;
+
+        .el-step__icon-inner {
+          color: #fff;
+          font-size: 24px;
+          font-weight: 700;
+        }
+      }
+
+      .el-step__main {
+        margin-top: 20px;
+        .is-success,
+        .is-process {
+          font-size: 16px;
+          color: #fff;
+          font-weight: normal;
+        }
+
+        .is-wait {
+          font-size: 16px;
+          color: #fff;
+          font-weight: normal;
+          opacity: 0.5;
+        }
+      }
+    }
+
+    .formAccount {
+      margin-top: 157px;
+      margin-left: 200px;
+      width: 550px;
+    }
+
+    .formNet,
+    .formInfo {
+      margin-top: 90px;
+      margin-left: 200px;
+      width: 550px;
+    }
+
+    .control {
+      position: fixed;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      bottom: 258px;
+      left: 0;
+      right: 0;
+      line-height: 40px;
+      .pre {
+        margin-right: 20px;
+        cursor: pointer;
+        width: 260px;
+        height: 40px;
+        border: 2px solid rgba(255, 255, 255, 0.3);
+        border-radius: 20px;
+        font-weight: bold;
+        color: #ffffff;
+      }
+
+      .next {
+        cursor: pointer;
+        width: 260px;
+        height: 40px;
+        background: rgba(255, 255, 255, 0.3);
+        border-radius: 20px;
+        font-weight: bold;
+        color: #ffffff;
+      }
     }
   }
-  .gradient-text-one {
-    background-image: linear-gradient(to right, #51feff 5%, #ff8725 100%);
-    -webkit-background-clip: text;
-    -webkit-text-fill-color: transparent;
+
+  ::v-deep .el-carousel__indicators {
+    display: none;
   }
 
-  .el-input__prefix {
-    left: 8px;
-  }
-
-  .el-form-item__error {
-    left: 54px;
+  ::v-deep .el-carousel__container button {
+    display: none;
   }
 }
-</style>
+
+.white {
+  height: 100%;
+  background-color: #fff;
+}
+</style>
\ No newline at end of file
diff --git a/src/pages/index/api.ts b/src/pages/index/api.ts
index 4d4c24f..26369c4 100644
--- a/src/pages/index/api.ts
+++ b/src/pages/index/api.ts
@@ -1,66 +1,67 @@
 import request from '@/scripts/httpRequest'
 import qs from 'qs'
 
-// 鐧诲綍
-export const tologin = (query: any) => {
-  // let query = 'username=' + user.loginName + '&password=' + user.password
+ //鑾峰彇鏄惁淇濆瓨杩囩敤鎴峰悕瀵嗙爜 浠ュ強鏄惁淇濆瓨杩囨敞鍐屼俊鎭�
+export const getInitInfo = (query: any) => {
   return request({
-    url: '/data/api-u/sys/login',
-    method: 'post',
-    data: qs.stringify(query)
-  })
-}
+    url: "/data/api-v/sysinit/getInitInfo",
+    method: "get",
+    params: query
+  });
+};
 
-// 閫�鍑�
-export const logout = () => {
+//鑾峰彇娉ㄥ唽淇℃伅
+export const getRegInfo = (query: any) => {
   return request({
-    url: '/data/api-u/sys/logout',
-    method: 'get'
-  })
-}
+    url: "/data/api-v/sysinit/getRegInfo" ,
+    method: "get",
+    params: query
+  });
+};
 
-// 鑾峰彇鐢ㄦ埛淇℃伅
-// export const getLoginUserData = () => {
-//   let token =
-//     sessionStorage.getItem('loginedInfo') &&
-//     JSON.parse(sessionStorage.getItem('loginedInfo')).access_token
-//   return request({
-//     url: '/data/api-u/users/current',
-//     method: 'get',
-//     headers: {
-//       'Content-Type': 'application/x-www-form-urlencoded',
-//       Authorization: token || ''
-//     }
-//   })
-// }
 
-export const getLoginUserData = () => {
-    let token =
-      sessionStorage.getItem('loginedInfo') &&
-      JSON.parse(sessionStorage.getItem('loginedInfo')).access_token
-    return request({
-      url: '/data/api-u/users/profile',
-      method: 'get',
-      headers: {
-        'Content-Type': 'application/x-www-form-urlencoded',
-        Authorization: token || ''
-      }
-    })
-  }
-
-//淇敼瀵嗙爜
-export const updatePwd = (query: any) => {
+//鑾峰彇缃戝崱鍒楄〃
+export const networkList = (query: any) => {
   return request({
-    url: '/data/api-u/users/updatePwd',
-    method: 'post',
-    data: qs.stringify(query)
-  })
-}
+    url: "/data/api-v/sysinit/networkList",
+    method: "get",
+    params: query
+  });
+};
 
-//鑾峰彇椤圭洰鍚嶇О
-export const getServerName = (query: any) => {
+
+//淇濆瓨鐢ㄦ埛鍚嶅瘑鐮�
+export const savePassword = (data: any) => {
   return request({
-    url: '/data/api-v/info/getServerName',
-    method: 'get'
-  })
-}
+    url: "/data/api-v/sysinit/savePassword",
+    method: "post",
+    data
+  });
+};
+
+
+//鍒濆鍖栫綉缁�
+export const initNetwork = (data: any) => {
+  return request({
+    url: "/data/api-v/sysinit/initNetwork",
+    method: "post",
+    data
+  });
+};
+
+//淇濆瓨娉ㄥ唽淇℃伅
+export const saveRegInfo = (data: any) => {
+  return request({
+    url:  "/data/api-v/sysinit/saveRegInfo" ,
+    method: "post",
+    data
+  });
+};
+
+export const getList = (query: any) => {
+  return request({
+    url: "/data/api-v/gb28181/findAreaByParentId",
+    method: "get",
+    params: query
+  });
+};
\ No newline at end of file
diff --git a/src/pages/index/components/IPInput.vue b/src/pages/index/components/IPInput.vue
new file mode 100644
index 0000000..4636588
--- /dev/null
+++ b/src/pages/index/components/IPInput.vue
@@ -0,0 +1,238 @@
+<template>
+  <div class="ip-input-container" ref="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"
+        @focus="showBorder"
+        @keydown="onInputKeydown($event, index)"
+        @input="onInput($event, index)"
+        @blur="onInputBlur"
+        @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: {
+    showBorder(){
+      this.$refs['ip-input-container'].style.border = '2px solid var(--colorCard)'
+    },
+    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() {
+      this.$refs['ip-input-container'].style.border = '2px solid transparent'
+      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 {
+  
+  width: 100%;
+  height: 32px;
+  line-height: normal;
+  border: 1px solid #dcdfe6;
+  box-sizing: border-box;
+  background-color: #fff;
+  text-align: left;
+  max-width: 360px;
+  display: flex;
+}
+.ip-segment {
+  display: inline-block;
+  width: 25%;
+    display: flex;
+    align-items: center;
+  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/pages/index/components/formAccount.vue b/src/pages/index/components/formAccount.vue
new file mode 100644
index 0000000..0362ab5
--- /dev/null
+++ b/src/pages/index/components/formAccount.vue
@@ -0,0 +1,134 @@
+<template>
+  <div class="formAccount">
+    <el-form ref="form" :model="form" label-width="90px" :rules="rules">
+      <el-form-item label="鐢ㄦ埛鍚�" prop="username">
+        <el-input
+          v-model="form.username"
+          placeholder="2-10浣嶅瓧绗︼紝涓嶈兘浠ユ暟瀛楀紑澶达紝涓嶅彲鍖呭惈姹夊瓧"
+        ></el-input>
+      </el-form-item>
+
+      <el-form-item label="瀵嗙爜" prop="password">
+        <el-input
+          v-model="form.password"
+          placeholder="鑷冲皯涓�6浣嶅瓧绗�"
+          type="password"
+        ></el-input>
+      </el-form-item>
+
+      <el-form-item label="纭瀵嗙爜" prop="repassword">
+        <el-input
+          v-model="form.repassword"
+          placeholder="璇风‘璁ゅ瘑鐮�"
+          type="password"
+        ></el-input>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import { getRegInfo } from "../api";
+
+export default {
+  data() {
+    const validateName = (rule, value, callback) => {
+      var reg = /^[A-Za-z][A-Za-z0-9]{0,}$/;
+      if (!reg.test(value)) {
+        return callback(new Error("涓嶈兘浠ユ暟瀛楀紑澶达紝涓嶅彲鍖呭惈姹夊瓧"));
+      } else callback();
+    };
+
+    const validateRePass = (rule, value, callback) => {
+      if (this.form.password != value) {
+        return callback(new Error("涓ゆ瀵嗙爜涓嶄竴鑷�"));
+      } else callback();
+    };
+
+    return {
+      form: {
+        username: "",
+        password: "",
+        repassword: "",
+      },
+      rules: {
+        name: [
+          { required: true, message: "璇疯緭鍏ョ敤鎴峰悕", trigger: "blur" },
+          {
+            min: 2,
+            max: 10,
+            message: "闀垮害鍦� 2 鍒� 10 涓瓧绗�",
+            trigger: "blur",
+          },
+          { validator: validateName, trigger: "blur" },
+        ],
+        password: [
+          { required: true, message: "璇疯緭鍏ュ瘑鐮�", trigger: "blur" },
+          {
+            min: 6,
+            max: 24,
+            message: "鑷冲皯涓�6浣嶅瓧绗�",
+            trigger: "blur",
+          },
+        ],
+        repassword: [
+          { required: true, message: "璇风‘璁ゅ瘑鐮�", trigger: "blur" },
+          { validator: validateRePass, trigger: "blur" },
+        ],
+      },
+    };
+  },
+  methods: {
+    getFormData() {
+      const _this = this;
+      let data = null;
+      this.$refs["form"].validate((valid) => {
+        if (valid) {
+          data = _this.form;
+        } else {
+          return false;
+        }
+      });
+      return data;
+    },
+
+    async getRegInfo() {
+      const res = await getRegInfo();
+      console.log(res);
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.formAccount {
+  .el-form-item ::v-deep {
+    label {
+      font-size: 14px;
+      color: #fff;
+      text-align: left;
+    }
+
+    .el-form-item__content {
+      margin-left: 110px !important;
+    }
+
+    input {
+      background-color: rgba(0, 0, 0, 0.1);
+      color: #fff;
+      border: none;
+      caret-color: #fff !important;
+    }
+
+    input:-webkit-autofill,
+    textarea:-webkit-autofill,
+    select:-webkit-autofill {
+      -webkit-text-fill-color: #fff !important;
+      -webkit-box-shadow: 0 0 0px 1000px transparent inset !important;
+      background-color: transparent;
+      background-image: none;
+      transition: background-color 50000s ease-in-out 0s; //鑳屾櫙鑹查�忔槑  鐢熸晥鏃堕暱  杩囨浮鏁堟灉  鍚敤鏃跺欢杩熺殑鏃堕棿
+    }
+  }
+}
+</style>
\ No newline at end of file
diff --git a/src/pages/index/components/formInfo.vue b/src/pages/index/components/formInfo.vue
new file mode 100644
index 0000000..4599768
--- /dev/null
+++ b/src/pages/index/components/formInfo.vue
@@ -0,0 +1,259 @@
+<template>
+  <div class="formInfo">
+    <el-form ref="form" :model="form" label-width="90px" :rules="rules">
+      <el-form-item label="绫诲瀷" prop="type">
+        <el-radio v-model="form.userType" label="personal">涓汉</el-radio>
+        <el-radio v-model="form.userType" label="company">鍏徃</el-radio>
+      </el-form-item>
+
+      <el-form-item
+        label="鍏徃鍚嶇О"
+        prop="name1"
+        v-if="form.userType == 'company'"
+      >
+        <el-input v-model="form.name1" placeholder="璇疯緭鍏ュ叕鍙稿悕绉�"></el-input>
+      </el-form-item>
+
+      <el-form-item
+        label="鑱旂郴浜哄鍚�"
+        prop="name2"
+        v-if="form.userType == 'company'"
+      >
+        <el-input
+          v-model="form.name2"
+          placeholder="璇疯緭鍏ヨ仈绯讳汉濮撳悕"
+        ></el-input>
+      </el-form-item>
+
+      <el-form-item label="濮撳悕" prop="name" v-else>
+        <el-input v-model="form.name" placeholder="璇疯緭鍏ュ鍚�"></el-input>
+      </el-form-item>
+
+      <el-form-item label="鎵�鍦ㄥ湴" prop="addr">
+        <el-cascader
+          :props="props"
+          popper-class="location"
+          separator=" "
+          @change="handleChange"
+          v-model="form.addr"
+        ></el-cascader>
+      </el-form-item>
+
+      <el-form-item label="閭" prop="email">
+        <el-input v-model="form.email" placeholder="璇疯緭鍏ラ偖绠�"></el-input>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import { getList } from "../api";
+export default {
+  created() {},
+  data() {
+    return {
+      form: {
+        userType: "personal",
+        name: "",
+        name1: "",
+        name2: "",
+        email: "",
+        addr: "",
+        provinceId: "",
+        cityId: "",
+        labelList: "",
+      },
+      rules: {
+        name1: [{ required: true, message: "璇疯緭鍏ュ叕鍙稿悕绉�", trigger: "blur" }],
+        name2: [
+          { required: true, message: "璇疯緭鍏ヨ仈绯讳汉濮撳悕", trigger: "blur" },
+        ],
+        name: [{ required: true, message: "璇疯緭鍏ュ鍚�", trigger: "blur" }],
+        addr: [{ required: true, message: "璇烽�夋嫨鎵�鍦ㄥ湴", trigger: "blur" }],
+        email: [{ required: true, message: "璇疯緭鍏ラ偖绠�", trigger: "blur" }],
+      },
+      provinceOptions: [],
+      props: {
+        lazy: true, // 寮�鍚姩鎬佸姞杞�
+        lazyLoad: async (node, resolve) => {
+          // 璁剧疆鍔犺浇鏁版嵁婧愭柟娉� 榛樿鎵ц涓�娆�
+          // node 涓哄綋鍓嶇偣鍑荤殑鑺傜偣
+          // resolve 涓烘暟鎹姞杞藉畬鎴愮殑鍥炶皟(蹇呴』璋冪敤)
+          /* node姝ゆ椂灞炴�т负:
+          		褰撳墠鍙跺瓙  level锛�0
+          		loaded锛歵rue
+          		loading锛歠alse
+          		鏄惁鏄牴  root锛歵ure
+          	*/
+          console.log(node);
+
+          if (node.level == 0) {
+            const res = await getList();
+            this.provinceOptions = res.data.map((item) => {
+              return {
+                value: item.id,
+                label: item.name, // 閫夐」鍚�
+                leaf: false, // 鏄惁涓烘湯灏�
+              };
+            });
+            resolve(this.provinceOptions);
+            console.log(node.level);
+          }
+
+          if (node.level == 1) {
+            console.log("-------------");
+            this.provinceId = node.value;
+            const res2 = await getList({
+              parentId: node.value,
+            });
+
+            const arr = res2.data.map((item) => {
+              return {
+                value: item.id,
+                label: item.name, // 閫夐」鍚�
+                leaf: true, // 鏄惁涓烘湯灏�
+              };
+            });
+            resolve(arr);
+          } else {
+            console.log(node);
+          }
+        },
+      },
+      value: [],
+    };
+  },
+
+  methods: {
+    getFormData() {
+      const _this = this;
+      let data = null;
+      this.$refs["form"].validate((valid) => {
+        if (valid) {
+          console.log(_this.form.userType);
+          if (_this.form.userType == "personal") {
+            data = {
+              userType: _this.form.userType,
+              name: _this.form.name,
+              email: _this.form.email,
+              addr: _this.form.labelList,
+              provinceId: _this.form.provinceId,
+              cityId: _this.form.cityId,
+            };
+          } else {
+            data = {
+              userType: _this.form.userType,
+              name: _this.form.name1 + " " + _this.form.name2,
+              email: _this.form.email,
+              addr: _this.form.labelList,
+              provinceId: _this.form.provinceId,
+              cityId: _this.form.cityId,
+            };
+          }
+        } else {
+          return false;
+        }
+      });
+
+      return data;
+    },
+    handleChange(val) {
+      this.form.provinceId = val[0] + "";
+      this.form.cityId = val[1] + "";
+
+      setTimeout(() => {
+        this.form.labelList =
+          document.querySelectorAll(".el-cascader input")[0].value;
+      }, 200);
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.formInfo {
+  .el-form-item ::v-deep {
+    label {
+      font-size: 14px;
+      color: #fff;
+      text-align: left;
+    }
+
+    .el-radio {
+      .el-radio__inner {
+        background: none;
+        border-color: rgba(255, 255, 255, 0.3) !important;
+
+        &::after {
+          width: 6px;
+          height: 6px;
+        }
+      }
+
+      .el-radio__label {
+        color: #fff !important;
+      }
+    }
+
+    .el-form-item__content {
+      margin-left: 110px !important;
+      text-align: left;
+    }
+
+    input {
+      background-color: rgba(0, 0, 0, 0.1);
+      color: #fff;
+      border: none;
+      caret-color: #fff !important;
+    }
+
+    input:-webkit-autofill,
+    textarea:-webkit-autofill,
+    select:-webkit-autofill {
+      -webkit-text-fill-color: #fff !important;
+      -webkit-box-shadow: 0 0 0px 1000px transparent inset !important;
+      background-color: transparent;
+      background-image: none;
+      transition: background-color 50000s ease-in-out 0s; //鑳屾櫙鑹查�忔槑  鐢熸晥鏃堕暱  杩囨浮鏁堟灉  鍚敤鏃跺欢杩熺殑鏃堕棿
+    }
+
+    .el-cascader {
+      width: 100%;
+    }
+  }
+}
+</style>
+
+<style lang="scss">
+.el-popper.el-cascader__dropdown.location {
+  background-color: rgb(77, 72, 111);
+  border: none;
+  margin: 0 0;
+
+  * {
+    color: #fff;
+    border-color: rgba(255, 255, 2555, 0.1);
+  }
+
+  .el-cascader-node:hover,
+  .in-active-path,
+  .is-active,
+  .el-cascader-node {
+    background-color: rgb(101, 93, 126) !important;
+  }
+
+  .popper__arrow::after,
+  .popper__arrow {
+    display: none;
+  }
+
+  .el-cascader-node__label {
+    text-align: left;
+  }
+
+  .el-cascader-menu__wrap {
+    width: 226px;
+    height: 175px;
+  }
+}
+</style>
\ No newline at end of file
diff --git a/src/pages/index/components/formNet.vue b/src/pages/index/components/formNet.vue
new file mode 100644
index 0000000..a151478
--- /dev/null
+++ b/src/pages/index/components/formNet.vue
@@ -0,0 +1,141 @@
+<template>
+  <div class="formNet">
+    <el-form ref="form" :model="form" label-width="80px">
+      <el-form-item label="缃戝崱">
+        <el-select
+          v-model="form.netName"
+          placeholder="璇烽�夋嫨缃戝崱"
+          popper-class="formNet_select"
+        >
+          <el-option
+            v-for="(item, index) in options"
+            :key="index"
+            :label="item.label"
+            :value="item.value"
+          >
+          </el-option>
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="IP">
+        <ipInput :ip="form.ip" @on-blur="form.ip = arguments[0]"></ipInput>
+      </el-form-item>
+
+      <el-form-item label="瀛愮綉鎺╃爜">
+        <ipInput
+          :ip="form.subMask"
+          @on-blur="form.subMask = arguments[0]"
+        ></ipInput>
+      </el-form-item>
+
+      <el-form-item label="缃戝叧">
+        <ipInput
+          :ip="form.gateway"
+          @on-blur="form.gateway = arguments[0]"
+        ></ipInput>
+      </el-form-item>
+
+      <el-form-item label="DNS">
+        <ipInput :ip="form.dns" @on-blur="form.dns = arguments[0]"></ipInput>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import ipInput from "../components/IPInput";
+import { networkList } from "../api";
+
+export default {
+  created() {
+    this.networkList();
+  },
+  data() {
+    return {
+      form: { netName: "", ip: "", subMask: "", gateway: "", dns: "" },
+
+      options: [],
+    };
+  },
+  components: {
+    ipInput,
+  },
+  methods: {
+    getFormData() {
+      return this.form;
+    },
+    async networkList() {
+      const res = await networkList();
+      res.data.forEach((item) => {
+        this.options.push({
+          value: item.name,
+          label: item.name,
+        });
+      });
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.formNet {
+  .el-form-item ::v-deep {
+    label {
+      font-size: 14px;
+      color: #fff;
+      text-align-last: left;
+    }
+
+    .el-form-item__content {
+      margin-left: 110px !important;
+    }
+  }
+
+  .ip-input-container ::v-deep {
+    background-color: rgba(0, 0, 0, 0.1);
+    border: none !important;
+    height: 40px;
+    max-width: none;
+
+    .ip-segment-input {
+      color: #fff;
+    }
+  }
+
+  .el-select ::v-deep {
+    width: 100%;
+
+    input {
+      background-color: rgba(0, 0, 0, 0.1);
+      border: none !important;
+      color: #fff;
+    }
+  }
+}
+</style>
+
+<style lang="scss">
+.el-select-dropdown.el-popper.formNet_select {
+  background-color: rgb(60, 62, 99);
+
+  border: none;
+  margin: 0 0;
+  z-index: 5;
+
+  * {
+    color: #fff;
+  }
+
+  li {
+    z-index: 4;
+  }
+  .el-select-dropdown__item.hover {
+    background-color: rgba(85, 82, 117) !important;
+  }
+
+  .popper__arrow::after,
+  .popper__arrow {
+    display: none;
+  }
+}
+</style>
\ No newline at end of file
diff --git a/src/pages/internetData/views/helemtTable.vue b/src/pages/internetData/views/helemtTable.vue
index ee8972e..f12a8ff 100644
--- a/src/pages/internetData/views/helemtTable.vue
+++ b/src/pages/internetData/views/helemtTable.vue
@@ -110,25 +110,25 @@
               src="/images/InternetData/瑙嗛.png"
               alt=""
               v-if="!scope.row.isSend"
-              @click="sendVoice(scope.row)"
+              @click="sendVoice(scope.row, scope.$index)"
             />
             <img
               src="/images/InternetData/瑙嗛_鐐瑰嚮.png"
               alt=""
               v-else
-              @click="sendVoice(scope.row)"
+              @click="sendVoice(scope.row, scope.$index)"
             />
             <img
               src="/images/InternetData/璇煶.png"
               alt=""
               v-if="!scope.row.istele"
-              @click="telephone(scope.row)"
+              @click="telephone(scope.row, scope.$index)"
             />
             <img
               src="/images/InternetData/璇煶_鐐瑰嚮.png"
               alt=""
               v-else
-              @click="telephone(scope.row)"
+              @click="telephone(scope.row, scope.$index)"
             />
           </div>
         </template>
@@ -166,141 +166,10 @@
       currentPage: 1,
       page_size: 10,
       total: 10,
-      tableData: [
-        {
-          code: "A123123123123",
-          elec: 79.1,
-          ip: "192.168.1.2",
-          mac: "ec:da:da:da:ed:98",
-          longitude: 120.123123,
-          latitude: 120.123123,
-          height: "11.21",
-          time: "0.23.45",
-          positon: "鍗曞悜瀹氫綅",
-          isSend: false,
-          istele: false,
-        },
-        {
-          code: "A123123123123",
-          elec: 29.1,
-          ip: "192.168.1.2",
-          mac: "ec:da:da:da:ed:98",
-          longitude: 120.123123,
-          latitude: 120.123123,
-          height: "11.21",
-          time: "0.23.45",
-          positon: "鍗曞悜瀹氫綅",
-          isSend: false,
-          istele: false,
-        },
-        {
-          code: "A123123123123",
-          elec: 0,
-          ip: "192.168.1.2",
-          mac: "ec:da:da:da:ed:98",
-          longitude: 120.123123,
-          latitude: 120.123123,
-          height: "11.21",
-          time: "0.23.45",
-          positon: "鍗曞悜瀹氫綅",
-          isSend: false,
-          istele: false,
-        },
-        {
-          code: "A123123123123",
-          elec: 79.1,
-          ip: "192.168.1.2",
-          mac: "ec:da:da:da:ed:98",
-          longitude: 120.123123,
-          latitude: 120.123123,
-          height: "11.21",
-          time: "0.23.45",
-          positon: "鍗曞悜瀹氫綅",
-          isSend: false,
-          istele: false,
-        },
-        {
-          code: "A123123123123",
-          elec: 79.1,
-          ip: "192.168.1.2",
-          mac: "ec:da:da:da:ed:98",
-          longitude: 120.123123,
-          latitude: 120.123123,
-          height: "11.21",
-          time: "0.23.45",
-          positon: "鍗曞悜瀹氫綅",
-          isSend: false,
-          istele: false,
-        },
-        {
-          code: "A123123123123",
-          elec: 79.1,
-          ip: "192.168.1.2",
-          mac: "ec:da:da:da:ed:98",
-          longitude: 120.123123,
-          latitude: 120.123123,
-          height: "11.21",
-          time: "0.23.45",
-          positon: "鍗曞悜瀹氫綅",
-          isSend: false,
-          istele: false,
-        },
-        {
-          code: "A123123123123",
-          elec: 79.1,
-          ip: "192.168.1.2",
-          mac: "ec:da:da:da:ed:98",
-          longitude: 120.123123,
-          latitude: 120.123123,
-          height: "11.21",
-          time: "0.23.45",
-          positon: "鍗曞悜瀹氫綅",
-          isSend: false,
-          istele: false,
-        },
-        {
-          code: "A123123123123",
-          elec: 79.1,
-          ip: "192.168.1.2",
-          mac: "ec:da:da:da:ed:98",
-          longitude: 120.123123,
-          latitude: 120.123123,
-          height: "11.21",
-          time: "0.23.45",
-          positon: "鍗曞悜瀹氫綅",
-          isSend: false,
-          istele: false,
-        },
-        {
-          code: "A123123123123",
-          elec: 79.1,
-          ip: "192.168.1.2",
-          mac: "ec:da:da:da:ed:98",
-          longitude: 120.123123,
-          latitude: 120.123123,
-          height: "11.21",
-          time: "0.23.45",
-          positon: "鍗曞悜瀹氫綅",
-          isSend: false,
-          istele: false,
-        },
-        {
-          code: "A123123123123",
-          elec: 79.1,
-          ip: "192.168.1.2",
-          mac: "ec:da:da:da:ed:98",
-          longitude: 120.123123,
-          latitude: 120.123123,
-          height: "11.21",
-          time: "0.23.45",
-          positon: "鍗曞悜瀹氫綅",
-          isSend: false,
-          istele: false,
-        },
-      ],
       helemtArr: [],
       commentContent: "",
       telephoneObj: null,
+      targetIndex: null,
     };
   },
   created() {
@@ -312,11 +181,11 @@
   methods: {
     async getHelemtArr(data) {
       const res = await getHelemtData(data);
-      console.log(res);
       this.helemtArr = res.data.items;
       this.total = res.data.total;
     },
-    sendVoice(target) {
+    sendVoice(target, index) {
+      const _this = this;
       target.isSend = true;
 
       const h = this.$createElement;
@@ -381,29 +250,41 @@
           target.isSend = false;
           done();
         },
-      }).then((action) => {
-        if (action == "confirm") {
-          if (!voiceText) {
-            this.$message({
-              message: "鎸囦护涓嶈兘涓虹┖",
-              type: "warning",
+      })
+        .then((action) => {
+          if (action == "confirm") {
+            if (!voiceText) {
+              this.$message({
+                message: "鎸囦护涓嶈兘涓虹┖",
+                type: "warning",
+              });
+              target.isSend = false;
+              _this.$set(_this.helemtArr, index, target);
+              return;
+            }
+            console.log(voiceText);
+            sendAudio(target.device_sn, voiceText).then((res) => {
+              this.$message({
+                message: "鎸囦护鍙戦�佹垚鍔�",
+                type: "success",
+              });
+              target.isSend = false;
+              _this.$set(_this.helemtArr, index, target);
             });
-            return;
+            target.isSend = false;
+            _this.$set(_this.helemtArr, index, target);
+          } else {
+            target.isSend = false;
+            _this.$set(_this.helemtArr, index, target);
           }
-          console.log(voiceText);
-          sendAudio(target.device_sn, voiceText).then((res) => {
-            this.$message({
-              message: "鎸囦护鍙戦�佹垚鍔�",
-              type: "success",
-            });
-          });
+        })
+        .catch(() => {
           target.isSend = false;
-        } else {
-          target.isSend = false;
-        }
-      });
+          _this.$set(_this.helemtArr, index, target);
+        });
     },
-    telephone(target) {
+    telephone(target, index) {
+      this.targetIndex = index;
       target.istele = true;
       this.telephoneObj = target;
     },
@@ -431,7 +312,9 @@
     },
     closeTele(e) {
       e.istele = false;
+      this.$set(this.helemtArr, this.targetIndex, e);
       this.telephoneObj = null;
+      this.targetIndex = null;
     },
   },
   components: {
diff --git a/src/pages/internetEquipment/components/headCard.vue b/src/pages/internetEquipment/components/headCard.vue
index 4291714..4738c7a 100644
--- a/src/pages/internetEquipment/components/headCard.vue
+++ b/src/pages/internetEquipment/components/headCard.vue
@@ -1,77 +1,73 @@
 <template>
   <div class="head-card">
-      <div class="card-left">
-          <div class="number" :style="colorStyle">{{number}}</div>
-          <div class="info">{{info}}</div>
-      </div>
-      <img class="card-right" :src="src" alt="">
+    <div class="card-left">
+      <div class="number" :style="colorStyle">{{ number }}</div>
+      <div class="info">{{ info }}</div>
+    </div>
+    <img class="card-right" :src="src" alt="" />
   </div>
 </template>
 
 <script>
 export default {
-    props: {
-        number: {
-            require: true
-        },
-        info: {
-            require: true
-        },
-        icon: {
-            require: true
-        },
-        color: {
-            require: true
-        },
-        src: {
-            require: true
-        }
+  props: {
+    number: {
+      require: true,
     },
-    data (){
-        return {
-            
-        }
+    info: {
+      require: true,
     },
-    computed: {
-        colorStyle (){
-            return {
-                "--color":this.color
-            }
-        }
-    }
-}
+    icon: {
+      require: true,
+    },
+    color: {
+      require: true,
+    },
+    src: {
+      require: true,
+    },
+  },
+  data() {
+    return {};
+  },
+  computed: {
+    colorStyle() {
+      return {
+        "--color": this.color,
+      };
+    },
+  },
+};
 </script>
 
 <style scoped lang="scss">
 .head-card {
-    box-sizing: border-box;
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-    padding: 20px;
-    width: 187px;
-    height: 90px;
-    background: #FFFFFF;
-    box-shadow: 0px 2px 10px rgba(141, 164, 187, 0.25);
-    border-radius: 15px;
+  box-sizing: border-box;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 20px 2%;
+  width: 187px;
+  height: 90px;
+  background: #ffffff;
+  box-shadow: 0px 2px 10px rgba(141, 164, 187, 0.25);
+  border-radius: 15px;
 
-    .card-left {
-        .number {
-            font-size: 24px;
-            font-weight: 700;
-            color: var(--color);
-        }
-        .info {
-            font-size: 12px;
-            color: #4F4F4F;
-;
-        }
+  .card-left {
+    .number {
+      font-size: 24px;
+      font-weight: 700;
+      color: var(--color);
     }
-
-    .card-right {
-        width: 58px;
-        height: 58px;
-
+    .info {
+      font-size: 12px;
+      color: #4f4f4f;
     }
+  }
+
+  .card-right {
+    width: 58px;
+    height: 58px;
+  }
 }
 </style>
\ No newline at end of file
diff --git a/src/pages/internetEquipment/components/helemetEchart.vue b/src/pages/internetEquipment/components/helemetEchart.vue
index 4af998f..fab8843 100644
--- a/src/pages/internetEquipment/components/helemetEchart.vue
+++ b/src/pages/internetEquipment/components/helemetEchart.vue
@@ -21,6 +21,9 @@
     });
     let myChart = echarts.init(document.getElementById("echart-cotainer"));
     myChart.setOption(this.option);
+    window.addEventListener("resize", function () {
+      myChart.resize();
+    });
   },
   data() {
     return {
diff --git a/src/pages/internetEquipment/components/helemetHead.vue b/src/pages/internetEquipment/components/helemetHead.vue
index 6f6600c..b81f365 100644
--- a/src/pages/internetEquipment/components/helemetHead.vue
+++ b/src/pages/internetEquipment/components/helemetHead.vue
@@ -51,10 +51,12 @@
   display: flex;
 
   .head-card {
+    flex: 1;
     margin-right: 10px;
   }
 
   .helemet-echart {
+    flex: 4;
     margin-left: 10px;
     width: 570px;
     height: 90px;
diff --git a/src/pages/internetEquipment/components/telephoneBox.vue b/src/pages/internetEquipment/components/telephoneBox.vue
new file mode 100644
index 0000000..6c9215b
--- /dev/null
+++ b/src/pages/internetEquipment/components/telephoneBox.vue
@@ -0,0 +1,122 @@
+<template>
+  <div class="telephone-box">
+    <div class="title">
+      <span class="icon iconfont">&#xe7cc;</span>
+      <span>鍘荤數</span>
+    </div>
+    <div class="info">
+      <div class="id">1139</div>
+      <div class="sip">sip:1139@47.112.193.0</div>
+    </div>
+
+    <div class="video">1</div>
+
+    <div class="control">
+      <img src="/images/InternetData/鎸傛柇.png" />
+      <img src="/images/InternetData/澹伴煶.png" class="mid" />
+      <img src="/images/InternetData/璇濈瓛.png" />
+    </div>
+
+    <div class="close el-icon-close" @click="close"></div>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    tele: {
+      type: Object,
+    },
+  },
+  data() {
+    return {};
+  },
+
+  methods: {
+    close() {
+      this.$emit("close");
+    },
+  },
+};
+</script>
+
+<style scoped lang="scss">
+.telephone-box {
+  box-sizing: border-box;
+  position: fixed;
+  z-index: 5;
+  padding: 32px 28px 28px 55px;
+
+  width: 420px;
+  height: 382px;
+  left: 50%;
+  top: 50%;
+  margin-top: -15%;
+  margin-left: -15%;
+
+  background: #ffffff;
+  border-radius: 8px;
+  color: #4f4f4f;
+
+  .title {
+    text-align: left;
+    font-size: 16px;
+    font-weight: 700;
+
+    .icon {
+      margin-right: 2px;
+      font-size: 18px;
+      font-weight: normal;
+    }
+  }
+
+  .info {
+    margin-top: 18px;
+    font-weight: bold;
+    font-size: 16px;
+
+    .sip {
+      margin-top: 2px;
+      font-size: 12px;
+      font-weight: normal;
+    }
+  }
+
+  .video {
+    margin: 0 auto;
+    margin-top: 20px;
+    box-sizing: border-box;
+    width: 104px;
+    height: 104px;
+    background: #454141;
+    border: 5px solid #ffaa44;
+    border-radius: 50%;
+
+    font-size: 36px;
+    color: #fff;
+    line-height: 94px;
+  }
+
+  .control {
+    margin-top: 50px;
+
+    img {
+      width: 37px;
+      height: 37px;
+    }
+
+    .mid {
+      margin: 0 37px;
+    }
+  }
+
+  .close {
+    cursor: pointer;
+    position: absolute;
+    top: 12px;
+    right: 12px;
+    font-size: 12px;
+    font-weight: 700;
+  }
+}
+</style>
\ No newline at end of file
diff --git a/src/pages/internetEquipment/module/elecModule.vue b/src/pages/internetEquipment/module/elecModule.vue
index 7e2ec79..0f726fc 100644
--- a/src/pages/internetEquipment/module/elecModule.vue
+++ b/src/pages/internetEquipment/module/elecModule.vue
@@ -62,10 +62,10 @@
   .elec-item {
     display: flex;
     align-items: center;
-    justify-content: space-between;
+    justify-content: space-around;
     margin-bottom: 4px;
-    padding: 20px 5px 20px 5px;
-    width: 240px;
+    padding: 20px 0;
+    width: 100%;
     height: 78px;
     background: #f9fafc;
     border-radius: 10px;
diff --git a/src/pages/internetEquipment/module/historyModule.vue b/src/pages/internetEquipment/module/historyModule.vue
index ce928fe..523943d 100644
--- a/src/pages/internetEquipment/module/historyModule.vue
+++ b/src/pages/internetEquipment/module/historyModule.vue
@@ -87,11 +87,11 @@
 
   .history-item {
     display: flex;
-    width: 240px;
+    width: 100%;
     height: 74px;
     margin-bottom: 4px;
     align-items: center;
-    justify-content: space-between;
+    justify-content: space-around;
     background: #f9fafc;
     border-radius: 10px;
     padding: 0 10px;
diff --git a/src/pages/internetEquipment/module/mapIndex.vue b/src/pages/internetEquipment/module/mapIndex.vue
index e295056..18305c4 100644
--- a/src/pages/internetEquipment/module/mapIndex.vue
+++ b/src/pages/internetEquipment/module/mapIndex.vue
@@ -1,19 +1,110 @@
 <template>
   <div id="map-index">
     <div class="control">
-      <div class="location icon iconfont" @click="location">&#xe74e;</div>
-      <div class="zoom-in icon iconfont" @click="zoomIn">&#xeb89;</div>
-      <div class="zoom-out icon iconfont" @click="zoomOut">&#xe758;</div>
+      <a href="#" title="瀹氫綅" @click="aClick()">
+        <div class="location icon iconfont" @click="location">&#xe74e;</div>
+      </a>
+      <a href="#" title="鏀惧ぇ" @click="aClick()">
+        <div class="zoom-in icon iconfont" @click="zoomIn">&#xeb89;</div>
+      </a>
+
+      <a href="#" title="缂╁皬" @click="aClick()">
+        <div class="zoom-out icon iconfont" @click="zoomOut">&#xe758;</div>
+      </a>
     </div>
-    <div class="range icon iconfont" @click="drawPolygon">&#xe773;</div>
+    <a href="#" title="鏂板/缂栬緫" @click="aClick()">
+      <div class="range icon iconfont" @click="drawPolygon">&#xe773;</div>
+    </a>
     <el-input v-model="nodeId" placeholder="璇疯緭鍏ュ唴瀹�"></el-input>
     <div class="save" v-if="showBtn" @click="savePoly">淇濆瓨</div>
+    <div class="del" v-if="polygonInfo" @click="delPoly">鍒犻櫎</div>
     <div class="cancel" v-if="showBtn" @click="resetMap">鍙栨秷</div>
+
+    <span id="polygonInfo" v-show="polygonInfo">{{ polygonInfo }}</span>
+
+    <img
+      v-if="myNode && !isHidden"
+      src="/images/map/Group 594.png"
+      alt=""
+      class="video_icon"
+      @click="hiddenVideo()"
+    />
+    <a v-if="myNode && isHidden" href="#" title="瀹炴椂鐩戞帶" @click="aClick()">
+      <img
+        src="/images/map/鐩戞帶.png"
+        alt=""
+        class="video_icon"
+        @click="showVideo()"
+      />
+    </a>
+
+    <div class="video_box" v-show="myNode" :class="{ hidden: isHidden }">
+      <div class="title">
+        <div class="left">
+          <span class="ball"></span>
+          <span class="left_info">瀹炴椂鐩戞帶</span>
+        </div>
+
+        <div class="right">
+          璁惧缂栫爜: {{ myNode && myNode.values && myNode.values_.id }}
+        </div>
+      </div>
+
+      <video controls="controls" loop="loop">
+        <source src="/images/map/video_20210924_101628.mp4" type="video/mp4" />
+      </video>
+    </div>
+
+    <div class="helmet_box" v-show="myNodeHover">
+      <div class="icon_close iconfont" @click="close">&#xe729;</div>
+      <div class="sn" v-if="myNodeHover">{{ myNodeHover.values_.lat.id }}</div>
+      <div class="location" v-if="myNodeHover">
+        缁忓害: {{ myNodeHover.values_.lat }}
+      </div>
+      <div class="location" v-if="myNodeHover">
+        绾害: {{ myNodeHover.values_.lng }}
+      </div>
+      <div class="info" v-if="myNodeHover">
+        鐢甸噺: {{ myNodeHover.values_.battery }}
+      </div>
+      <div class="button">
+        <img
+          src="/images/InternetData/瑙嗛.png"
+          alt=""
+          v-if="!isSending"
+          @click="sendVoice()"
+        />
+        <img src="/images/InternetData/瑙嗛_鐐瑰嚮.png" alt="" v-if="isSending" />
+        <img
+          src="/images/InternetData/璇煶.png"
+          alt=""
+          v-if="isTele == false"
+          @click="isTele = true"
+        />
+        <img
+          src="/images/InternetData/璇煶_鐐瑰嚮.png"
+          alt=""
+          v-if="isTele == true"
+          @click="isTele = false"
+        />
+      </div>
+    </div>
+
+    <telephoneBox :tele="myNode" v-if="isTele" @close="isTele = false" />
+
+    <div class="mask" v-if="isTele"></div>
   </div>
 </template>
 
 <script>
-import { getHelemtData, getZones, createZones } from "@/api/helemt";
+import {
+  getHelemtData,
+  getZones,
+  createZones,
+  delZones,
+  sendAudio,
+} from "@/api/helemt";
+import telephoneBox from "../components/telephoneBox.vue";
 
 import "ol/ol.css";
 import Feature from "ol/Feature";
@@ -28,6 +119,9 @@
 import Draw from "ol/interaction/Draw";
 import { Modify, Snap } from "ol/interaction";
 import Polygon from "ol/geom/Polygon";
+import Select from "ol/interaction/Select";
+import Overlay from "ol/Overlay";
+import { pointerMove } from "ol/events/condition";
 
 let myMap = {};
 let myVectorSource = {};
@@ -41,24 +135,21 @@
 });
 let myDraw = {};
 let myModify = {};
-
+let myPolygon = {};
+let mySelect = {};
+let mySelect2 = {};
+let overlay = {};
+let overlay2 = {};
+let voiceText = "";
+let drawFeature = [];
 export default {
-  created() {
-    this.getNodeData();
-  },
   data() {
     return {
+      isSending: false,
+      isTele: false,
+      isHidden: false,
       showBtn: false,
-      nodeArr: [
-        { data: [116.06157, 39.66157], id: 1, color: "缁�" },
-        { data: [116.06247, 39.66247], id: 2, color: "缁�" },
-        { data: [116.06337, 39.66337], id: 3, color: "缁�" },
-        { data: [116.06467, 39.66437], id: 4, color: "缁�" },
-        { data: [116.06517, 39.66517], id: 5, color: "绾�" },
-        { data: [116.06627, 39.66627], id: 6, color: "绾�" },
-        { data: [116.06787, 39.66787], id: 7, color: "绾�" },
-        { data: [116.06897, 39.66897], id: 8, color: "绾�" },
-      ],
+      nodeArr: [],
       nodeId: "",
       iconArr: [],
       rangeArr: [],
@@ -68,14 +159,22 @@
       polyFeature: [],
       drawStore: [],
       modifyStore: [],
+      polygonInfo: "",
+      nodeFeature: [],
+      myNode: null,
+      myNodeHover: null,
+      commentContent: "",
     };
   },
   mounted() {
     this.initMap();
   },
+  components: {
+    telephoneBox,
+  },
   methods: {
-    async getNodeData() {},
     async initMap() {
+      const that = this;
       // 鑾峰彇鑺傜偣
       const res = await getHelemtData();
       this.nodeArr = [];
@@ -84,6 +183,7 @@
           data: [item.lng, item.lat],
           id: item.device_sn,
           color: item.is_out_bound == 0 ? "缁�" : "绾�",
+          battery: item.battery,
         });
       });
 
@@ -97,7 +197,6 @@
           return obj;
         });
       }
-      console.log(this.polygonArr);
 
       // 璁剧疆鍦板浘涓績
       this.center = this.nodeArr[0].data;
@@ -131,6 +230,120 @@
         console.log(item);
       })
     }) */
+
+      window.addEventListener("resize", function () {
+        map.updateSize();
+      });
+
+      const select = new Select({
+        filter: (feature, layer) => {
+          if (feature.values_ && feature.values_.type == "node") {
+            this.myNode = feature;
+            return true;
+          } else if (feature.type && feature.type == "polygon") {
+            myPolygon = feature;
+            this.myNode = null;
+            this.nodeId = "";
+            return true;
+          }
+        },
+        style: (feature) => {
+          if (feature.values_ && feature.values_.type == "node") {
+            return new Style({
+              image: new Icon({
+                size: [32, 32],
+                src: `/images/map/瀹夊叏甯�-${feature.values_.color}.png`,
+              }),
+              zIndex: 1,
+            });
+          } else if (feature.type && feature.type == "polygon") {
+            return new Style({
+              fill: new Fill({
+                color: "rgba(0, 0, 255, 0.1)",
+              }),
+              stroke: new Stroke({
+                color: "skyblue",
+                width: 3,
+              }),
+            });
+          }
+        },
+      });
+
+      const select2 = new Select({
+        condition: pointerMove,
+        filter: (feature, layer) => {
+          if (feature.values_ && feature.values_.type == "node") {
+            this.myNodeHover = feature;
+            return true;
+          } else {
+            return false;
+          }
+        },
+        style: (feature) => {
+          if (feature.values_ && feature.values_.type == "node") {
+            return new Style({
+              image: new Icon({
+                size: [32, 32],
+                src: `/images/map/瀹夊叏甯�-${feature.values_.color}.png`,
+              }),
+              zIndex: 1,
+            });
+          }
+        },
+      });
+
+      const info = document.querySelector("#polygonInfo");
+
+      map.addInteraction(select);
+      map.addInteraction(select2);
+      mySelect = select;
+      mySelect2 = select2;
+
+      select.on("select", function (e) {
+        //   e.stopPropagation();
+        console.log("--------------");
+        overlay.setPosition(undefined);
+
+        if (e.selected.length == 0) {
+          console.log("999999");
+
+          that.polygonInfo = "";
+          that.nodeId = "";
+          that.myNode = null;
+          return false;
+        }
+
+        if (e.selected[0].values_.type == "node") {
+          that.isHidden = false;
+          that.nodeId = e.selected[0].values_.id;
+          return false;
+        }
+
+        if (myPolygon.polygonName) {
+          that.polygonInfo = myPolygon.polygonName;
+        } else {
+          that.polygonInfo = "鏂板尯鍩�";
+        }
+        if (e.mapBrowserEvent) {
+          console.log(e.mapBrowserEvent.coordinate);
+          overlay.setPosition(e.mapBrowserEvent.coordinate);
+        }
+
+        return false;
+      });
+
+      select2.on("select", function (e) {
+        if (
+          e.selected.length &&
+          e.selected[0].values_.type == "node" &&
+          that.myNodeHover &&
+          that.myNodeHover.values_.id == e.selected[0].values_.id
+        ) {
+          overlay2.setPosition(e.mapBrowserEvent.coordinate);
+        } else {
+        }
+      });
     },
     initNode([x, y], color) {
       const iconFeature = new Feature({
@@ -147,12 +360,19 @@
 
       iconFeature.setStyle(iconStyle);
       this.iconArr.push(iconFeature);
+      iconFeature.set("color", `${color}`);
+      iconFeature.set("lat", `${x}`);
+      iconFeature.set("lng", `${y}`);
+
       return iconFeature;
     },
     initAllNode() {
       this.nodeArr.forEach((item) => {
         const node = this.initNode(item.data, item.color);
         node.set("id", item.id);
+        node.set("type", "node");
+        node.set("battery", item.battery);
+        this.nodeFeature.push(node);
         myVectorSource.addFeature(node);
       });
     },
@@ -161,6 +381,9 @@
       this.polygonArr.forEach((item) => {
         const feature = new Feature({ geometry: new Polygon([item.data]) });
         feature.id = item.id;
+        feature.type = "polygon";
+        feature.polygonName = item.name;
+        feature.data1 = item.data[1];
         this.polyFeature.push(feature);
       });
     },
@@ -179,6 +402,19 @@
       });
     },
     initBottomMap(vectorLayer) {
+      const info = document.querySelector("#polygonInfo");
+      const helmet_box = document.querySelector(".helmet_box");
+      overlay2 = new Overlay({
+        element: helmet_box,
+        autoPan: true,
+        autoPanAnimation: {
+          duration: 250,
+        },
+      });
+
+      overlay = new Overlay({
+        element: info,
+      });
       return new Map({
         target: "map-index",
         layers: [baseLayer, vectorLayer],
@@ -186,6 +422,7 @@
           center: transform(this.center, "EPSG:4326", "EPSG:3857"),
           zoom: this.zoom,
         }),
+        overlays: [overlay, overlay2],
       });
     },
     zoomIn() {
@@ -204,6 +441,20 @@
       view.setCenter(transform(this.center, "EPSG:4326", "EPSG:3857"));
     },
     drawPolygon() {
+      this.rangeArr = [];
+      this.myNodeHover = null;
+      //   this.myNode = null;
+      //   this.nodeId = "";
+      mySelect2.getFeatures().clear();
+
+      mySelect.dispatchEvent({
+        type: "select",
+        selected: [],
+      });
+
+      this.resetMap();
+      mySelect.setActive(false);
+      mySelect2.setActive(false);
       this.showBtn = true;
       const draw = new Draw({
         source: myVectorSource,
@@ -232,15 +483,16 @@
         }
 
         event.feature.id = id;
+        event.feature.type = "polygon";
         this.drawStore.push({
           id,
           data: event.feature.getGeometry().getCoordinates()[0],
         });
+        drawFeature.push(event.feature);
       });
 
       const modify = new Modify({ source: myVectorSource });
       modify.addEventListener("modifyend", (event) => {
-        console.log(event.features);
         const id = event.features.array_[0].id;
         const data = event.features.array_[0].getGeometry().getCoordinates()[0];
         this.modifyStore.push({ id, data });
@@ -250,14 +502,16 @@
       myMap.addInteraction(draw);
     },
     resetMap() {
+      drawFeature = [];
+      this.polygonInfo = "";
+      mySelect.setActive(true);
+      mySelect2.setActive(true);
       this.initPolygonArr();
-      console.log(this.polyFeature);
       const vectorSource = new VectorSource({
         features: this.polyFeature,
       });
       /* if(this.polygonArr.length>0){
       this.initPolygonArr()
-      console.log(this.polyFeature);
       vectorSource.addFeature(this.polyFeature[0])
       } */
       myVectorSource = vectorSource;
@@ -272,6 +526,8 @@
       this.modifyStore = [];
     },
     async savePoly() {
+      mySelect.setActive(true);
+      mySelect2.setActive(true);
       myMap.removeInteraction(myDraw);
       myMap.removeInteraction(myModify);
       this.showBtn = false;
@@ -291,7 +547,6 @@
       }
       const arrData = this.polygonArr.map((item) => {
         let name = item.name ? item.name : "";
-        console.log(item);
         let data = item.data.map((arr) => {
           arr = transform([arr[0], arr[1]], "EPSG:3857", "EPSG:4326");
           return arr.join(",");
@@ -304,7 +559,215 @@
         };
       });
       const res = await createZones({ dots_arr: arrData });
-      console.log(res);
+      if (res.status == 200) {
+        this.$message({
+          type: "success",
+          message: "淇濆瓨鎴愬姛!",
+        });
+      } else {
+        this.$message({
+          type: "info",
+          message: "淇濆瓨澶辫触",
+        });
+      }
+
+      const res2 = await getZones();
+      if (res2.data && res2.data.items && res2.data.items.length > 0) {
+        this.polygonArr = res2.data.items.map((obj) => {
+          obj.data = obj.dots.map((item) => {
+            return transform([item[0], item[1]], "EPSG:4326", "EPSG:3857");
+          });
+          return obj;
+        });
+      }
+
+      if (drawFeature.length > 0) {
+        this.polyFeature.forEach((item) => {
+          myVectorSource.removeFeature(item);
+        });
+        this.initPolygonArr();
+
+        this.polyFeature.forEach((item) => {
+          myVectorSource.addFeature(item);
+        });
+      }
+
+      //   ;
+
+      /*  const res = await getHelemtData();
+      this.nodeArr = [];
+      res.data.items.forEach((item) => {
+        this.nodeArr.push({
+          data: [item.lng, item.lat],
+          id: item.device_sn,
+          color: item.is_out_bound == 0 ? "缁�" : "绾�",
+        });
+      });
+      this.nodeFeature.forEach((item) => {
+        myVectorSource.removeFeature(item);
+      });
+      this.initNode();
+      this.initAllNode(); */
+    },
+    delPoly() {
+      this.$confirm("姝ゆ搷浣滃皢鍒犻櫎璇ュ尯鍩�, 鏄惁缁х画?", "鎻愮ず", {
+        confirmButtonText: "纭畾",
+        cancelButtonText: "鍙栨秷",
+        type: "warning",
+      })
+        .then(async () => {
+          myVectorSource.removeFeature(myPolygon);
+          const res = await delZones({ id: myPolygon.id });
+          if (res.status == 200) {
+            this.$message({
+              type: "success",
+              message: "鍒犻櫎鎴愬姛!",
+            });
+            this.polygonInfo = "";
+            const res2 = await getZones();
+            if (res2.data && res2.data.items && res2.data.items.length > 0) {
+              this.polygonArr = res2.data.items.map((obj) => {
+                obj.data = obj.dots.map((item) => {
+                  return transform(
+                    [item[0], item[1]],
+                    "EPSG:4326",
+                    "EPSG:3857"
+                  );
+                });
+                return obj;
+              });
+            }
+          } else {
+            this.$message({
+              type: "info",
+              message: "鍒犻櫎澶辫触",
+            });
+          }
+        })
+        .catch(() => {
+          this.$message({
+            type: "info",
+            message: "宸插彇娑堝垹闄�",
+          });
+        });
+    },
+    showVideo() {
+      if (!this.myNode) {
+        return false;
+      }
+
+      this.isHidden = false;
+    },
+    hiddenVideo() {
+      document.querySelector("video").pause();
+      this.isHidden = true;
+    },
+    close() {
+      overlay2.setPosition(undefined);
+    },
+    onCommentInputChange() {
+      let value = document.querySelector("#commentContent").value;
+      voiceText = value;
+      let cont = 20 - value.length;
+      document.querySelector(
+        "#comment_info"
+      ).innerHTML = `杩樺彲杈撳叆${cont}涓瓧绗;
+    },
+    sendVoice() {
+      const _this = this;
+      this.isSending = true;
+
+      const h = this.$createElement;
+      this.$msgbox({
+        message: h(
+          "div",
+          {
+            attrs: {
+              class: "el-textarea",
+            },
+          },
+          [
+            h(
+              "div",
+              {
+                attrs: {
+                  class: "el-title",
+                },
+              },
+              [
+                h(
+                  "span",
+                  {
+                    attrs: {
+                      class: "icon iconfont",
+                    },
+                  },
+                  "\ue7cc"
+                ),
+                h("span", null, "鍙戦�佽闊�"),
+              ]
+            ),
+            h("textarea", {
+              attrs: {
+                placeholder: "璇疯緭鍏ヨ闊冲懡浠�",
+                maxlength: "20",
+                class: "el-textarea__inner",
+                autocomplete: "off",
+                rows: 3,
+                id: "commentContent",
+              },
+              value: this.commentContent,
+              on: { input: this.onCommentInputChange },
+            }),
+            h(
+              "div",
+              { attrs: { class: "info", id: "comment_info" } },
+              "杩樺彲杈撳叆20涓瓧绗�"
+            ),
+          ]
+        ),
+        showCancelButton: true,
+        confirmButtonText: "纭畾",
+        confirmButtonClass: "hele_btn_save",
+        cancelButtonClass: "hele_btn_cancel",
+        cancelButtonText: "鍙栨秷",
+        beforeClose: (action, instance, done) => {
+          document.querySelector("#commentContent").value = "";
+          document.querySelector(
+            "#comment_info"
+          ).innerHTML = `杩樺彲杈撳叆20涓瓧绗;
+          _this.isSending = false;
+          done();
+        },
+      })
+        .then((action) => {
+          if (action == "confirm") {
+            if (!voiceText) {
+              this.$message({
+                message: "鎸囦护涓嶈兘涓虹┖",
+                type: "warning",
+              });
+              _this.isSending = false;
+              return;
+            }
+            sendAudio(_this.myNode.values_.id, voiceText).then((res) => {
+              this.$message({
+                message: "鎸囦护鍙戦�佹垚鍔�",
+                type: "success",
+              });
+              _this.isSending = false;
+            });
+            _this.isSending = false;
+          } else {
+            _this.isSending = false;
+          }
+        })
+        .catch(() => {
+          _this.isSending = false;
+        });
+    },
+    aClick() {
+      return false;
     },
   },
   watch: {
@@ -318,22 +781,40 @@
             this.rangeArr = [];
           }
 
-          return;
+          return false;
         }
 
         const res = await getHelemtData({ sn: val });
+
+        if (res.msg == "zone") {
+          mySelect.getFeatures().clear();
+          const polyArr = this.polyFeature.filter((item) => {
+            return item.id == res.data.ID;
+          });
+
+          myPolygon = polyArr[0];
+          mySelect.getFeatures().push(polyArr[0]);
+          mySelect.dispatchEvent({
+            type: "select",
+            selected: [polyArr[0]],
+            mapBrowserEvent: {
+              coordinate: polyArr[0].data1,
+            },
+          });
+
+          return;
+        }
+
         const arr = [];
         if (res.data.items && res.data.items.length > 0) {
           res.data.items.forEach((obj) => {
             this.nodeArr.forEach((item) => {
-              if ((item.id = obj.device_sn)) {
+              if (item.id == obj.device_sn) {
                 arr.push(item);
               }
             });
           });
         }
-
-        console.log(this.rangeArr);
 
         if (this.rangeArr.length > 0) {
           this.rangeArr.forEach((item) => {
@@ -362,6 +843,7 @@
 
             rangeFeature.setStyle(iconStyle);
             myVectorSource.addFeature(rangeFeature);
+            rangeFeature.set("type", "range");
             this.rangeArr.push(rangeFeature);
           });
         }
@@ -372,12 +854,106 @@
 </script>
 
 <style scoped lang="scss">
+a {
+  background-color: transparent;
+  color: #337ab7;
+  text-decoration: none;
+}
+a:active a:hover {
+  outline: 0;
+}
+
 #map-index {
   position: relative;
   margin: 20px 0;
-  width: 1170px;
+  width: 100%;
   height: 396px;
   border-radius: 15px;
+
+  .helmet_box {
+    width: 205px;
+    height: 172px;
+    padding: 10px 10px 20px 15px;
+    font-size: 12px;
+    background: rgba(255, 255, 255, 0.7);
+    backdrop-filter: blur(4px);
+    border-radius: 15px;
+    text-align: left;
+
+    .icon_close {
+      text-align: right;
+      cursor: pointer;
+    }
+
+    .sn {
+      color: #f54336;
+    }
+    .location {
+      margin: 10px 0;
+    }
+    .button {
+      margin-top: 10px;
+      text-align: center;
+      img {
+        cursor: pointer;
+        width: 22px;
+        &:first-child {
+          margin-right: 48px;
+        }
+      }
+    }
+  }
+
+  .video_box {
+    box-sizing: border-box;
+    overflow: hidden;
+    position: absolute;
+    z-index: 2;
+    top: 45px;
+    right: 25px;
+    width: 483px;
+    height: 306px;
+    background: rgba(241, 250, 246, 0.6);
+    backdrop-filter: blur(4px);
+    /* Note: backdrop-filter has minimal browser support */
+    border-radius: 15px;
+    border: 1px solid rgb(17, 170, 102);
+    transition: all linear 0.5s;
+
+    &.hidden {
+      width: 0;
+      border: none;
+    }
+
+    .title {
+      margin: 15px 40px 0 20px;
+      width: 420px;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      color: #4f4f4f;
+      font-size: 12px;
+
+      .left {
+        .ball {
+          display: inline-block;
+          width: 0;
+          height: 0;
+          border: 4px solid #f54336;
+          border-radius: 2px;
+          margin-right: 10px;
+        }
+      }
+    }
+
+    video {
+      margin: 8px 40px 0 20px;
+      width: 424px;
+      height: 246px;
+      object-fit: fill;
+    }
+  }
+
   .control {
     position: absolute;
     display: flex;
@@ -464,6 +1040,85 @@
     line-height: 36px;
     cursor: pointer;
   }
+
+  .del {
+    position: absolute;
+    z-index: 3;
+    top: 15px;
+    right: 113px;
+    width: 87px;
+    height: 35px;
+    background: rgb(245, 108, 108);
+    border: 1px solid rgb(245, 108, 108);
+    border-radius: 8px;
+    color: #fff;
+    font-size: 12px;
+    line-height: 36px;
+    cursor: pointer;
+  }
+
+  .video_icon {
+    position: absolute;
+    z-index: 3;
+    top: 179px;
+    right: 10px;
+    width: 37px;
+  }
+
+  #polygonInfo {
+    position: absolute;
+    padding: 10px;
+    border: 1px solid;
+    color: black;
+    background-color: #fff;
+    z-index: 3;
+    width: 100px;
+  }
+
+  .mask {
+    position: fixed;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    text-align: center;
+    z-index: 4;
+    background-color: black;
+    opacity: 0.5;
+  }
+}
+
+.el-textarea {
+  height: 150px;
+  padding: 0 15px;
+
+  .el-title {
+    margin-top: 20px;
+    margin-bottom: 15px;
+    color: #4f4f4f;
+    font-size: 16px;
+    font-weight: 700;
+
+    .icon {
+      font-weight: normal;
+      font-size: 19px;
+    }
+  }
+
+  .el-textarea__inner {
+    width: 357px;
+
+    &:focus {
+      border: 1px solid #11aa66;
+    }
+  }
+
+  .info {
+    font-size: 12px;
+    color: #828282;
+    text-align: right;
+    padding-right: 38px;
+  }
 }
 </style>
 
diff --git a/src/pages/internetEquipment/module/realTimeModule.vue b/src/pages/internetEquipment/module/realTimeModule.vue
index 140629d..198a452 100644
--- a/src/pages/internetEquipment/module/realTimeModule.vue
+++ b/src/pages/internetEquipment/module/realTimeModule.vue
@@ -1,17 +1,27 @@
 <template>
   <div class="real-time-module">
     <div class="title">瀹炴椂鎶撴媿棰勮</div>
-    <div class="real-time-item" v-for="(item, index) in boundArr" :key="index">
-      <img :src="item.snap_shot" alt="" class="warnArea" />
-      <warnDescription
-        :warnDes="{
-          code: item.device_sn,
-          time: item.updated_at,
-          longitude: item.lng,
-          latitude: item.lat,
-          warn: '鏈湪鐢靛瓙鍥存爮鍖哄煙',
-        }"
-      />
+    <div class="real-time-list">
+      <div
+        class="real-time-item"
+        v-for="(item, index) in boundArr"
+        :key="index"
+      >
+        <img
+          :src="'http://192.168.8.10:9000' + item.snap_shot"
+          alt=""
+          class="warnArea"
+        />
+        <warnDescription
+          :warnDes="{
+            code: item.device_sn,
+            time: item.updated_at,
+            longitude: item.lng,
+            latitude: item.lat,
+            warn: '鏈湪鐢靛瓙鍥存爮鍖哄煙',
+          }"
+        />
+      </div>
     </div>
   </div>
 </template>
@@ -32,10 +42,7 @@
 
 <style scoped lang="scss">
 .real-time-module {
-  display: flex;
-  flex-wrap: wrap;
   padding: 20px;
-  padding-right: 0px;
   width: 570px;
   height: 292px;
   background-color: #fff;
@@ -43,17 +50,29 @@
   border-radius: 15px;
   overflow-y: scroll;
 
+  .real-time-list {
+    display: grid;
+    justify-content: space-between;
+    grid-template-columns: repeat(auto-fill, 170px);
+    grid-gap: 10px;
+  }
+
   .title {
     margin-bottom: 10px;
     font-size: 14px;
     font-weight: 700;
-    width: 530px;
+    width: 100%;
     text-align: left;
   }
 
   .real-time-item {
-    margin-right: 13px;
+    margin-right: 10px;
   }
+
+  .real-time-item:last-child {
+    margin-right: auto;
+  }
+
   .warnArea {
     width: 167px;
     height: 104px;
diff --git a/src/pages/internetEquipment/views/helemetEquipment.vue b/src/pages/internetEquipment/views/helemetEquipment.vue
index ee3abec..d9e407a 100644
--- a/src/pages/internetEquipment/views/helemetEquipment.vue
+++ b/src/pages/internetEquipment/views/helemetEquipment.vue
@@ -53,6 +53,7 @@
 }
 
 .helmet-equipment {
+  position: relative;
   padding: 20px;
   width: 100%;
   height: 100%;
@@ -63,13 +64,27 @@
   }
 
   .footer {
-    height: 292px;
+    position: absolute;
+    top: 540px;
+    left: 20px;
+    right: 20px;
+    bottom: 20px;
     display: flex;
     justify-content: start;
     color: #4f4f4f;
-
+    .real-time-module {
+      flex: 2.35;
+      height: 100%;
+    }
     .elec-module {
+      flex: 1;
       margin: 0 20px;
+      height: 100%;
+    }
+
+    .history-module {
+      flex: 1;
+      height: 100%;
     }
   }
 }
diff --git a/src/pages/login/App.vue b/src/pages/login/App.vue
new file mode 100644
index 0000000..6754bff
--- /dev/null
+++ b/src/pages/login/App.vue
@@ -0,0 +1,564 @@
+<template>
+  <!-- <div class v-loading="vLoading" :style="`width: ${currentWidth}px;height:${currentHeight}px`">
+    <div class="web-site">
+      <a href="http://www.smartai.com" target="_blank">www.smartai.com</a>
+    </div>
+
+    <lang-select class="lang-select"/>
+    <licence />
+    <div class="right-bg" style>
+      <particle-network />
+    </div>
+    <div class="left-bg">
+      <div class="login-logo">
+        <img src="/images/login-logo.png" alt width="105px" height="105px" />
+      </div>
+      <div class="login-com">
+        <span>{{ $t('login.company') }}</span>
+      </div>
+      <div class="login-form">
+        <el-form
+          :model="user"
+          status-icon
+          :rules="nullRule"
+          :validate-on-rule-change="false"
+          ref="ruleForm"
+          class="demo-ruleForm"
+        >
+          <el-form-item prop="loginName">
+            <el-input v-model="user.loginName" style="width:280px" :placeholder="$t('placeholder.enterUsername')">
+              <i slot="prefix" class="iconfont iconyonghu1"></i>
+            </el-input>
+          </el-form-item>
+          <el-form-item prop="password">
+            <el-input
+              show-password
+              @keyup.enter.native="systemLogin()"
+              v-model="user.password"
+              autocomplete="off"
+              style="width:280px"
+              :placeholder="$t('placeholder.enterPassword')"
+            >
+              <i slot="prefix" class="iconfont iconmima"></i>
+            </el-input>
+          </el-form-item>
+          <el-form-item>
+            <el-button ref="submit" type="warning" @click="systemLogin()" style="width:280px">{{ $t('button.login') }}</el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+      <p class="gradient-text gradient-text-one">
+        鈥斺��
+        <b>SmartAI</b> {{ $t('login.aios') }} 鈥斺��
+      </p>
+      <p
+        class="gradient-text gradient-text-one"
+        style="letter-spacing: 1.8px;font-size:15px;"
+      >V1.0.0</p>
+    </div>
+  </div> -->
+  <div class="login">
+    <div class="title">
+      <div class="en">Smart AI</div>
+      <div class="ch">浜哄伐鏅鸿兘鎿嶄綔绯荤粺</div>
+    </div>
+
+    <div class="left_footer">
+      <img class="logo" src="/images/login/LOGO.png" alt="" />
+      <div class="web">www.smartai.com</div>
+    </div>
+
+    <div
+      class="login-form"
+      :style="{ background: backgroundColor }"
+      :class="{ empty: !user.loginName && !user.password }"
+    >
+      <img class="logo" src="/images/login/OS.png" alt="" />
+
+      <el-form
+        :model="user"
+        status-icon
+        :rules="nullRule"
+        :validate-on-rule-change="false"
+        ref="ruleForm"
+        class="demo-ruleForm"
+      >
+        <el-form-item prop="loginName">
+          <el-input
+            v-model="user.loginName"
+            :placeholder="$t('placeholder.enterUsername')"
+          >
+            <i slot="prefix" class="iconfont icon">&#xe7e5;</i>
+          </el-input>
+        </el-form-item>
+        <el-form-item prop="password">
+          <el-input
+            show-password
+            @keyup.enter.native="systemLogin()"
+            v-model="user.password"
+            autocomplete="off"
+            :placeholder="$t('placeholder.enterPassword')"
+          >
+            <i slot="prefix" class="iconfont icon">&#xe7e4;</i>
+          </el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button ref="submit" type="warning" @click="systemLogin()">{{
+            $t("button.login")
+          }}</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+  </div>
+</template>
+
+<script>
+import { tologin, getLoginUserData, getServerName } from "./api.ts";
+import ParticleNetwork from "./ParticleNetwork";
+import Licence from "@/components/licence";
+import LangSelect from "@/components/langSelect";
+import { getMenuListData } from "@/api/utils";
+
+export default {
+  name: "login-pgae",
+  metaInfo: {
+    title: "鐧诲綍椤�",
+  },
+  components: {
+    //  ParticleNetwork,
+    // Licence,
+    //  LangSelect
+  },
+  computed: {
+    rules() {
+      return {
+        loginName: [
+          {
+            required: true,
+            message: this.$t("placeholder.enterUsername"),
+            trigger: "change",
+          },
+        ],
+        password: [
+          {
+            required: true,
+            message: this.$t("placeholder.enterPassword"),
+            trigger: "change",
+          },
+        ],
+      };
+    },
+  },
+  data: () => ({
+    serverTitle: "",
+    user: {
+      loginName: "",
+      password: "",
+      rememberMe: false,
+    },
+    nullRule: {},
+
+    loading: "",
+    vLoading: false,
+    currentHeight: 1057,
+    currentWidth: 1920,
+    backgroundColor: "",
+    backgroundList: [
+      "#2A2344",
+      "#342344",
+      "#000000",
+      "#233044",
+      "#0B252E",
+      "#150051",
+      "#110040",
+    ],
+  }),
+  created() {
+    this.getServerName();
+    this.getScreenHeight();
+    this.backgroundColor =
+      this.backgroundList[
+        Math.floor(Math.random() * this.backgroundList.length)
+      ];
+  },
+  mounted() {
+    // 鑷姩鐧诲綍鎺ュ彛
+    this.loginRobot();
+  },
+  watch: {},
+  beforeDestroy() {
+    window.onresize = null;
+  },
+  methods: {
+    loginRobot() {
+      // 瑙f瀽璺敱鍙傛暟锛屽苟缂撳瓨
+      let user = this.getQueryVariable("username");
+      let passwd = this.getQueryVariable("password");
+      if (user.length && passwd.length) {
+        sessionStorage.setItem(
+          "autoLogin",
+          JSON.stringify({ username: user, passwd: passwd })
+        );
+
+        this.user.loginName = user;
+        this.user.password = passwd;
+        this.systemLogin();
+        return;
+      }
+
+      // 鐧婚檰瓒呮椂鍚庣殑閲嶆柊鐧婚檰
+      let sessionInfo = sessionStorage.getItem("autoLogin");
+      if (sessionInfo) {
+        let authority = JSON.parse(sessionInfo);
+        this.user.loginName = authority.username;
+        this.user.password = authority.passwd;
+        this.systemLogin();
+      }
+    },
+    systemLogin() {
+      this.nullRule = this.rules;
+      this.$nextTick(() => {
+        this.$refs["ruleForm"].validate((valid) => {
+          if (valid) {
+            this.loading = this.$loading({
+              lock: true,
+              text: "Loading",
+              spinner: "el-icon-loading",
+              background: "rgba(0, 0, 0, 0.7)",
+            });
+            this.testLogin();
+          } else {
+            this.nullRule = {};
+          }
+        });
+        this.nullRule = {};
+      });
+    },
+    async testLogin() {
+      // location.assign("/view/desktop/")
+      tologin({ username: this.user.loginName, password: this.user.password })
+        .then((json) => {
+          const loginedInfo = {
+            access_token: json.token_type + " " + json.access_token,
+            refresh_token: json.refresh_token,
+          };
+          sessionStorage.setItem("expires_in", json.expires_in);
+          sessionStorage.setItem("loginedInfo", JSON.stringify(loginedInfo));
+          this.loading.close();
+          this.getLoginUserData();
+        })
+        .catch((err) => {
+          this.loading.close();
+          this.$notify({
+            title: "鎻愮ず",
+            type: "error",
+            message: err.msg,
+          });
+          this.$refs.pwd.focus();
+        });
+    },
+    async getLoginUserData() {
+      let res = await getLoginUserData();
+      if (res.success) {
+        sessionStorage.setItem("userInfo", JSON.stringify(res.data));
+        this.$notify.success("鐧诲綍鎴愬姛锛�");
+        // 鑾峰彇鏉冮檺
+        await this.getMenuList();
+        location.assign("/view/desktop/");
+        return res.data;
+      } else {
+        this.$notify.error("鐧诲綍澶辫触锛�");
+      }
+    },
+
+    getScreenHeight() {
+      this.currentHeight = document.documentElement.clientHeight;
+      this.currentWidth = document.documentElement.clientWidth;
+      window.onresize = () => {
+        this.currentHeight = document.documentElement.clientHeight;
+        this.currentWidth = document.documentElement.clientWidth;
+        this.$forceUpdate();
+      };
+    },
+    async getServerName() {
+      let res = await getServerName();
+      if (res && res.success) {
+        this.serverTitle = res.data.serverName;
+        window.document.title = res.data.serverName
+          ? res.data.serverName
+          : "SmartAI";
+        sessionStorage.setItem("title", res.data.serverName);
+      }
+    },
+    async getMenuList() {
+      let results = await getMenuListData({});
+      if (results && results.success) {
+        /* 瀛樺偍鏉冮檺 */
+        let buttonAuthoritys = results.data;
+        if (results && results.length && this.$route.query.is_login) {
+          this.$router.replace(results[0].url);
+        }
+        sessionStorage.setItem(
+          "buttonAuthoritys",
+          "," + buttonAuthoritys + ","
+        );
+        sessionStorage.setItem("menuInfo", JSON.stringify(results));
+      } else {
+        this.$toast({
+          type: "error",
+          message: "鑿滃崟鑾峰彇澶辫触",
+        });
+      }
+    },
+    getQueryVariable(variable) {
+      var query = window.location.search.substring(1);
+      var vars = query.split("&");
+      for (var i = 0; i < vars.length; i++) {
+        var pair = vars[i].split("=");
+        if (pair[0] == variable) {
+          return pair[1];
+        }
+      }
+      return false;
+    },
+  },
+};
+</script>
+<style lang="scss">
+.login {
+  height: 100%;
+  position: relative;
+  background-image: url("/images/login/鑳屾櫙鍥�.png");
+
+  .title {
+    position: absolute;
+    top: 345px;
+    left: 301px;
+    color: #fff;
+    text-align: center;
+
+    .en {
+      font-size: 120px;
+    }
+
+    .ch {
+      font-size: 48px;
+      letter-spacing: 9px;
+    }
+  }
+
+  .left_footer {
+    position: absolute;
+    display: flex;
+    justify-content: start;
+    align-items: center;
+    left: 358px;
+    bottom: 40px;
+
+    .logo {
+      width: 136px;
+      margin-right: 30px;
+    }
+
+    .web {
+      font-size: 24px;
+      font-weight: 700;
+      color: rgba(255, 255, 255, 0.7);
+    }
+  }
+
+  .login-form {
+    position: absolute;
+    width: 780px;
+    height: 1000px;
+    right: 40px;
+    top: 40px;
+    padding: 0 90px;
+    box-sizing: border-box;
+
+    background: #2a2344;
+    opacity: 0.95;
+    box-shadow: -4px 0px 10px rgba(0, 0, 0, 0.25);
+    border-radius: 56px;
+
+    .logo {
+      margin-top: 100px;
+      margin-bottom: 16px;
+    }
+
+    .el-form-item {
+      background: rgba(0, 0, 0, 0);
+    }
+
+    .el-form-item:nth-child(2) {
+      margin-top: 60px;
+      margin-bottom: 80px;
+    }
+
+    .el-button {
+      width: 600px;
+      height: 60px;
+      background: #4e94ff;
+      border-radius: 30px;
+      border: none;
+    }
+
+    .el-input {
+      width: 100%;
+      background: rgba(0, 0, 0, 0);
+    }
+
+    input {
+      width: 100%;
+      height: 56px;
+      background: rgba(255, 255, 255, 0.1) !important;
+      border: 1px solid #4e94ff;
+      box-sizing: border-box;
+      border-radius: 28px;
+      color: #fff;
+      caret-color: #fff; //鍏夋爣棰滆壊
+      padding-left: 100px;
+      padding-right: 50px;
+      font-weight: 700;
+    }
+
+    input:-webkit-autofill,
+    textarea:-webkit-autofill,
+    select:-webkit-autofill {
+      -webkit-text-fill-color: #ededed !important;
+      -webkit-box-shadow: 0 0 0px 1000px transparent inset !important;
+      background-color: transparent;
+      background-image: none;
+      transition: background-color 50000s ease-in-out 0s; //鑳屾櫙鑹查�忔槑  鐢熸晥鏃堕暱  杩囨浮鏁堟灉  鍚敤鏃跺欢杩熺殑鏃堕棿
+    }
+
+    .el-form-item__error {
+      top: 110%;
+      left: 80px;
+    }
+
+    .icon {
+      font-size: 32px;
+      color: rgb(80, 151, 255);
+    }
+
+    .el-input__prefix {
+      padding: 0 20px;
+      height: 40px;
+      left: 5px;
+      top: 8px;
+      border-right: 1px solid #4e94ff;
+    }
+
+    .el-input__suffix {
+      right: 20px;
+    }
+
+    .el-icon-circle-close {
+      display: none;
+    }
+  }
+
+  .login-form.empty {
+    input {
+      border-color: #999;
+      color: #bbb;
+    }
+
+    .el-button {
+      background-color: #999;
+      color: #fff;
+    }
+
+    .icon {
+      color: #fff;
+    }
+
+    .el-input__prefix {
+      border-color: #d4d6d9;
+    }
+  }
+}
+
+// .right-bg {
+//   position: fixed;
+//   top: 0;
+//   left: 0;
+//   background-image: url("/images/login-net.png");
+
+//   width: 100%;
+//   height: 100%;
+//   min-width: 1000px;
+//   z-index: -10;
+//   zoom: 1;
+//   background-color: #fff;
+//   background-repeat: no-repeat;
+//   background-size: cover;
+//   -webkit-background-size: cover;
+//   -o-background-size: cover;
+//   background-position: center 0;
+// }
+// .web-site {
+//   position: absolute;
+//   top: 55px;
+//   left: 41px;
+//   font-family: PingFangSC-Medium;
+//   font-size: 20px;
+//   color: #6170e1;
+//   letter-spacing: 6.15px;
+// }
+// .lang-select {
+//   float: right;
+//   color: white !important;
+//   font-size: 14px;
+//   margin: 13px;
+//   cursor: pointer;
+// }
+// .left-bg {
+//   position: absolute;
+//   top: 29%;
+//   right: 18%;
+//   width: 390px;
+//   height: 426px;
+//   background: rgba(146, 208, 255, 0.23);
+//   border-radius: 4px;
+//   text-align: center;
+//   .login-logo {
+//     margin-top: -53px;
+//   }
+
+//   .login-com {
+//     font-family: PingFangSC-Medium;
+//     font-size: 22px;
+//     color: #ffffff;
+//     letter-spacing: 0.44px;
+//     margin: 15px;
+//   }
+//   .login-form {
+//     margin: 40px 10px;
+//   }
+//   .gradient-text {
+//     line-height: 36px;
+//     font-size: 17px;
+//     font-family: -webkit-pictograph;
+//     font-weight: bolder;
+//     position: relative;
+//     b {
+//       font-size: 20px;
+//     }
+//   }
+//   .gradient-text-one {
+//     background-image: linear-gradient(to right, #51feff 5%, #ff8725 100%);
+//     -webkit-background-clip: text;
+//     -webkit-text-fill-color: transparent;
+//   }
+
+//   .el-input__prefix {
+//     left: 8px;
+//   }
+
+//   .el-form-item__error {
+//     left: 54px;
+//   }
+// }
+</style>
diff --git a/src/pages/login/ParticleNetwork.vue b/src/pages/login/ParticleNetwork.vue
new file mode 100644
index 0000000..53a1e12
--- /dev/null
+++ b/src/pages/login/ParticleNetwork.vue
@@ -0,0 +1,348 @@
+<template>
+  <div class="particle-network-animation" :style="`height:${height}px;width:${width}px`">
+    <div style="display:none">
+      <img ref="conf0" src="/images/login/0.png" />
+      <img ref="conf1" src="/images/login/1.png" />
+      <img ref="conf2" src="/images/login/2.png" />
+      <img ref="conf3" src="/images/login/3.png" />
+      <img ref="conf4" src="/images/login/4.png" />
+      <img ref="conf5" src="/images/login/5.png" />
+      <img ref="conf6" src="/images/login/6.png" />
+      <img ref="conf7" src="/images/login/7.png" />
+      <img ref="conf8" src="/images/login/8.png" />
+      <img ref="conf9" src="/images/login/9.png" />
+      <img ref="conf10" src="/images/login/10.png" />
+      <img ref="conf11" src="/images/login/11.png" />
+      <img ref="conf12" src="/images/login/12.png" />
+      <img ref="conf13" src="/images/login/13.png" />
+      <img ref="conf14" src="/images/login/14.png" />
+      <img ref="conf15" src="/images/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]
+        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>
diff --git a/src/pages/login/api.ts b/src/pages/login/api.ts
new file mode 100644
index 0000000..4d4c24f
--- /dev/null
+++ b/src/pages/login/api.ts
@@ -0,0 +1,66 @@
+import request from '@/scripts/httpRequest'
+import qs from 'qs'
+
+// 鐧诲綍
+export const tologin = (query: any) => {
+  // let query = 'username=' + user.loginName + '&password=' + user.password
+  return request({
+    url: '/data/api-u/sys/login',
+    method: 'post',
+    data: qs.stringify(query)
+  })
+}
+
+// 閫�鍑�
+export const logout = () => {
+  return request({
+    url: '/data/api-u/sys/logout',
+    method: 'get'
+  })
+}
+
+// 鑾峰彇鐢ㄦ埛淇℃伅
+// export const getLoginUserData = () => {
+//   let token =
+//     sessionStorage.getItem('loginedInfo') &&
+//     JSON.parse(sessionStorage.getItem('loginedInfo')).access_token
+//   return request({
+//     url: '/data/api-u/users/current',
+//     method: 'get',
+//     headers: {
+//       'Content-Type': 'application/x-www-form-urlencoded',
+//       Authorization: token || ''
+//     }
+//   })
+// }
+
+export const getLoginUserData = () => {
+    let token =
+      sessionStorage.getItem('loginedInfo') &&
+      JSON.parse(sessionStorage.getItem('loginedInfo')).access_token
+    return request({
+      url: '/data/api-u/users/profile',
+      method: 'get',
+      headers: {
+        'Content-Type': 'application/x-www-form-urlencoded',
+        Authorization: token || ''
+      }
+    })
+  }
+
+//淇敼瀵嗙爜
+export const updatePwd = (query: any) => {
+  return request({
+    url: '/data/api-u/users/updatePwd',
+    method: 'post',
+    data: qs.stringify(query)
+  })
+}
+
+//鑾峰彇椤圭洰鍚嶇О
+export const getServerName = (query: any) => {
+  return request({
+    url: '/data/api-v/info/getServerName',
+    method: 'get'
+  })
+}
diff --git a/src/pages/login/main.ts b/src/pages/login/main.ts
new file mode 100644
index 0000000..1a04451
--- /dev/null
+++ b/src/pages/login/main.ts
@@ -0,0 +1,18 @@
+import Vue from 'vue'
+import App from './App.vue'
+
+import ElementUI from 'element-ui'
+import 'element-ui/lib/theme-chalk/index.css'
+import '@/assets/css/element-variables.scss'
+
+import i18n from '@/lang'
+
+Vue.use(ElementUI, {
+  i18n: (key, value) => i18n.t(key, value),
+})
+
+new Vue({
+  el: '#app',
+  i18n,
+  render: (h) => h(App),
+})
diff --git a/vue.config.js b/vue.config.js
index f4b88d8..9cebf58 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -40,8 +40,8 @@
   // }
 });
 
-// const serverUrl = "http://192.168.20.189/:7009"; // 缇婁簲
-const serverUrl = "http://192.168.8.10:7009";
+const serverUrl = "http://192.168.20.189:7009"; // 缇婁簲
+//  const serverUrl = "http://192.168.8.10:7009";
 const serverUrl2 = "http://192.168.8.10:9000";
 // const serverUrl = "http://192.168.20.10:7009";
 // const serverUrl2 = "http://192.168.20.10:9000";

--
Gitblit v1.8.0