|
@@ -0,0 +1,288 @@
|
|
|
+<template>
|
|
|
+ <Teleport to="body">
|
|
|
+ <div class="login-layer">
|
|
|
+ <div class="login-box">
|
|
|
+ <span class="close" @click="emits('close')"><i class="iconfont icon-close"></i></span>
|
|
|
+ <div class="area">
|
|
|
+ <h4>用户登录</h4>
|
|
|
+ <div class="input">
|
|
|
+ <span class="icon">
|
|
|
+ <i class="iconfont icon-user"></i>
|
|
|
+ </span>
|
|
|
+ <input type="text" v-model.trim="username" />
|
|
|
+ <div class="tips" v-show="errors.username">{{ errors.username }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="input">
|
|
|
+ <span class="icon">
|
|
|
+ <i class="iconfont icon-password"></i>
|
|
|
+ </span>
|
|
|
+ <input :type="showpass ? 'text' : 'password'" v-model.trim="password" />
|
|
|
+ <div class="tips" v-show="errors.password">{{ errors.password }}</div>
|
|
|
+ <span class="showpass" @click="showpass = !showpass">
|
|
|
+ <i class="iconfont" :class="[showpass ? 'icon-log_eye_selected' : 'icon-log_eye_normal']"></i>
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ <div class="remember">
|
|
|
+ <div @click="remember = !remember">
|
|
|
+ <div class="checkbox" :class="{ checked: remember }"></div>
|
|
|
+ <div class="checkbox-label">记住密码</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="button">
|
|
|
+ <button type="submit" @click="onLogin">登录</button>
|
|
|
+ <div class="tips" v-show="errors.message">{{ errors.message }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="links">
|
|
|
+ <a href="http://test.4dkankan.com/#/login/forget?from=%2F">忘记密码</a>
|
|
|
+ <a href="http://test.4dkankan.com/#/login/register?from=%2F">官网注册</a>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </Teleport>
|
|
|
+</template>
|
|
|
+<script setup>
|
|
|
+import { ref, onMounted } from 'vue'
|
|
|
+import { http } from '@/utils/request'
|
|
|
+import common from '@/utils/common'
|
|
|
+const emits = defineEmits(['close','user'])
|
|
|
+const showpass = ref(false)
|
|
|
+const remember = ref(false)
|
|
|
+const username = ref('')
|
|
|
+const password = ref('')
|
|
|
+const errors = ref({})
|
|
|
+const onLogin = () => {
|
|
|
+ errors.value = {}
|
|
|
+ if (!username.value) {
|
|
|
+ errors.value.username = '手机号码不能为空'
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (!/^1[3-9]\d{9}$/.test(username.value)) {
|
|
|
+ errors.value.username = '请输入正确手机号'
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (!password.value) {
|
|
|
+ errors.value.password = '密码不能为空'
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ http.post(`smart-site/fdLogin`, {
|
|
|
+ password: common.encodeStr(Base64.encode(password.value)),
|
|
|
+ phoneNum: username.value,
|
|
|
+ rememberMe: remember.value,
|
|
|
+ randomcode: '1234',
|
|
|
+ })
|
|
|
+ .then(response => {
|
|
|
+ if (response.success) {
|
|
|
+ if (remember.value) {
|
|
|
+ localStorage.setItem('remember', true)
|
|
|
+ localStorage.setItem('username', username.value)
|
|
|
+ localStorage.setItem('password', password.value)
|
|
|
+ } else {
|
|
|
+ localStorage.removeItem('remember')
|
|
|
+ localStorage.removeItem('username')
|
|
|
+ localStorage.removeItem('password')
|
|
|
+ }
|
|
|
+ localStorage.setItem('token',response.data.token)
|
|
|
+ emits('user',response.data.user)
|
|
|
+ } else {
|
|
|
+ errors.value.message = response.message
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ alert('服务器连接失败')
|
|
|
+ })
|
|
|
+}
|
|
|
+onMounted(() => {
|
|
|
+ if (localStorage.getItem('remember')) {
|
|
|
+ remember.value = true
|
|
|
+ username.value = localStorage.getItem('username') || ''
|
|
|
+ password.value = localStorage.getItem('password') || ''
|
|
|
+ }
|
|
|
+})
|
|
|
+</script>
|
|
|
+<style lang="scss" scoped>
|
|
|
+.login-layer {
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ top: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ z-index: 9999;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+.login-box {
|
|
|
+ padding: 0 40px;
|
|
|
+ position: absolute;
|
|
|
+ width: 440px;
|
|
|
+ height: 482px;
|
|
|
+ background: rgba(27, 27, 28, 0.8);
|
|
|
+ box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);
|
|
|
+ border-radius: 4px 4px 4px 4px;
|
|
|
+ opacity: 1;
|
|
|
+ border: 1px solid #000000;
|
|
|
+ backdrop-filter: blur(4px);
|
|
|
+ color: #fff;
|
|
|
+
|
|
|
+ h4 {
|
|
|
+ font-size: 24px;
|
|
|
+ color: #999999;
|
|
|
+ font-weight: 400;
|
|
|
+ padding-bottom: 20px;
|
|
|
+ border-bottom: solid 1px rgba(255, 255, 255, 0.16);
|
|
|
+ margin-top: 60px;
|
|
|
+ margin-bottom: 0px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .close {
|
|
|
+ cursor: pointer;
|
|
|
+ position: absolute;
|
|
|
+ top: 20px;
|
|
|
+ right: 20px;
|
|
|
+ color: rgba(255, 255, 255, 0.8);
|
|
|
+ i {
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .tips {
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ top: 38px;
|
|
|
+ font-size: 12px;
|
|
|
+ color: rgba(250, 85, 85, 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ .input {
|
|
|
+ position: relative;
|
|
|
+ height: 34px;
|
|
|
+ margin-top: 30px;
|
|
|
+ background: rgba(255, 255, 255, 0.1);
|
|
|
+ border-radius: 4px 4px 4px 4px;
|
|
|
+ border: 1px solid rgba(255, 255, 255, 0.2);
|
|
|
+ display: flex;
|
|
|
+ .icon {
|
|
|
+ position: relative;
|
|
|
+ width: 36px;
|
|
|
+ height: 100%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ &::after {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ right: 0;
|
|
|
+ top: 50%;
|
|
|
+ width: 1px;
|
|
|
+ height: 20px;
|
|
|
+ margin-top: -10px;
|
|
|
+ background-color: rgba(255, 255, 255, 0.2);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .showpass {
|
|
|
+ cursor: pointer;
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ right: 10px;
|
|
|
+ transform: translateY(-50%);
|
|
|
+ }
|
|
|
+ input {
|
|
|
+ flex: 1;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ border: none;
|
|
|
+ background: transparent;
|
|
|
+ outline: none;
|
|
|
+ padding: 0 10px;
|
|
|
+ color: #fff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .remember {
|
|
|
+ margin-top: 30px;
|
|
|
+
|
|
|
+ > div {
|
|
|
+ cursor: pointer;
|
|
|
+ display: inline-block;
|
|
|
+ position: relative;
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .checkbox {
|
|
|
+ display: inline-block;
|
|
|
+ position: relative;
|
|
|
+ width: 16px;
|
|
|
+ height: 16px;
|
|
|
+ margin-right: 5px;
|
|
|
+ &::before {
|
|
|
+ content: '';
|
|
|
+ border: 1px solid #0076f6;
|
|
|
+ border-radius: 2px;
|
|
|
+ width: 16px;
|
|
|
+ height: 16px;
|
|
|
+ position: absolute;
|
|
|
+ left: 0px;
|
|
|
+ top: 0;
|
|
|
+ display: inline-block;
|
|
|
+ }
|
|
|
+ &.checked {
|
|
|
+ &::after {
|
|
|
+ left: 4px;
|
|
|
+ top: 7px;
|
|
|
+ position: absolute;
|
|
|
+ display: table;
|
|
|
+ border: 2px solid #0076f6;
|
|
|
+ border-top: 0;
|
|
|
+ border-left: 0;
|
|
|
+ transform: rotate(45deg) translate(-50%, -50%);
|
|
|
+ opacity: 1;
|
|
|
+ transition: all 0.2s cubic-bezier(0.12, 0.4, 0.29, 1.46) 0.1s;
|
|
|
+ width: 6px;
|
|
|
+ height: 8px;
|
|
|
+ content: ' ';
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .checkbox-label {
|
|
|
+ display: inline-block;
|
|
|
+ vertical-align: 3px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .button {
|
|
|
+ position: relative;
|
|
|
+ margin-top: 40px;
|
|
|
+ button {
|
|
|
+ cursor: pointer;
|
|
|
+ color: #fff;
|
|
|
+ width: 100%;
|
|
|
+ height: 34px;
|
|
|
+ background: #0076f6;
|
|
|
+ border-radius: 2px;
|
|
|
+ border: none;
|
|
|
+ outline: none;
|
|
|
+ }
|
|
|
+ .tips {
|
|
|
+ text-align: center;
|
|
|
+ top: 40px;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .links {
|
|
|
+ margin-top: 40px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ a {
|
|
|
+ color: #0076f6;
|
|
|
+ text-decoration: none;
|
|
|
+ &:hover {
|
|
|
+ text-decoration: underline;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|