Files
cz-web/src/views/profile/bind-phone.vue
2026-10-10 09:57:56 +08:00

236 lines
5.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { computed, ref } from 'vue'
import { useRouter } from 'vue-router'
import { storeToRefs } from 'pinia'
import { ElMessage } from 'element-plus'
import { useProfileStore } from '@/stores/modules/profile'
import { useCountDown } from '@/composables/useCountDown'
const router = useRouter()
const profileStore = useProfileStore()
const { profile } = storeToRefs(profileStore)
const hasPhone = computed(() => Boolean(profile.value?.phone))
const phone = ref('')
const code = ref('')
const { seconds, isCounting, start } = useCountDown(60)
function onGetCode(): void {
const target = hasPhone.value ? profile.value?.phone : phone.value
if (!target) {
ElMessage.warning('请输入手机号')
return
}
start(60)
ElMessage.success('验证码已发送')
}
function onSubmit(): void {
const target = hasPhone.value ? profile.value?.phone : phone.value
if (!target) {
ElMessage.warning('请输入手机号')
return
}
if (!code.value) {
ElMessage.warning('请输入验证码')
return
}
void profileStore.bindPhone(target, code.value).then(() => {
void router.push('/profile/security')
})
}
</script>
<template>
<div class="bind-phone-page">
<h2 class="bind-phone-page__title">
绑定手机号
</h2>
<form class="bind-phone-page__form" @submit.prevent="onSubmit">
<div class="bind-phone-page__field">
<label class="bind-phone-page__label">手机号</label>
<input
v-if="hasPhone"
class="bind-phone-page__input bind-phone-page__input--disabled"
type="text"
:value="profile?.phone ?? ''"
readonly
>
<input
v-else
v-model="phone"
class="bind-phone-page__input"
type="text"
placeholder="请输入手机号"
maxlength="20"
>
</div>
<div class="bind-phone-page__field">
<label class="bind-phone-page__label">验证码</label>
<div class="bind-phone-page__code">
<input
v-model="code"
class="bind-phone-page__input"
type="text"
placeholder="请输入验证码"
maxlength="6"
>
<button
type="button"
class="bind-phone-page__get-code"
:disabled="isCounting"
@click="onGetCode"
>
{{ isCounting ? `${seconds}秒后重获` : '获取验证码' }}
</button>
</div>
<p class="bind-phone-page__hint">
注:更换新手机号之后,可以用新的手机号充当当前账号登录
</p>
</div>
<button type="submit" class="bind-phone-page__submit">
{{ hasPhone ? '验证并换绑' : '验证并绑定' }}
</button>
</form>
</div>
</template>
<style lang="less" scoped>
.bind-phone-page {
.flex(column, flex-start, stretch);
&__title {
position: relative;
padding-left: 14px;
margin-bottom: 24px;
font-size: @font-size-base;
font-weight: 600;
color: @profile-ink;
line-height: 20px;
&::before {
content: '';
position: absolute;
left: 0;
top: 3px;
width: 4px;
height: 14px;
border-radius: 2px;
background: @primary-strong;
}
}
&__form {
width: 860px;
max-width: 100%;
}
&__field {
.flex(column, flex-start);
margin-bottom: 20px;
}
&__label {
margin-bottom: 12px;
font-size: @font-size-sm;
font-weight: 500;
color: @profile-ink;
line-height: 14px;
}
&__input {
width: 100%;
height: 38px;
padding: 0 14px;
border: 1px solid @profile-input-border;
border-radius: @profile-radius;
background: @white;
font-size: 13px;
color: @profile-ink;
outline: none;
transition: border-color 0.2s;
box-sizing: border-box;
&:focus {
border-color: @primary-strong;
}
&::placeholder {
color: @finance-axis-text;
}
&--disabled {
border-color: transparent;
background: @profile-input-disabled-bg;
color: @finance-muted-text;
cursor: not-allowed;
}
}
&__code {
position: relative;
width: 100%;
.bind-phone-page__input {
padding-right: 124px;
}
}
&__get-code {
position: absolute;
top: 0;
right: 0;
width: 107px;
height: 38px;
border: 1px solid @primary-strong;
border-radius: @profile-radius;
background: @white;
color: @primary-strong;
font-size: 13px;
cursor: pointer;
transition: all 0.2s;
&:hover:not(:disabled) {
background: @primary-strong;
color: @white;
}
&:disabled {
border-color: @text-color-disabled;
color: @text-color-disabled;
cursor: not-allowed;
}
}
&__hint {
margin-top: 8px;
font-size: @font-size-sm;
color: @finance-axis-text;
line-height: 16px;
}
&__submit {
width: 100%;
height: 46px;
margin-top: 2px;
border: none;
border-radius: @profile-radius;
background: @primary-strong;
color: @white;
font-size: @font-size-base;
font-weight: 500;
cursor: pointer;
transition: background 0.2s;
&:hover {
background: darken(@primary-strong, 6%);
}
}
}
</style>