From eb82684152ffb0acddf67da92e4533a0190eb258 Mon Sep 17 00:00:00 2001
From: MrShi <1878285526@qq.com>
Date: 星期五, 10 十月 2025 18:27:31 +0800
Subject: [PATCH] 对接口

---
 admin/src/views/login.vue |  458 +++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 397 insertions(+), 61 deletions(-)

diff --git a/admin/src/views/login.vue b/admin/src/views/login.vue
index 5d27534..12a0bb7 100644
--- a/admin/src/views/login.vue
+++ b/admin/src/views/login.vue
@@ -1,36 +1,96 @@
 <template>
   <div class="wrap">
-    <div class="introduce">
-      <h2>璞嗙背璺宠烦</h2>
-      <h3></h3>
-    </div>
-    <div class="login">
-      <h1>绯荤粺鐧诲綍&nbsp;/&nbsp;LOGIN IN</h1>
-      <div class="info-input">
-        <el-input v-model="username" placeholder="璇疯緭鍏ョ敤鎴峰悕" prefix-icon="el-icon-user-solid" maxlength="50" v-trim/>
-        <el-input v-model="password" placeholder="璇疯緭鍏ュ瘑鐮�" type="password" prefix-icon="eva-icon-password" maxlength="30" show-password/>
-        <div class="captcha-input">
-          <el-input v-model="captcha.value" placeholder="鍥剧墖楠岃瘉鐮�" prefix-icon="eva-icon-shield" maxlength="4" @keypress.enter.native="login"/>
-          <img v-if="!captcha.loading" :src="captcha.uri" @click="refreshCaptcha">
-          <span v-else><i class="el-icon-loading"></i></span>
+    <img src="@/assets/images/bg@2x.png" class="main_bg" alt="">
+    <div class="login_wrap">
+      <div class="login_img">
+        <div class="h2">鑺滄箹鐑熻崏鏅烘収瀹夋秷瀹夊叏闃茶寖绯荤粺</div>
+        <div class="h3">鏅烘収鐗╂祦鍥尯瀹夋秷涓�浣撳寲绯荤粺</div>
+      </div>
+      <div class="form_wrap">
+        <div class="tabs">
+          <div class="tab" @click="tabClick('0')" :class="{ active: activeTab == '0' }">
+            <div class="name">甯愬彿鐧诲綍</div>
+            <div class="icon"></div>
+          </div>
+          <div class="tab" @click="tabClick('1')" :class="{ active: activeTab == '1' }">
+            <div class="name">鎵嬫満鐧诲綍</div>
+            <div class="icon"></div>
+          </div>
+        </div>
+        <template v-if="activeTab == '0'">
+          <div class="df_ac">
+            <div class="label">甯愬彿</div>
+            <div class="line">
+              <el-input v-model="username" placeholder="璇疯緭鍏ュ笎鍙�" maxlength="50" v-trim />
+            </div>
+          </div>
+          <div class="df_ac">
+            <div class="label">瀵嗙爜</div>
+            <div class="line">
+              <el-input v-model="password" placeholder="璇疯緭鍏ュ瘑鐮�" type="password" maxlength="30" show-password />
+            </div>
+          </div>
+          <div class="df_ac">
+            <div class="label">楠岃瘉鐮�</div>
+            <div class="line">
+              <el-input v-model="captcha.value" placeholder="璇疯緭鍏ラ獙璇佺爜" maxlength="4" @keypress.enter.native="login" />
+              <img v-if="!captcha.loading" class="code_image" :src="captcha.uri" @click="refreshCaptcha">
+              <span v-else><i class="el-icon-loading"></i></span>
+            </div>
+          </div>
+        </template>
+        <template v-if="activeTab == '1'">
+          <div class="df_ac">
+            <div class="label">鎵嬫満鍙�</div>
+            <div class="line">
+              <el-input v-model="phone" placeholder="璇疯緭鍏ユ墜鏈哄彿" type="text" maxlength="16" />
+            </div>
+          </div>
+          <div class="df_ac">
+            <div class="label">楠岃瘉鐮�</div>
+            <div class="line">
+              <el-input v-model="smsCode" placeholder="璇疯緭鍏ラ獙璇佺爜" maxlength="6" @keypress.enter.native="login" />
+              <span v-if="downTime == 0" class="code_get" @click="getCode">鑾峰彇楠岃瘉鐮�</span>
+              <span v-else class="code_get downtime">{{ downTime }}</span>
+            </div>
+          </div>
+        </template>
+
+        <el-button :loading="loading" type="primary" class="login_btn" @click.native.prevent="login">绔嬪嵆鐧诲綍</el-button>
+        <div class="btn_wrap">
+          <el-checkbox v-model="isRemPsd">
+            <span style="font-size: 13px; font-weight: 400" class="placeholder9">{{ activeTab == 0 ? '璁颁綇瀵嗙爜' : '璁颁綇鎵嬫満鍙�'
+              }}</span>
+          </el-checkbox>
+        </div>
+        <div class="google">
+          <img src="@/assets/images/ic_google@2x.png" class="img" alt="">
+          <span class="placeholder6">鏈郴缁熸帹鑽愪娇鐢℅OOGLE娴忚鍣�</span>
         </div>
       </div>
-      <el-button :loading="loading" @click="login">鐧�&nbsp;&nbsp;褰�</el-button>
     </div>
   </div>
 </template>
 
 <script>
 import { mapMutations } from 'vuex'
-import { getCaptcha, loginByPassword } from '@/api/system/common'
+import { getCaptcha, loginByPassword, sendSmsPost, loginByPhone } from '@/api/system/common'
+import Cookies from "js-cookie"
+import { Message } from 'element-ui'
 
 export default {
   name: 'Login',
-  data () {
+  data() {
     return {
       loading: false,
+      isRemPsd: false,
       username: '',
       password: '',
+      phone: '',
+      downTime: 0,
+
+      smsCode: '',
+      activeTab: '0',
       // 楠岃瘉鐮�
       captcha: {
         loading: false,
@@ -40,37 +100,97 @@
       }
     }
   },
+  mounted() {
+    this.username = localStorage.getItem('username') || ''
+    this.password = localStorage.getItem('password') || ''
+    this.phone = localStorage.getItem('phone') || ''
+    const isRemPsd = localStorage.getItem('isRemPsd') || false
+    this.isRemPsd = JSON.parse(isRemPsd)
+    this.refreshCaptcha()
+  },
   methods: {
     ...mapMutations(['setUserInfo']),
     // 鐧诲綍
-    login () {
+    login() {
       if (this.loading) {
         return
       }
-      if (!this.__check()) {
-        return
-      }
-      this.loading = true
-      loginByPassword({
-        username: this.username.trim(),
-        password: this.password,
-        code: this.captcha.value.trim(),
-        uuid: this.captcha.uuid
-      })
-        .then(() => {
-         // window.location.href = process.env.VUE_APP_CONTEXT_PATH
-          window.location.reload()
+      if (this.activeTab == 0) {
+        if (!this.__check()) {
+          return
+        }
+        this.loading = true
+        loginByPassword({
+          username: this.username.trim(),
+          password: this.password,
+          code: this.captcha.value.trim(),
+          uuid: this.captcha.uuid
         })
-        .catch(e => {
+          .then((res) => {
+            // window.location.href = process.env.VUE_APP_CONTEXT_PATH
+            if (this.isRemPsd) {
+              localStorage.setItem('username', this.username.trim())
+              localStorage.setItem('password', this.password.trim())
+              localStorage.setItem('isRemPsd', this.isRemPsd)
+            } else {
+              localStorage.removeItem('username')
+              localStorage.removeItem('password')
+              localStorage.removeItem('isRemPsd')
+            }
+            Cookies.set('dm_user_token', res)
+            this.$router.push('index')
+          })
+          .catch(e => {
+            this.refreshCaptcha()
+          })
+          .finally(() => {
+            this.loading = false
+          })
+      } else {
+        const { smsCode, phone } = this
+        if (!phone || phone.length != 11) {
+          return Message.error('璇疯緭鍏ユ纭殑鎵嬫満鍙�')
+        }
+        if (!smsCode) {
+          return Message.error('璇疯緭鍏ラ獙璇佺爜')
+        }
+        this.loading = true
+        loginByPhone({ phone, code: smsCode }).then(res => {
+          if (this.isRemPsd) {
+            localStorage.setItem('phone', this.username.trim())
+          }
+          Cookies.set('dm_user_token', res)
+          this.$router.push('index')
+        }).catch(e => {
           this.refreshCaptcha()
-          this.$tip.apiFailed(e)
-        })
-        .finally(() => {
+        }).finally(() => {
           this.loading = false
         })
+      }
+
+    },
+    getCode() {
+      console.log('getCode')
+      const { phone } = this
+      if (!phone || phone.length != 11) {
+        return Message.error('璇疯緭鍏ユ纭殑鎵嬫満鍙�')
+      }
+      sendSmsPost({ phone, type: 0 }).then(res => {
+        Message.success('鐭俊鍙戦�佹垚鍔�')
+        this.downTime = 60
+        let timer = setInterval(() => {
+          if (this.downTime == 0) {
+            return clearInterval(timer)
+          }
+          this.downTime--
+        }, 1000)
+      })
+    },
+    tabClick(val) {
+      this.activeTab = val
     },
     // 鍒锋柊楠岃瘉鐮�
-    refreshCaptcha () {
+    refreshCaptcha() {
       this.captcha.loading = true
       getCaptcha()
         .then(data => {
@@ -87,7 +207,7 @@
         })
     },
     // 鐧诲綍鍓嶉獙璇�
-    __check () {
+    __check() {
       if (this.username.trim() === '') {
         this.$tip.error('璇疯緭鍏ョ敤鎴峰悕')
         return false
@@ -103,47 +223,252 @@
       return true
     }
   },
-  created () {
-    this.refreshCaptcha()
-  }
+
 }
 </script>
 
 <style scoped lang="scss">
 @import "@/assets/style/variables.scss";
+
+div {
+  box-sizing: border-box;
+}
+
 $input-gap: 30px;
+
 .wrap {
-  display: flex;
   width: 100%;
   height: 100vh;
-  background-image: url("../assets/images/login.jpg");
-  background-repeat: no-repeat;
-  background-size: auto 180%;
-  background-clip: content-box;
-  background-position: center;
+  position: relative;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+
   // 宸﹁竟浠嬬粛
-  .introduce {
-    padding-left: 10%;
+  .main_bg {
+    position: absolute;
     width: 100%;
     height: 100%;
+    left: 0;
+    top: 0;
+    z-index: -1;
+  }
+
+  .login_wrap {
+    width: 1000px;
+    height: 600px;
     box-sizing: border-box;
-    color: #fff;
-    background: rgba(0, 0, 0, 0.4);
+    background: #ffffff;
+    box-shadow: 0px 20px 60px 0px rgba(0, 0, 0, 0.11);
     display: flex;
-    flex-direction: column;
-    justify-content: center;
-    h2 {
-      font-size:34px;
-      font-style: italic;
-      font-weight: 900;
-      margin-top: 50px;
+
+    .login_img {
+      width: 500px;
+      height: 600px;
+      background: url("../assets/images/login_img@2x.png");
+      background-size: 100% 100%;
+      padding-left: 40px;
+      padding-top: 60px;
+
+      .h2 {
+        color: $primary-color;
+        background-color: #fff;
+        height: 24px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        border-radius: 4px;
+        width: 208px;
+        display: flex;
+        margin-bottom: 12px;
+      }
+
+      .h3 {
+        font-size: 28px;
+        font-weight: 700;
+        color: #fff;
+        margin-bottom: 26px;
+      }
+
+      .text {
+        font-size: 18px;
+        color: #fff;
+      }
     }
-    h3 {
-      font-size: 49px;
-      font-weight: 300;
-      margin: 25px 0;
+
+    .form_wrap {
+      flex: 1;
+      height: 100%;
+      background-color: #fff;
+      box-sizing: border-box;
+      /* padding: 50px 80px 20px; */
+      padding: 50px 80px 20px;
+      position: relative;
+
+      .tabs {
+        display: flex;
+        justify-content: space-evenly;
+        font-size: 20px;
+        color: #666666;
+        margin-bottom: 30px;
+
+        .tab {
+          display: flex;
+          flex-direction: column;
+          justify-content: center;
+          align-items: center;
+          cursor: pointer;
+
+          .icon {
+            width: 36px;
+            height: 4px;
+            background: #fff;
+            border-radius: 2px;
+            margin-top: 8px;
+          }
+        }
+
+        .active {
+          font-weight: 500;
+          font-size: 24px;
+          color: #222222;
+
+          .icon {
+            background: #207FF7;
+          }
+        }
+      }
+
+      .df_ac {
+        flex-direction: column;
+        align-items: flex-start;
+      }
+
+      .title {
+        font-size: 24px;
+        margin-top: 70px;
+        margin-bottom: 48px;
+        text-align: center;
+      }
+
+      .label {
+        color: #222222;
+        margin-bottom: 18px;
+        font-size: 14px;
+        margin-right: 12px;
+        width: 42px;
+      }
+
+      &.ey {
+        .label {
+          width: 135px;
+        }
+      }
+
+      .line {
+        margin-bottom: 17px;
+        display: flex;
+        width: 100%;
+        align-items: center;
+        position: relative;
+
+        .el-input {
+          height: 40px;
+          flex: 1;
+
+          // font-size: 14px;
+          ::v-deep .el-input__inner {
+            height: 40px !important;
+          }
+        }
+
+        .code_image {
+          width: 100px;
+          margin-left: 10px;
+        }
+
+        .code_get {
+          position: absolute;
+          top: 10px;
+          right: 10px;
+          font-size: 14px;
+          width: 72px;
+          z-index: 11;
+          margin-left: 10px;
+          cursor: pointer;
+          color: $primary-color;
+          text-align: right;
+        }
+
+        .downtime {
+          color: #999999;
+        }
+      }
+
+      .forget {
+        justify-content: space-between;
+        width: 100%;
+
+        .text {
+          cursor: pointer;
+        }
+      }
+
+      .login_btn {
+        width: 100%;
+        height: 40px;
+        background: $primary-color;
+        box-shadow: 0px 2px 8px 0px rgba(67, 94, 190, 0.15);
+        border-radius: 2px;
+        margin: 0 auto;
+        font-weight: 500;
+        font-size: 16px;
+      }
+
+      .google {
+        position: absolute;
+        left: 50%;
+        transform: translate(-50%, 0);
+        bottom: 20px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        width: 100%;
+        font-size: 12px;
+
+        .img {
+          margin-right: 5px;
+          width: 18px;
+        }
+      }
+
+      .btn_wrap {
+        margin-top: 20px;
+      }
+
+      .agreement {
+        text-align: center;
+      }
+
+      .google {
+        position: absolute;
+        left: 50%;
+        transform: translate(-50%, 0);
+        bottom: 20px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        width: 100%;
+        font-size: 12px;
+
+        .img {
+          margin-right: 5px;
+          width: 18px;
+        }
+      }
     }
   }
+
   // 鍙宠竟鐧诲綍
   .login {
     height: 100%;
@@ -158,40 +483,50 @@
     flex-direction: column;
     justify-content: center;
     box-sizing: border-box;
+
     h1 {
       font-size: 28px;
       font-weight: 500;
     }
+
     .info-input {
       margin-top: $input-gap;
       margin-bottom: 60px;
+
       /deep/ .el-input {
         margin-top: 30px;
+
         .el-input__inner {
           height: 50px;
           background: #F9F9F9;
           border: 1px solid transparent;
+
           &:focus {
             border: 1px solid $primary-color;
           }
         }
       }
     }
+
     // 楠岃瘉鐮佽緭鍏�
     .captcha-input {
       display: flex;
       margin-top: $input-gap;
       height: 50px;
+
       .el-input {
         width: 100%;
         margin-top: 0;
       }
-      span, img {
+
+      span,
+      img {
         width: 45%;
         height: 100%;
         flex-shrink: 0;
         margin-left: 16px;
       }
+
       span {
         display: flex;
         align-items: center;
@@ -200,6 +535,7 @@
         border-radius: 8px;
       }
     }
+
     .el-button {
       height: 50px;
       width: 100%;

--
Gitblit v1.9.3