Files
cz-web/src/views/profile/cpns/ChangePasswordDialog.vue
2026-10-01 17:24:57 +08:00

257 lines
5.5 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 { ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { AppButton, PasswordStrength, SmsCodeInput } from '@/components'
interface Props {
phone: string
}
const props = defineProps<Props>()
const visible = defineModel<boolean>('visible', { default: false })
const emit = defineEmits<{
submit: [payload: { code: string; password: string; confirm: string }]
}>()
const code = ref('')
const password = ref('')
const confirm = ref('')
const agree = ref(false)
watch(visible, (open) => {
if (!open) return
code.value = ''
password.value = ''
confirm.value = ''
agree.value = false
})
function onGetCode(): void {
ElMessage.success('验证码已发送')
}
function onSubmit(): void {
if (!code.value) {
ElMessage.warning('请输入验证码')
return
}
if (!password.value) {
ElMessage.warning('请输入新密码')
return
}
if (!agree.value) {
ElMessage.warning('请先阅读并同意《用户协议》和《隐私政策》')
return
}
emit('submit', {
code: code.value,
password: password.value,
confirm: confirm.value,
})
}
</script>
<template>
<Teleport to="body">
<div v-if="visible" class="change-pwd-dialog" @click.self="visible = false">
<div class="change-pwd-dialog__panel">
<h3 class="change-pwd-dialog__title">
修改密码
</h3>
<div class="change-pwd-dialog__field">
<label class="change-pwd-dialog__label">手机号</label>
<input
class="change-pwd-dialog__input"
type="text"
:value="props.phone"
readonly
>
</div>
<div class="change-pwd-dialog__field">
<label class="change-pwd-dialog__label">验证码</label>
<SmsCodeInput v-model:code="code" @get-code="onGetCode" />
</div>
<div class="change-pwd-dialog__field">
<label class="change-pwd-dialog__label">设置密码</label>
<input
v-model="password"
class="change-pwd-dialog__input"
type="password"
placeholder="请输入密码(6-20位)"
maxlength="20"
>
<PasswordStrength :password="password" />
</div>
<div class="change-pwd-dialog__field">
<label class="change-pwd-dialog__label">确认密码</label>
<input
v-model="confirm"
class="change-pwd-dialog__input"
type="password"
placeholder="请再次输入密码"
maxlength="20"
@keyup.enter="onSubmit"
>
</div>
<label class="change-pwd-dialog__agree">
<input v-model="agree" type="checkbox">
<span>我已阅读并同意<em>《用户协议》</em>和<em>《隐私政策》</em></span>
</label>
<div class="change-pwd-dialog__footer">
<AppButton type="default" @click="visible = false">
取消
</AppButton>
<AppButton type="primary" @click="onSubmit">
确认修改
</AppButton>
</div>
</div>
</div>
</Teleport>
</template>
<style lang="less" scoped>
.change-pwd-dialog {
position: fixed;
inset: 0;
z-index: 1000;
.flex(row, center);
background: transparent;
overflow-y: auto;
&__panel {
width: 700px;
max-width: calc(100vw - 32px);
max-height: calc(100vh - 48px);
overflow-y: auto;
padding: @spacing-base;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-lg;
.flex(column, flex-start);
gap: @spacing-base;
.scrollbar();
}
&__title {
position: relative;
padding-left: 12px;
font-size: 12px;
font-weight: 700;
color: @heading-color;
line-height: 20px;
&::before {
content: '';
position: absolute;
left: 0;
top: 3px;
width: 3px;
height: 14px;
border-radius: 2px;
background: @primary-strong;
}
}
&__field {
.flex(column, flex-start);
gap: @spacing-xs;
width: 100%;
}
&__label {
font-size: 11px;
font-weight: 500;
color: @heading-color;
}
&__input {
width: 100%;
height: 32px;
padding: 0 12px;
border: 1px solid @profile-input-border;
border-radius: @profile-radius;
background: @white;
font-size: 11px;
color: @text-color;
outline: none;
transition: border-color 0.2s;
box-sizing: border-box;
&:focus {
border-color: @primary-strong;
}
&::placeholder {
color: @heading-color;
}
&:read-only {
color: @text-color;
cursor: not-allowed;
}
}
&__agree {
.flex(row, flex-start, center);
gap: @spacing-sm;
font-size: 11px;
color: @text-color-secondary;
cursor: pointer;
input {
accent-color: @primary-strong;
}
em {
font-style: normal;
color: @primary-strong;
}
}
&__footer {
.flex(row, flex-start);
gap: @spacing-sm;
width: 100%;
}
.app-button {
flex: 1;
height: 36px;
font-size: 12px;
font-weight: 500;
border-radius: @profile-radius;
}
.app-button--primary {
border-color: @primary-strong;
background: @primary-strong;
&:hover {
border-color: darken(@primary-strong, 6%);
background: darken(@primary-strong, 6%);
}
}
.app-button--default {
border: none;
background: @profile-quiet-btn;
color: @text-color;
&:hover {
border: none;
background: darken(@profile-quiet-btn, 4%);
color: @text-color;
}
}
}
</style>