Stepper 3 步引导:账号(含 PasswordStrength)→ 个人(含 PhoneInput)→ 协议同意。每步有进入前置校验。
<script setup lang="ts">
import { computed, ref } from 'vue';
import {
CfCard,
CfStepper,
CfInput,
CfButton,
CfPasswordStrength,
CfPhoneInput,
CfCheckbox,
} from '@chufix-design/vue';
const steps = [
{ id: 'account', title: '账号' },
{ id: 'profile', title: '个人' },
{ id: 'verify', title: '验证' },
];
const current = ref(0);
const email = ref('');
const password = ref('');
const name = ref('');
const phone = ref('');
const country = ref('CN');
const agreed = ref(false);
const canNext = computed(() => {
if (current.value === 0) return email.value.length > 3 && password.value.length >= 8;
if (current.value === 1) return name.value.length > 0;
if (current.value === 2) return agreed.value;
return false;
});
function next() {
if (current.value < steps.length - 1) current.value += 1;
else alert(`Register: ${email.value}`);
}
function prev() {
if (current.value > 0) current.value -= 1;
}
</script>
<template>
<div class="reg">
<CfCard class="reg__card">
<h2>注册新账号</h2>
<CfStepper :items="steps" :current="current" />
<div v-if="current === 0" class="reg__pane">
<label class="reg__field">
<span>邮箱</span>
<CfInput v-model="email" type="email" placeholder="[email protected]" />
</label>
<label class="reg__field">
<span>密码</span>
<CfPasswordStrength v-model="password" placeholder="至少 8 位,含大小写、数字、符号" />
</label>
</div>
<div v-if="current === 1" class="reg__pane">
<label class="reg__field">
<span>姓名</span>
<CfInput v-model="name" placeholder="张三" />
</label>
<label class="reg__field">
<span>手机号(可选)</span>
<CfPhoneInput v-model="phone" v-model:country="country" />
</label>
</div>
<div v-if="current === 2" class="reg__pane">
<p>
注册即代表你同意 <a href="#">服务条款</a> 与 <a href="#">隐私政策</a>。
</p>
<label class="reg__agree">
<CfCheckbox v-model="agreed" />
我已阅读并同意上述协议
</label>
</div>
<div class="reg__actions">
<CfButton v-if="current > 0" variant="tertiary" @click="prev">上一步</CfButton>
<CfButton variant="primary" :disabled="!canNext" @click="next">
{{ current === steps.length - 1 ? '完成注册' : '下一步' }}
</CfButton>
</div>
</CfCard>
</div>
</template>
<style scoped>
.reg {
display: flex;
align-items: center;
justify-content: center;
padding: 24px;
min-height: 600px;
font-family: var(--font-sans);
}
.reg__card {
width: 100%;
max-width: 480px;
padding: 28px;
}
.reg__card h2 {
margin: 0 0 16px;
font-size: var(--t-22);
font-weight: var(--w-medium);
color: var(--fg-1);
}
.reg__pane {
margin: 18px 0;
display: flex;
flex-direction: column;
gap: 14px;
font-size: var(--t-13);
}
.reg__field {
display: flex;
flex-direction: column;
gap: 6px;
}
.reg__field > span {
font-size: var(--t-12);
color: var(--fg-2);
}
.reg__agree {
display: inline-flex;
align-items: center;
gap: 8px;
font-size: var(--t-13);
color: var(--fg-2);
}
.reg__actions {
display: flex;
justify-content: flex-end;
gap: 8px;
margin-top: 12px;
}
</style>
import { useState } from 'react';
import {
CfCard,
CfStepper,
CfInput,
CfButton,
CfPasswordStrength,
CfPhoneInput,
CfCheckbox,
} from '@chufix-design/react';
const steps = [
{ id: 'account', title: '账号' },
{ id: 'profile', title: '个人' },
{ id: 'verify', title: '验证' },
];
export function RegisterMultiStep() {
const [current, setCurrent] = useState(0);
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [name, setName] = useState('');
const [phone, setPhone] = useState('');
const [country, setCountry] = useState('CN');
const [agreed, setAgreed] = useState(false);
const canNext =
(current === 0 && email.length > 3 && password.length >= 8) ||
(current === 1 && name.length > 0) ||
(current === 2 && agreed);
function next() {
if (current < steps.length - 1) setCurrent(current + 1);
else alert(`Register: ${email}`);
}
function prev() {
if (current > 0) setCurrent(current - 1);
}
return (
<div className="reg">
<CfCard className="reg__card">
<h2>注册新账号</h2>
<CfStepper items={steps} current={current} />
{current === 0 && (
<div className="reg__pane">
<label className="reg__field">
<span>邮箱</span>
<CfInput value={email} onChange={setEmail} type="email" placeholder="[email protected]" />
</label>
<label className="reg__field">
<span>密码</span>
<CfPasswordStrength value={password} onChange={setPassword} placeholder="至少 8 位,含大小写、数字、符号" />
</label>
</div>
)}
{current === 1 && (
<div className="reg__pane">
<label className="reg__field">
<span>姓名</span>
<CfInput value={name} onChange={setName} placeholder="张三" />
</label>
<label className="reg__field">
<span>手机号(可选)</span>
<CfPhoneInput value={phone} onChange={setPhone} country={country} onCountryChange={setCountry} />
</label>
</div>
)}
{current === 2 && (
<div className="reg__pane">
<p>
注册即代表你同意 <a href="#">服务条款</a> 与 <a href="#">隐私政策</a>。
</p>
<label className="reg__agree">
<CfCheckbox checked={agreed} onChange={setAgreed} />
我已阅读并同意上述协议
</label>
</div>
)}
<div className="reg__actions">
{current > 0 && <CfButton variant="tertiary" onClick={prev}>上一步</CfButton>}
<CfButton variant="primary" disabled={!canNext} onClick={next}>
{current === steps.length - 1 ? '完成注册' : '下一步'}
</CfButton>
</div>
</CfCard>
</div>
);
}