Commit c9a8a512 by pangchong

feat: 扫码登录

parent ed32eddf
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
"lodash": "^4.17.21", "lodash": "^4.17.21",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"pinia-plugin-persistedstate": "^3.2.1", "pinia-plugin-persistedstate": "^3.2.1",
"qrcode.vue": "^3.4.1",
"qs": "^6.12.1", "qs": "^6.12.1",
"vite-plugin-compression": "^0.5.1", "vite-plugin-compression": "^0.5.1",
"vue": "^3.4.19", "vue": "^3.4.19",
...@@ -6065,6 +6066,14 @@ ...@@ -6065,6 +6066,14 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/qrcode.vue": {
"version": "3.4.1",
"resolved": "https://registry.npmmirror.com/qrcode.vue/-/qrcode.vue-3.4.1.tgz",
"integrity": "sha512-wq/zHsifH4FJ1GXQi8/wNxD1KfQkckIpjK1KPTc/qwYU5/Bkd4me0w4xZSg6EXk6xLBkVDE0zxVagewv5EMAVA==",
"peerDependencies": {
"vue": "^3.0.0"
}
},
"node_modules/qs": { "node_modules/qs": {
"version": "6.12.1", "version": "6.12.1",
"resolved": "https://registry.npmmirror.com/qs/-/qs-6.12.1.tgz", "resolved": "https://registry.npmmirror.com/qs/-/qs-6.12.1.tgz",
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
"lodash": "^4.17.21", "lodash": "^4.17.21",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"pinia-plugin-persistedstate": "^3.2.1", "pinia-plugin-persistedstate": "^3.2.1",
"qrcode.vue": "^3.4.1",
"qs": "^6.12.1", "qs": "^6.12.1",
"vite-plugin-compression": "^0.5.1", "vite-plugin-compression": "^0.5.1",
"vue": "^3.4.19", "vue": "^3.4.19",
......
...@@ -2,24 +2,31 @@ ...@@ -2,24 +2,31 @@
<div class="w-full h-full flex justify-center items-center bg-primary"> <div class="w-full h-full flex justify-center items-center bg-primary">
<div class="w-[400px] py-4 px-8 bg-white shadow-xl rounded-3xl" @keyup.enter="handleLogin"> <div class="w-[400px] py-4 px-8 bg-white shadow-xl rounded-3xl" @keyup.enter="handleLogin">
<div class="flex justify-center my-8"><a-image :src="logo" :preview="false" fit="fill" /></div> <div class="flex justify-center my-8"><a-image :src="logo" :preview="false" fit="fill" /></div>
<h3 class="font-bold text-xl">登录</h3> <div v-show="showScanCode">
<a-form ref="loginFormRef" :rules="rules" :model="loginForm" layout="vertical"> <qrcode-vue :value="scanCode" :size="336" render-as="svg" />
<a-form-item field="username" label="用户名:" validate-trigger="change" hide-asterisk> <a-button class="shadow-xl my-4" size="large" type="primary" @click="handleBack" long>返回登录</a-button>
<a-input v-model="loginForm.username" placeholder="请输入你的用户名" size="large" allow-clear /> </div>
</a-form-item> <div v-show="!showScanCode">
<a-form-item field="password" label="密码:" validate-trigger="change" hide-asterisk> <h3 class="font-bold text-xl">{{ getLoginMethod.name }}</h3>
<a-input-password v-model="loginForm.password" size="large" placeholder="请输入你的密码" allow-clear /> <a-form ref="loginFormRef" :rules="rules" :model="loginForm" layout="vertical">
</a-form-item> <a-form-item field="username" label="用户名:" validate-trigger="change" hide-asterisk>
<a-form-item field="captcha" label="验证码:" validate-trigger="change" hide-asterisk> <a-input v-model="loginForm.username" placeholder="请输入你的用户名" size="large" allow-clear />
<a-input v-model="loginForm.captcha" placeholder="请输入验证码" size="large" allow-clear /> </a-form-item>
<div class="w-24 h-9 ml-2 cursor-pointer" @click="getCaptcha"> <a-form-item field="password" label="密码:" validate-trigger="change" hide-asterisk>
<a-image width="100%" height="100%" :src="loginCode" :preview="false" fit="fill" v-if="loginCode && loginForm.username"></a-image> <a-input-password v-model="loginForm.password" size="large" placeholder="请输入你的密码" allow-clear />
</div> </a-form-item>
</a-form-item> <a-form-item field="captcha" label="验证码:" validate-trigger="change" hide-asterisk>
<a-form-item> <a-input v-model="loginForm.captcha" placeholder="请输入验证码" size="large" allow-clear />
<a-button class="shadow-xl" size="large" type="primary" @click="handleLogin" long :loading="loading">登录</a-button> <div class="w-24 h-9 ml-2 cursor-pointer" @click="getCaptcha">
</a-form-item> <a-image width="100%" height="100%" :src="loginCode" :preview="false" fit="fill" v-if="loginCode && loginForm.username"></a-image>
</a-form> </div>
</a-form-item>
<a-form-item>
<a-button class="shadow-xl" size="large" type="primary" @click="handleLogin" long :loading="loading">登录</a-button>
</a-form-item>
</a-form>
<div class="m-4 text-center cursor-pointer underline text-xs" style="color: rgb(32, 128, 240)" @click="handleLoginMethod">{{ getLoginMethod.btnText }}</div>
</div>
</div> </div>
</div> </div>
</template> </template>
...@@ -31,6 +38,7 @@ import { Notification, ValidatedError } from '@arco-design/web-vue' ...@@ -31,6 +38,7 @@ import { Notification, ValidatedError } from '@arco-design/web-vue'
import { alova } from '@/api/alova-instance' import { alova } from '@/api/alova-instance'
import { useRequest } from 'alova' import { useRequest } from 'alova'
import { debounce } from 'lodash' import { debounce } from 'lodash'
import QrcodeVue from 'qrcode.vue'
const loginForm = reactive({ const loginForm = reactive({
username: '', username: '',
...@@ -48,6 +56,35 @@ const rules = { ...@@ -48,6 +56,35 @@ const rules = {
], ],
captcha: [{ required: true, message: '请输入验证码' }] captcha: [{ required: true, message: '请输入验证码' }]
} }
// 登录模式
type MethodType = 'account' | 'scan'
interface loginMethodItem {
name: string
btnText: string
}
const loginMethod = reactive<{ [key in MethodType]: loginMethodItem }>({
account: { name: '登录', btnText: '眼镜端登录' },
scan: { name: '眼镜端登录', btnText: '返回PC登录' }
})
const loginMethodType = ref<MethodType>('account')
//获取当前登录模式
const getLoginMethod = computed(() => {
return loginMethod[loginMethodType.value]
})
//切换登录模式
const handleLoginMethod = () => {
if (loginMethodType.value == 'account') {
loginMethodType.value = 'scan'
} else {
loginMethodType.value = 'account'
}
getCaptcha()
}
//返回登录
const handleBack = () => {
showScanCode.value = false
scanCode.value = ''
}
//登录 //登录
const loginFormRef = ref() const loginFormRef = ref()
const userStore = useUserStore() const userStore = useUserStore()
...@@ -74,12 +111,23 @@ const handleLogin = async () => { ...@@ -74,12 +111,23 @@ const handleLogin = async () => {
} }
}) })
} }
//是否扫码登录
const showScanCode = ref(false)
const scanCode = ref('')
//登录成功
loginSuccess(({ data: res }) => { loginSuccess(({ data: res }) => {
if (res.code == 200) { if (res.code == 200) {
userStore.setUserInfo(res.data) //扫码登录
Notification.success({ if (loginMethodType.value == 'scan') {
content: '登录成功' showScanCode.value = true
}) scanCode.value = res.data.token || ''
} else {
//账号登录
userStore.setUserInfo(res.data)
Notification.success({
content: '登录成功'
})
}
} else { } else {
Notification.error({ Notification.error({
content: res.message content: res.message
...@@ -114,5 +162,8 @@ watch( ...@@ -114,5 +162,8 @@ watch(
} }
}, 500) }, 500)
) )
onMounted(() => {
handleBack()
})
</script> </script>
<style lang="less" scoped></style> <style lang="less" scoped></style>
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 to comment