Files
verify/frontend/src/pages/auth/register.vue
T
admin c653ed071d refactor: 将 @iconify/vue 图标替换为 lucide-vue-next 本地组件
- 所有 lucide: 前缀的图标字符串替换为 lucide-vue-next 组件直接引用
- 动态图标绑定改为 <component :is> 渲染
- h(Icon, { icon: 'lucide:xxx' }) 改为 h(Xxx, { class: ... })
- app-card.vue 的 icon_url 改为 <img> 标签(实际是图片路径)
- 修复 Webhook 标识符冲突(重命名为 WebhookIcon)
- payment-channels 保留 @iconify/vue 用于品牌图标(支付宝、微信、Stripe、PayPal、USDT)
2026-05-03 04:25:34 +08:00

216 lines
6.6 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 { Check, Loader2, ShieldCheck } from 'lucide-vue-next'
import { computed, ref } from 'vue'
import { useRouter } from 'vue-router'
import { toast } from 'vue-sonner'
import api from '@/services/api'
const router = useRouter()
const loading = ref(false)
const form = ref({
username: '',
email: '',
password: '',
confirmPassword: '',
agree: false,
})
const isValid = computed(() => {
return form.value.username
&& form.value.email
&& form.value.password
&& form.value.password === form.value.confirmPassword
&& form.value.agree
})
async function handleRegister() {
if (!form.value.username) {
toast.error('请输入用户名')
return
}
if (!form.value.email) {
toast.error('请输入邮箱')
return
}
if (!form.value.password) {
toast.error('请输入密码')
return
}
if (form.value.password.length < 6) {
toast.error('密码长度至少6位')
return
}
if (form.value.password !== form.value.confirmPassword) {
toast.error('两次输入的密码不一致')
return
}
if (!form.value.agree) {
toast.error('请阅读并同意服务条款')
return
}
loading.value = true
try {
await api.post('/auth/register', {
username: form.value.username,
email: form.value.email,
password: form.value.password,
})
toast.success('注册成功,请登录')
router.push('/login')
}
catch (error: any) {
console.error('注册失败:', error)
toast.error(error.message || '注册失败')
}
finally {
loading.value = false
}
}
</script>
<template>
<div class="min-h-screen flex">
<div class="hidden lg:flex lg:w-1/2 bg-gradient-to-br from-primary/10 via-primary/5 to-background relative overflow-hidden">
<div class="absolute inset-0">
<div class="absolute top-20 left-20 w-72 h-72 bg-primary/20 rounded-full blur-3xl" />
<div class="absolute bottom-20 right-20 w-96 h-96 bg-primary/10 rounded-full blur-3xl" />
</div>
<div class="relative z-10 flex flex-col justify-center px-12">
<div class="flex items-center gap-3 mb-8">
<div class="size-12 rounded-xl bg-primary flex items-center justify-center">
<ShieldCheck class="size-7 text-primary-foreground" />
</div>
<span class="text-2xl font-bold">管理平台</span>
</div>
<h1 class="text-4xl font-bold mb-4">
开始使用
</h1>
<p class="text-lg text-muted-foreground mb-8">
创建账号立即体验专业的软件授权管理服务
</p>
<div class="space-y-4">
<div class="flex items-center gap-3">
<div class="size-8 rounded-full bg-primary/20 flex items-center justify-center">
<Check class="size-4 text-primary" />
</div>
<span>免费创建应用快速集成 SDK</span>
</div>
<div class="flex items-center gap-3">
<div class="size-8 rounded-full bg-primary/20 flex items-center justify-center">
<Check class="size-4 text-primary" />
</div>
<span>完善的用户管理和数据分析</span>
</div>
<div class="flex items-center gap-3">
<div class="size-8 rounded-full bg-primary/20 flex items-center justify-center">
<Check class="size-4 text-primary" />
</div>
<span>灵活的卡密授权方案</span>
</div>
</div>
</div>
</div>
<div class="flex-1 flex items-center justify-center p-8">
<div class="w-full max-w-md">
<div class="text-center mb-8 lg:hidden">
<div class="flex items-center justify-center gap-3 mb-4">
<div class="size-10 rounded-xl bg-primary flex items-center justify-center">
<ShieldCheck class="size-6 text-primary-foreground" />
</div>
<span class="text-xl font-bold">管理平台</span>
</div>
</div>
<div class="mb-8">
<h2 class="text-2xl font-bold mb-2">
创建账号
</h2>
<p class="text-muted-foreground">
填写以下信息完成注册
</p>
</div>
<form class="space-y-5" @submit.prevent="handleRegister">
<div class="space-y-2">
<UiLabel for="username">用户名</UiLabel>
<UiInput
id="username"
v-model="form.username"
type="text"
placeholder="请输入用户名"
:disabled="loading"
/>
</div>
<div class="space-y-2">
<UiLabel for="email">邮箱</UiLabel>
<UiInput
id="email"
v-model="form.email"
type="email"
placeholder="请输入邮箱"
:disabled="loading"
/>
</div>
<div class="space-y-2">
<UiLabel for="password">密码</UiLabel>
<UiInput
id="password"
v-model="form.password"
type="password"
placeholder="请输入密码(至少6位)"
:disabled="loading"
/>
</div>
<div class="space-y-2">
<UiLabel for="confirmPassword">确认密码</UiLabel>
<UiInput
id="confirmPassword"
v-model="form.confirmPassword"
type="password"
placeholder="请再次输入密码"
:disabled="loading"
/>
</div>
<div class="flex items-start gap-2">
<UiCheckbox
id="agree"
v-model:checked="form.agree"
/>
<UiLabel for="agree" class="text-sm font-normal cursor-pointer leading-tight">
我已阅读并同意
<a href="#" class="text-primary hover:underline">服务条款</a>
<a href="#" class="text-primary hover:underline">隐私政策</a>
</UiLabel>
</div>
<UiButton
type="submit"
class="w-full"
:disabled="loading || !isValid"
>
<Loader2 v-if="loading" class="mr-2 h-4 w-4 animate-spin" />
{{ loading ? '注册中...' : '注册' }}
</UiButton>
</form>
<div class="mt-6 text-center text-sm text-muted-foreground">
已有账号
<router-link to="/login" class="text-primary hover:underline">
立即登录
</router-link>
</div>
</div>
</div>
</div>
</template>