Commit c1952428 by 孙美琪

手机号登录

parent e587586e
...@@ -45,3 +45,25 @@ export function logout() { ...@@ -45,3 +45,25 @@ export function logout() {
method: 'post' method: 'post'
}) })
} }
// 发送验证码
export function sendCode(data) {
return request({
url: '/member/auth/send-sms-code',
method: 'post',
data: data
})
}
// 验证码提交
export function submitCode(data) {
return request({
url: '/member/auth/sms-login',
headers: {
isToken: false,
repeatSubmit: false
},
method: 'post',
data: data
})
}
import { login, logout, getInfo } from '@/api/login' import {login, logout, getInfo, submitCode} from '@/api/login'
import { getToken, setToken, removeToken } from '@/utils/auth' import { getToken, setToken, removeToken } from '@/utils/auth'
import defAva from '@/assets/images/profile.jpg' import defAva from '@/assets/images/profile.jpg'
...@@ -20,7 +20,6 @@ const useUserStore = defineStore( ...@@ -20,7 +20,6 @@ const useUserStore = defineStore(
const password = userInfo.password const password = userInfo.password
const code = userInfo.code const code = userInfo.code
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
login(mobile, password, code).then(res => { login(mobile, password, code).then(res => {
setToken(res.data.accessToken) setToken(res.data.accessToken)
...@@ -31,6 +30,19 @@ const useUserStore = defineStore( ...@@ -31,6 +30,19 @@ const useUserStore = defineStore(
}) })
}) })
}, },
cellPhoneLogin(userInfo) {
const mobile = userInfo.mobile.trim()
const code = userInfo.code
return new Promise((resolve, reject) => {
submitCode({mobile:mobile, code:code}).then(res => {
setToken(res.data.accessToken)
this.token = res.data.accessToken
resolve()
}).catch(error => {
reject(error)
})
})
},
// 获取用户信息 // 获取用户信息
getInfo() { getInfo() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
......
...@@ -2,34 +2,69 @@ ...@@ -2,34 +2,69 @@
<div class="login"> <div class="login">
<el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form"> <el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form">
<h3 class="title">面向科创园区的普惠算力公共服务平台</h3> <h3 class="title">面向科创园区的普惠算力公共服务平台</h3>
<el-form-item prop="mobile"> <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
<el-input <el-tab-pane label="手机号登录" :name="0" style="padding-top: 10px;">
v-model="loginForm.mobile" <el-form-item prop="phoneNumber">
type="text" <el-input
size="large" v-model="loginForm.phoneNumber"
auto-complete="off" type="text"
placeholder="账号"> size="large"
<template #prefix> auto-complete="off"
<svg-icon icon-class="user" class="el-input__icon input-icon"/> placeholder="手机号">
</template> <template #prefix>
</el-input> <svg-icon icon-class="phone" class="el-input__icon input-icon"/>
</el-form-item> </template>
<el-form-item prop="password"> </el-input>
<el-input </el-form-item>
v-model="loginForm.password" <el-form-item prop="code">
type="password" <el-input
size="large" v-model="loginForm.code"
auto-complete="off" type="text"
placeholder="密码" size="large"
@keyup.enter="handleLogin"> auto-complete="off"
<template #prefix> placeholder="验证码">
<svg-icon icon-class="password" class="el-input__icon input-icon"/> <template #prefix>
</template> <svg-icon icon-class="code" class="el-input__icon input-icon"/>
</el-input> </template>
</el-form-item> <template #append>
<el-button @click="startCountdown" :disabled="isCounting">
{{ isCounting ? `重新发送(${countdown})` : '发送验证码' }}
</el-button>
</template>
</el-input>
</el-form-item>
</el-tab-pane>
<el-tab-pane label="账号登录" :name="1" style="padding-top: 10px;">
<el-form-item prop="mobile">
<el-input
v-model="loginForm.mobile"
type="text"
size="large"
auto-complete="off"
placeholder="账号">
<template #prefix>
<svg-icon icon-class="user" class="el-input__icon input-icon"/>
</template>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="loginForm.password"
type="password"
size="large"
auto-complete="off"
placeholder="密码"
@keyup.enter="handleLogin">
<template #prefix>
<svg-icon icon-class="password" class="el-input__icon input-icon"/>
</template>
</el-input>
</el-form-item>
</el-tab-pane>
</el-tabs>
<div class="flex-align-center flex-space-between mb20"> <div class="flex-align-center flex-space-between mb20" style="height: 32px;">
<el-checkbox v-model="loginForm.rememberMe">记住密码</el-checkbox> <el-checkbox v-show="activeName === 1" v-model="loginForm.rememberMe">记住密码</el-checkbox>
<div v-if="register"> <div v-if="register">
<router-link class="link-type" :to="'/register'">立即注册</router-link> <router-link class="link-type" :to="'/register'">立即注册</router-link>
</div> </div>
...@@ -41,7 +76,7 @@ ...@@ -41,7 +76,7 @@
size="large" size="large"
type="primary" type="primary"
style="width:100%;" style="width:100%;"
@click.prevent="handleLogin"> @click.prevent="handleLogin(activeName)">
<span v-if="!loading"> </span> <span v-if="!loading"> </span>
<span v-else> ...</span> <span v-else> ...</span>
</el-button> </el-button>
...@@ -57,9 +92,11 @@ ...@@ -57,9 +92,11 @@
<script setup> <script setup>
import Cookies from 'js-cookie' import Cookies from 'js-cookie'
import { encrypt, decrypt } from '@/utils/jsencrypt' import {encrypt, decrypt} from '@/utils/jsencrypt'
import useUserStore from '@/store/modules/user' import useUserStore from '@/store/modules/user'
import { useRoute, useRouter } from 'vue-router' import {useRoute, useRouter} from 'vue-router'
import {sendCode} from "@/api/login.js";
import {ElMessage} from "element-plus";
const userStore = useUserStore() const userStore = useUserStore()
const route = useRoute() const route = useRoute()
...@@ -71,61 +108,125 @@ const loginForm = ref({ ...@@ -71,61 +108,125 @@ const loginForm = ref({
password: '', password: '',
rememberMe: false, rememberMe: false,
code: '', code: '',
uuid: '' uuid: '',
phoneNumber: ''
}) })
const loginRules = { const loginRules = {
mobile: [{required: true, trigger: 'blur', message: '请输入您的手机号'}], mobile: [{required: true, trigger: 'blur', message: '请输入您的手机号'}],
password: [{required: true, trigger: 'blur', message: '请输入您的密码'}], password: [{required: true, trigger: 'blur', message: '请输入您的密码'}],
code: [{required: true, trigger: 'change', message: '请输入验证码'}] code: [{required: true, trigger: 'change', message: '请输入验证码'}],
phoneNumber: [
{required: true, trigger: 'blur', message: '请输入手机号码'},
{validator: validatePhone},
]
} }
const codeUrl = ref('') const loginRef = ref(null)
const activeName = ref(0)
const loading = ref(false) const loading = ref(false)
// 验证码开关 // 验证码开关
const captchaEnabled = ref(true) const captchaEnabled = ref(false)
// 注册开关 // 注册开关
const register = ref(true) const register = ref(false)
const redirect = ref(undefined) const redirect = ref(undefined)
const countdown = ref(60); // 倒计时时间,初始为60秒
const isCounting = ref(false); // 是否正在倒计时的标志
// 开始倒计时的方法
const startCountdown = () => {
getCode()
loginRef.value.validateField('phoneNumber', valid => {
if (valid) {
if (isCounting.value) return; // 如果已经在倒计时,则不重复开始
isCounting.value = true; // 设置正在倒计时的标志为true
const timer = setInterval(() => {
if (countdown.value > 0) {
countdown.value--; // 倒计时减1
} else {
clearInterval(timer); // 倒计时结束,清除定时器
isCounting.value = false; // 设置正在倒计时的标志为false
countdown.value = 60; // 重置倒计时时间
}
}, 1000); // 每1000毫秒(1秒)执行一次
}
})
};
function getCode() {
sendCode({mobile: loginForm.value.mobile, scene: 1}).then(res => {
if (res.data === true) {
ElMessage({message: '短信已发送请注意查收', type: 'success'})
}
})
}
function validatePhone(rule, value, callback) {
const reg = /^1[3456789]\d{9}$/
if (!reg.test(value)) {
callback(new Error('请输入正确的手机号'))
return
}
callback()
}
watch(route, (newRoute) => { watch(route, (newRoute) => {
redirect.value = newRoute.query && newRoute.query.redirect redirect.value = newRoute.query && newRoute.query.redirect
}, {immediate: true}) }, {immediate: true})
function handleLogin () { function handleClick() {
proxy.$refs.loginRef.resetFields()
}
function handleLogin(num) {
proxy.$refs.loginRef.validate(valid => { proxy.$refs.loginRef.validate(valid => {
if (valid) { if (valid) {
loading.value = true loading.value = true
// 勾选了需要记住密码设置在 cookie 中设置记住用户名和密码 if (num === 1) {
if (loginForm.value.rememberMe) { // 勾选了需要记住密码设置在 cookie 中设置记住用户名和密码
Cookies.set('mobile', loginForm.value.mobile, {expires: 30}) if (loginForm.value.rememberMe) {
Cookies.set('password', encrypt(loginForm.value.password), {expires: 30}) Cookies.set('mobile', loginForm.value.mobile, {expires: 30})
Cookies.set('rememberMe', loginForm.value.rememberMe, {expires: 30}) Cookies.set('password', encrypt(loginForm.value.password), {expires: 30})
Cookies.set('rememberMe', loginForm.value.rememberMe, {expires: 30})
} else {
// 否则移除
Cookies.remove('mobile')
Cookies.remove('password')
Cookies.remove('rememberMe')
}
// 调用action的登录方法
userStore.login(loginForm.value).then(() => {
const query = route.query
const otherQueryParams = Object.keys(query).reduce((acc, cur) => {
if (cur !== 'redirect') {
acc[cur] = query[cur]
}
return acc
}, {})
router.push({path: redirect.value || '/', query: otherQueryParams})
}).catch(() => {
loading.value = false
})
} else { } else {
// 否则移除 userStore.cellPhoneLogin({mobile: loginForm.value.phoneNumber, code: loginForm.value.code}).then(res => {
Cookies.remove('mobile') const query = route.query
Cookies.remove('password') const otherQueryParams = Object.keys(query).reduce((acc, cur) => {
Cookies.remove('rememberMe') if (cur !== 'redirect') {
acc[cur] = query[cur]
}
return acc
}, {})
router.push({path: redirect.value || '/', query: otherQueryParams})
}).catch(() => {
loading.value = false
})
} }
// 调用action的登录方法
userStore.login(loginForm.value).then(() => {
const query = route.query
const otherQueryParams = Object.keys(query).reduce((acc, cur) => {
if (cur !== 'redirect') {
acc[cur] = query[cur]
}
return acc
}, {})
router.push({path: redirect.value || '/', query: otherQueryParams})
}).catch(() => {
loading.value = false
})
} }
}) })
} }
function getCookie () { function getCookie() {
const mobile = Cookies.get('mobile') const mobile = Cookies.get('mobile')
const password = Cookies.get('password') const password = Cookies.get('password')
const rememberMe = Cookies.get('rememberMe') const rememberMe = Cookies.get('rememberMe')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment