299 lines
6.2 KiB
Vue
299 lines
6.2 KiB
Vue
<template>
|
||
<view class="page">
|
||
<view class="hero-card">
|
||
<view class="hero-title">进入智慧团委小程序</view>
|
||
<view class="hero-desc">支持手机号密码登录,也支持微信手机号授权登录。</view>
|
||
</view>
|
||
|
||
<view class="login-card">
|
||
<view class="tab-row">
|
||
<view
|
||
class="tab-item"
|
||
:class="{ 'tab-item--active': loginMode === 'password' }"
|
||
@tap="loginMode = 'password'"
|
||
>
|
||
手机号密码登录
|
||
</view>
|
||
<view
|
||
class="tab-item"
|
||
:class="{ 'tab-item--active': loginMode === 'wechat' }"
|
||
@tap="loginMode = 'wechat'"
|
||
>
|
||
微信授权登录
|
||
</view>
|
||
</view>
|
||
|
||
<view v-if="loginMode === 'password'" class="form-section">
|
||
<uv-input
|
||
v-model.trim="form.username"
|
||
class="field-input"
|
||
type="text"
|
||
placeholder="请输入手机号或账号"
|
||
:maxlength="-1"
|
||
border="none"
|
||
/>
|
||
<uv-input
|
||
v-model="form.password"
|
||
class="field-input"
|
||
type="password"
|
||
placeholder="请输入密码"
|
||
:maxlength="-1"
|
||
border="none"
|
||
password
|
||
/>
|
||
<view class="submit-btn" :class="{ 'submit-btn--loading': loading }" @tap="submitPasswordLogin">
|
||
{{ loading ? '登录中...' : '立即登录' }}
|
||
</view>
|
||
</view>
|
||
|
||
<view v-else class="form-section">
|
||
<view class="wechat-intro">授权后将使用微信手机号完成登录。</view>
|
||
<button
|
||
class="submit-btn submit-btn--wechat"
|
||
:disabled="loading"
|
||
open-type="getPhoneNumber"
|
||
@getphonenumber="handleWxPhoneLogin"
|
||
>
|
||
{{ loading ? '登录中...' : '微信授权登录' }}
|
||
</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { loginByMpWxPhone, loginByPassword } from './service'
|
||
import { hasToken, setAuthInfo } from '../../utils/request'
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
loginMode: 'password',
|
||
loading: false,
|
||
redirect: '',
|
||
wxCode: '',
|
||
form: {
|
||
username: '',
|
||
password: ''
|
||
}
|
||
}
|
||
},
|
||
onLoad(options) {
|
||
this.redirect = decodeURIComponent((options && options.redirect) || '')
|
||
},
|
||
onShow() {
|
||
if (hasToken()) {
|
||
this.navigateAfterLogin()
|
||
return
|
||
}
|
||
this.refreshWxCode()
|
||
},
|
||
methods: {
|
||
showToast(title) {
|
||
uni.showToast({
|
||
title,
|
||
icon: 'none'
|
||
})
|
||
},
|
||
refreshWxCode() {
|
||
uni.login({
|
||
success: (res) => {
|
||
this.wxCode = (res && res.code) || ''
|
||
}
|
||
})
|
||
},
|
||
navigateAfterLogin() {
|
||
const url = this.redirect || '/pages/index/index'
|
||
uni.reLaunch({
|
||
url
|
||
})
|
||
},
|
||
async submitPasswordLogin() {
|
||
if (this.loading) {
|
||
return
|
||
}
|
||
if (!this.form.username) {
|
||
this.showToast('请输入手机号或账号')
|
||
return
|
||
}
|
||
if (!this.form.password) {
|
||
this.showToast('请输入密码')
|
||
return
|
||
}
|
||
this.loading = true
|
||
try {
|
||
const result = await loginByPassword({
|
||
username: this.form.username,
|
||
password: this.form.password
|
||
})
|
||
setAuthInfo(result)
|
||
this.showToast('登录成功')
|
||
setTimeout(() => {
|
||
this.navigateAfterLogin()
|
||
}, 300)
|
||
} catch (error) {
|
||
this.showToast((error && error.message) || '登录失败')
|
||
} finally {
|
||
this.loading = false
|
||
}
|
||
},
|
||
async handleWxPhoneLogin(event) {
|
||
if (this.loading) {
|
||
return
|
||
}
|
||
const detail = (event && event.detail) || {}
|
||
if (!detail.code) {
|
||
this.showToast(detail.errMsg || '未获取到微信手机号凭证')
|
||
return
|
||
}
|
||
this.loading = true
|
||
try {
|
||
if (!this.wxCode) {
|
||
await new Promise((resolve) => {
|
||
uni.login({
|
||
success: (res) => {
|
||
this.wxCode = (res && res.code) || ''
|
||
resolve()
|
||
},
|
||
fail: () => resolve()
|
||
})
|
||
})
|
||
}
|
||
const result = await loginByMpWxPhone({
|
||
phoneCode: detail.code,
|
||
code: this.wxCode || undefined
|
||
})
|
||
setAuthInfo(result)
|
||
this.showToast('登录成功')
|
||
setTimeout(() => {
|
||
this.navigateAfterLogin()
|
||
}, 300)
|
||
} catch (error) {
|
||
this.showToast((error && error.message) || '微信登录失败')
|
||
this.refreshWxCode()
|
||
} finally {
|
||
this.loading = false
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.page {
|
||
min-height: 100vh;
|
||
padding: 28rpx 24rpx 40rpx;
|
||
background:
|
||
radial-gradient(circle at top left, rgba(20, 150, 242, 0.14), transparent 30%),
|
||
linear-gradient(180deg, #f5fbff 0%, #eef7ff 100%);
|
||
}
|
||
|
||
.hero-card,
|
||
.login-card {
|
||
border-radius: 32rpx;
|
||
box-shadow: 0 18rpx 40rpx rgba(20, 118, 194, 0.12);
|
||
}
|
||
|
||
.hero-card {
|
||
padding: 34rpx 30rpx;
|
||
background: linear-gradient(145deg, #0d6fba 0%, #1496f2 58%, #5bc2ff 100%);
|
||
color: #fff;
|
||
}
|
||
|
||
.hero-badge {
|
||
display: inline-flex;
|
||
padding: 10rpx 18rpx;
|
||
border-radius: 999rpx;
|
||
background: rgba(255, 255, 255, 0.16);
|
||
font-size: 22rpx;
|
||
}
|
||
|
||
.hero-title {
|
||
margin-top: 22rpx;
|
||
font-size: 42rpx;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.hero-desc {
|
||
margin-top: 14rpx;
|
||
font-size: 24rpx;
|
||
line-height: 1.7;
|
||
color: rgba(255, 255, 255, 0.86);
|
||
}
|
||
|
||
.login-card {
|
||
margin-top: 24rpx;
|
||
padding: 28rpx 24rpx;
|
||
background: rgba(255, 255, 255, 0.94);
|
||
}
|
||
|
||
.tab-row {
|
||
display: grid;
|
||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||
gap: 14rpx;
|
||
}
|
||
|
||
.tab-item {
|
||
height: 82rpx;
|
||
border-radius: 22rpx;
|
||
background: #edf5ff;
|
||
color: #1496f2;
|
||
font-size: 24rpx;
|
||
font-weight: 600;
|
||
line-height: 82rpx;
|
||
text-align: center;
|
||
}
|
||
|
||
.tab-item--active {
|
||
background: linear-gradient(135deg, #1496f2, #0d6fba);
|
||
color: #fff;
|
||
}
|
||
|
||
.form-section {
|
||
margin-top: 22rpx;
|
||
}
|
||
|
||
:deep(.field-input.uv-input) {
|
||
width: 100%;
|
||
height: 88rpx;
|
||
margin-top: 16rpx;
|
||
padding: 0 24rpx !important;
|
||
border-radius: 24rpx;
|
||
background: #f8fbff !important;
|
||
border: 1rpx solid rgba(20, 150, 242, 0.12) !important;
|
||
}
|
||
|
||
:deep(.field-input.uv-input .uv-input__content__field-wrapper__field) {
|
||
font-size: 24rpx;
|
||
color: #1f2329;
|
||
}
|
||
|
||
.wechat-intro {
|
||
font-size: 24rpx;
|
||
line-height: 1.7;
|
||
color: #667085;
|
||
}
|
||
|
||
.submit-btn {
|
||
width: 100%;
|
||
height: 88rpx;
|
||
margin-top: 22rpx;
|
||
border: none;
|
||
border-radius: 24rpx;
|
||
background: linear-gradient(135deg, #1496f2, #0d6fba);
|
||
color: #fff;
|
||
font-size: 26rpx;
|
||
font-weight: 700;
|
||
line-height: 88rpx;
|
||
text-align: center;
|
||
}
|
||
|
||
.submit-btn--wechat {
|
||
background: linear-gradient(135deg, #1dbf73, #12a150);
|
||
}
|
||
|
||
.submit-btn--loading {
|
||
opacity: 0.72;
|
||
}
|
||
</style>
|