|
- <template>
- <view class="phone-login">
- <view class="title">手机号登录</view>
-
- <view class="field">
- <input v-model="phone" class="input" type="number" placeholder="请输入手机号" maxlength="11" />
- </view>
- <view class="field code">
- <input v-model="code" class="input" type="number" placeholder="请输入验证码" maxlength="6" />
- <view class="code-btn" :class="{ disabled: counting }" @click="sendCode">
- {{ counting ? `${count}s` : '获取验证码' }}
- </view>
- </view>
-
- <button class="btn-primary submit" :loading="postLoading" @click="onLogin">登录</button>
-
- <view class="agreement" @click="agree = !agree">
- <view class="checkbox" :class="{ checked: agree }">{{ agree ? '✓' : '' }}</view>
- <text>登录即代表同意《服务条款》与《隐私政策》</text>
- </view>
- </view>
- </template>
-
- <script setup>
- import { ref } from 'vue'
- import { userApi } from '@/api/index.js'
- import { useUserStore } from '@/store/user.js'
- import { useApp } from '@/utils/useApp.js'
-
- const userStore = useUserStore()
- const { toast } = useApp()
-
- const phone = ref('')
- const code = ref('')
- const agree = ref(false)
- const postLoading = ref(false)
- const counting = ref(false)
- const count = ref(60)
-
- function sendCode() {
- if (counting.value) return
- if (!/^1\d{10}$/.test(phone.value)) return toast('请输入正确的手机号')
- userApi
- .sendCode({ phone: phone.value })
- .then(() => {
- toast('验证码已发送')
- counting.value = true
- count.value = 60
- const timer = setInterval(() => {
- count.value--
- if (count.value <= 0) {
- clearInterval(timer)
- counting.value = false
- }
- }, 1000)
- })
- .catch((e) => toast(e.msg || '发送失败'))
- }
-
- async function onLogin() {
- if (!/^1\d{10}$/.test(phone.value)) return toast('请输入正确的手机号')
- if (!code.value) return toast('请输入验证码')
- if (!agree.value) return toast('请阅读并同意服务政策')
- try {
- postLoading.value = true
- const res = await userApi.loginPhone({ phone: phone.value, code: code.value })
- userStore.setLogin({ token: res.data.token, userInfo: res.data })
- toast('登录成功!')
-
- // #ifdef H5
- const redirect = uni.getStorageSync('login_redirect') || ''
- if (redirect) {
- uni.removeStorageSync('login_redirect')
- setTimeout(() => uni.reLaunch({ url: redirect }), 800)
- return
- }
- // #endif
-
- setTimeout(() => uni.switchTab({ url: '/pages/toolbox/toolbox' }), 800)
- } catch (e) {
- toast(e.msg || '登录失败,请重试!')
- } finally {
- postLoading.value = false
- }
- }
- </script>
-
- <style lang="scss" scoped>
- .phone-login {
- padding: 60rpx;
- }
- .title {
- font-size: 48rpx;
- font-weight: 800;
- margin-bottom: 60rpx;
- }
- .field {
- margin-bottom: 28rpx;
- &.code {
- display: flex;
- align-items: center;
- gap: 20rpx;
- }
- .input {
- flex: 1;
- height: 92rpx;
- padding: 0 28rpx;
- border-radius: 16rpx;
- background: $ai-panel;
- font-size: 30rpx;
- box-shadow: $ai-shadow;
- }
- .code-btn {
- flex-shrink: 0;
- height: 92rpx;
- line-height: 92rpx;
- padding: 0 28rpx;
- border-radius: 16rpx;
- font-size: 26rpx;
- color: $ai-accent;
- background: rgba(11, 140, 255, 0.1);
- &.disabled {
- color: $ai-muted;
- }
- }
- }
- .submit {
- margin-top: 20rpx;
- }
- .agreement {
- margin-top: 40rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 24rpx;
- color: $ai-muted;
-
- .checkbox {
- width: 34rpx;
- height: 34rpx;
- margin-right: 12rpx;
- border-radius: 50%;
- border: 2rpx solid $ai-muted;
- color: #fff;
- font-size: 22rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- &.checked {
- background: $ai-accent;
- border-color: $ai-accent;
- }
- }
- }
- </style>
|