Commit c9a8a512 by pangchong

feat: 扫码登录

parent ed32eddf
......@@ -19,6 +19,7 @@
"lodash": "^4.17.21",
"pinia": "^2.1.7",
"pinia-plugin-persistedstate": "^3.2.1",
"qrcode.vue": "^3.4.1",
"qs": "^6.12.1",
"vite-plugin-compression": "^0.5.1",
"vue": "^3.4.19",
......@@ -6065,6 +6066,14 @@
"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": {
"version": "6.12.1",
"resolved": "https://registry.npmmirror.com/qs/-/qs-6.12.1.tgz",
......
......@@ -20,6 +20,7 @@
"lodash": "^4.17.21",
"pinia": "^2.1.7",
"pinia-plugin-persistedstate": "^3.2.1",
"qrcode.vue": "^3.4.1",
"qs": "^6.12.1",
"vite-plugin-compression": "^0.5.1",
"vue": "^3.4.19",
......
......@@ -2,24 +2,31 @@
<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="flex justify-center my-8"><a-image :src="logo" :preview="false" fit="fill" /></div>
<h3 class="font-bold text-xl">登录</h3>
<a-form ref="loginFormRef" :rules="rules" :model="loginForm" layout="vertical">
<a-form-item field="username" label="用户名:" validate-trigger="change" hide-asterisk>
<a-input v-model="loginForm.username" placeholder="请输入你的用户名" size="large" allow-clear />
</a-form-item>
<a-form-item field="password" label="密码:" validate-trigger="change" hide-asterisk>
<a-input-password v-model="loginForm.password" size="large" placeholder="请输入你的密码" allow-clear />
</a-form-item>
<a-form-item field="captcha" label="验证码:" validate-trigger="change" hide-asterisk>
<a-input v-model="loginForm.captcha" placeholder="请输入验证码" size="large" allow-clear />
<div class="w-24 h-9 ml-2 cursor-pointer" @click="getCaptcha">
<a-image width="100%" height="100%" :src="loginCode" :preview="false" fit="fill" v-if="loginCode && loginForm.username"></a-image>
</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 v-show="showScanCode">
<qrcode-vue :value="scanCode" :size="336" render-as="svg" />
<a-button class="shadow-xl my-4" size="large" type="primary" @click="handleBack" long>返回登录</a-button>
</div>
<div v-show="!showScanCode">
<h3 class="font-bold text-xl">{{ getLoginMethod.name }}</h3>
<a-form ref="loginFormRef" :rules="rules" :model="loginForm" layout="vertical">
<a-form-item field="username" label="用户名:" validate-trigger="change" hide-asterisk>
<a-input v-model="loginForm.username" placeholder="请输入你的用户名" size="large" allow-clear />
</a-form-item>
<a-form-item field="password" label="密码:" validate-trigger="change" hide-asterisk>
<a-input-password v-model="loginForm.password" size="large" placeholder="请输入你的密码" allow-clear />
</a-form-item>
<a-form-item field="captcha" label="验证码:" validate-trigger="change" hide-asterisk>
<a-input v-model="loginForm.captcha" placeholder="请输入验证码" size="large" allow-clear />
<div class="w-24 h-9 ml-2 cursor-pointer" @click="getCaptcha">
<a-image width="100%" height="100%" :src="loginCode" :preview="false" fit="fill" v-if="loginCode && loginForm.username"></a-image>
</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>
</template>
......@@ -31,6 +38,7 @@ import { Notification, ValidatedError } from '@arco-design/web-vue'
import { alova } from '@/api/alova-instance'
import { useRequest } from 'alova'
import { debounce } from 'lodash'
import QrcodeVue from 'qrcode.vue'
const loginForm = reactive({
username: '',
......@@ -48,6 +56,35 @@ const rules = {
],
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 userStore = useUserStore()
......@@ -74,12 +111,23 @@ const handleLogin = async () => {
}
})
}
//是否扫码登录
const showScanCode = ref(false)
const scanCode = ref('')
//登录成功
loginSuccess(({ data: res }) => {
if (res.code == 200) {
userStore.setUserInfo(res.data)
Notification.success({
content: '登录成功'
})
//扫码登录
if (loginMethodType.value == 'scan') {
showScanCode.value = true
scanCode.value = res.data.token || ''
} else {
//账号登录
userStore.setUserInfo(res.data)
Notification.success({
content: '登录成功'
})
}
} else {
Notification.error({
content: res.message
......@@ -114,5 +162,8 @@ watch(
}
}, 500)
)
onMounted(() => {
handleBack()
})
</script>
<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