chore: update auth and portal
This commit is contained in:
@@ -1,93 +1,144 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { useToast } from 'primevue/usetoast';
|
||||
import Toast from 'primevue/toast';
|
||||
import { authApi } from '../../api/auth';
|
||||
import { tenantPath } from '../../utils/tenant';
|
||||
import { ref } from "vue";
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
import { useToast } from "primevue/usetoast";
|
||||
import Toast from "primevue/toast";
|
||||
import { authApi } from "../../api/auth";
|
||||
import { tenantPath } from "../../utils/tenant";
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const toast = useToast();
|
||||
const step = ref(1);
|
||||
const phone = ref('');
|
||||
const otpCode = ref('');
|
||||
const phone = ref("");
|
||||
const otpCode = ref("");
|
||||
const agreed = ref(false);
|
||||
|
||||
const getOTP = async () => {
|
||||
if(!agreed.value) return;
|
||||
try {
|
||||
await authApi.sendOTP(phone.value);
|
||||
step.value = 2;
|
||||
toast.add({ severity: 'success', summary: '发送成功', detail: '验证码已发送', life: 3000 });
|
||||
} catch (e) {
|
||||
toast.add({ severity: 'error', summary: '错误', detail: e.message, life: 3000 });
|
||||
}
|
||||
if (!agreed.value) return;
|
||||
try {
|
||||
await authApi.sendOTP(phone.value);
|
||||
step.value = 2;
|
||||
toast.add({
|
||||
severity: "success",
|
||||
summary: "发送成功",
|
||||
detail: "验证码已发送",
|
||||
life: 3000,
|
||||
});
|
||||
} catch (e) {
|
||||
toast.add({
|
||||
severity: "error",
|
||||
summary: "错误",
|
||||
detail: e.message,
|
||||
life: 3000,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const login = async () => {
|
||||
try {
|
||||
const res = await authApi.login(phone.value, otpCode.value);
|
||||
localStorage.setItem('token', res.token);
|
||||
localStorage.setItem('user', JSON.stringify(res.user));
|
||||
toast.add({ severity: 'success', summary: '登录成功', detail: '欢迎回来', life: 1000 });
|
||||
setTimeout(() => {
|
||||
router.push(tenantPath('/', route));
|
||||
}, 1000);
|
||||
} catch (e) {
|
||||
toast.add({ severity: 'error', summary: '登录失败', detail: e.message, life: 3000 });
|
||||
}
|
||||
try {
|
||||
const res = await authApi.login(phone.value, otpCode.value);
|
||||
localStorage.setItem("token", res.token);
|
||||
localStorage.setItem("user", JSON.stringify(res.user));
|
||||
toast.add({
|
||||
severity: "success",
|
||||
summary: "登录成功",
|
||||
detail: "欢迎回来",
|
||||
life: 1000,
|
||||
});
|
||||
setTimeout(() => {
|
||||
router.push(tenantPath("/", route));
|
||||
}, 1000);
|
||||
} catch (e) {
|
||||
toast.add({
|
||||
severity: "error",
|
||||
summary: "登录失败",
|
||||
detail: e.message,
|
||||
life: 3000,
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="bg-white rounded-2xl shadow-xl w-full max-w-4xl overflow-hidden flex min-h-[550px]">
|
||||
<div
|
||||
class="bg-white rounded-2xl shadow-xl w-full max-w-4xl overflow-hidden flex min-h-[550px]"
|
||||
>
|
||||
<!-- Left Brand Area -->
|
||||
<div class="hidden md:flex w-1/2 bg-slate-900 relative p-12 flex-col justify-between text-white">
|
||||
<div
|
||||
class="hidden md:flex w-1/2 bg-slate-900 relative p-12 flex-col justify-between text-white"
|
||||
>
|
||||
<!-- Decor/Bg could be here -->
|
||||
<div class="z-10">
|
||||
<div class="flex items-center gap-2 mb-8">
|
||||
<div class="w-8 h-8 bg-white/20 rounded flex items-center justify-center font-bold">Q</div>
|
||||
<span class="text-xl font-bold">Quyun</span>
|
||||
<div
|
||||
class="w-8 h-8 bg-white/20 rounded flex items-center justify-center font-bold"
|
||||
>
|
||||
Q
|
||||
</div>
|
||||
<span class="text-xl font-bold">Quyun</span>
|
||||
</div>
|
||||
<h1 class="text-4xl font-bold leading-tight mb-4">探索戏曲的<br>无限可能</h1>
|
||||
<p class="text-slate-400">专业的租户管理与内容交付平台,连接创作者与用户。</p>
|
||||
<h1 class="text-4xl font-bold leading-tight mb-4">
|
||||
探索戏曲的<br />无限可能
|
||||
</h1>
|
||||
<p class="text-slate-400">
|
||||
专业的租户管理与内容交付平台,连接创作者与用户。
|
||||
</p>
|
||||
</div>
|
||||
<div class="text-xs text-slate-500 z-10">
|
||||
© 2025 Quyun. All rights reserved.
|
||||
</div>
|
||||
<div class="text-xs text-slate-500 z-10">© 2025 Quyun. All rights reserved.</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Form Area -->
|
||||
<div class="w-full md:w-1/2 p-8 sm:p-12 flex flex-col justify-center bg-white relative">
|
||||
<div
|
||||
class="w-full md:w-1/2 p-8 sm:p-12 flex flex-col justify-center bg-white relative"
|
||||
>
|
||||
<div v-if="step === 1">
|
||||
<h2 class="text-2xl font-bold text-slate-900 mb-2">欢迎回来</h2>
|
||||
<p class="text-sm text-slate-500 mb-8">未注册的手机号验证后将自动创建账号</p>
|
||||
<p class="text-sm text-slate-500 mb-8">
|
||||
未注册的手机号验证后将自动创建账号
|
||||
</p>
|
||||
|
||||
<form @submit.prevent="getOTP">
|
||||
<div class="mb-6">
|
||||
<label class="block text-sm font-medium text-slate-700 mb-2">手机号码</label>
|
||||
<label class="block text-sm font-medium text-slate-700 mb-2"
|
||||
>手机号码</label
|
||||
>
|
||||
<div class="flex">
|
||||
<span class="inline-flex items-center px-4 rounded-l-lg border border-r-0 border-slate-300 bg-slate-50 text-slate-500 text-sm">+86</span>
|
||||
<input
|
||||
<span
|
||||
class="inline-flex items-center px-4 rounded-l-lg border border-r-0 border-slate-300 bg-slate-50 text-slate-500 text-sm"
|
||||
>+86</span
|
||||
>
|
||||
<input
|
||||
v-model="phone"
|
||||
type="tel"
|
||||
class="flex-1 block w-full rounded-r-lg border border-slate-300 focus:border-primary-500 focus:ring-primary-500 sm:text-lg py-3 px-4"
|
||||
type="tel"
|
||||
class="flex-1 block w-full rounded-r-lg border border-slate-300 focus:border-primary-500 focus:ring-primary-500 sm:text-lg py-3 px-4"
|
||||
placeholder="请输入手机号"
|
||||
required
|
||||
>
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-start mb-6">
|
||||
<div class="flex items-center h-5">
|
||||
<input id="terms" v-model="agreed" type="checkbox" class="w-5 h-5 rounded border-slate-300 text-primary-600 focus:ring-primary-500">
|
||||
<input
|
||||
id="terms"
|
||||
v-model="agreed"
|
||||
type="checkbox"
|
||||
class="w-5 h-5 rounded border-slate-300 text-primary-600 focus:ring-primary-500"
|
||||
/>
|
||||
</div>
|
||||
<label for="terms" class="ml-3 text-sm text-slate-500">
|
||||
我已阅读并同意 <a href="#" class="text-primary-600 hover:underline">用户协议</a> 和 <a href="#" class="text-primary-600 hover:underline">隐私政策</a>
|
||||
我已阅读并同意
|
||||
<a href="#" class="text-primary-600 hover:underline">用户协议</a>
|
||||
和
|
||||
<a href="#" class="text-primary-600 hover:underline">隐私政策</a>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
<button
|
||||
type="submit"
|
||||
class="w-full flex justify-center py-3 px-4 border border-transparent rounded-lg shadow-sm text-lg font-medium text-white bg-primary-600 hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
:disabled="!agreed || !phone"
|
||||
>
|
||||
@@ -105,38 +156,55 @@ const login = async () => {
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-6 flex justify-center gap-6">
|
||||
<button class="w-10 h-10 rounded-full bg-slate-50 border border-slate-200 flex items-center justify-center hover:bg-slate-100 text-green-600"><i class="pi pi-wechat text-xl"></i></button>
|
||||
<button class="w-10 h-10 rounded-full bg-slate-50 border border-slate-200 flex items-center justify-center hover:bg-slate-100 text-slate-800"><i class="pi pi-github text-xl"></i></button>
|
||||
<button
|
||||
class="w-10 h-10 rounded-full bg-slate-50 border border-slate-200 flex items-center justify-center hover:bg-slate-100 text-green-600"
|
||||
>
|
||||
<i class="pi pi-wechat text-xl"></i>
|
||||
</button>
|
||||
<button
|
||||
class="w-10 h-10 rounded-full bg-slate-50 border border-slate-200 flex items-center justify-center hover:bg-slate-100 text-slate-800"
|
||||
>
|
||||
<i class="pi pi-github text-xl"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="step === 2">
|
||||
<button @click="step = 1" class="absolute top-8 left-8 text-slate-400 hover:text-slate-600"><i class="pi pi-arrow-left mr-1"></i> 返回</button>
|
||||
<h2 class="text-2xl font-bold text-slate-900 mb-2">输入验证码</h2>
|
||||
<p class="text-sm text-slate-500 mb-8">验证码已发送至 +86 {{ phone }}</p>
|
||||
<button
|
||||
@click="step = 1"
|
||||
class="absolute top-8 left-8 text-slate-400 hover:text-slate-600"
|
||||
>
|
||||
<i class="pi pi-arrow-left mr-1"></i> 返回
|
||||
</button>
|
||||
<h2 class="text-2xl font-bold text-slate-900 mb-2">输入验证码</h2>
|
||||
<p class="text-sm text-slate-500 mb-8">
|
||||
验证码已发送至 +86 {{ phone }}
|
||||
</p>
|
||||
|
||||
<div class="mb-8">
|
||||
<input
|
||||
v-model="otpCode"
|
||||
type="text"
|
||||
maxlength="4"
|
||||
class="w-full h-14 px-4 text-center text-3xl font-bold border border-slate-300 rounded-lg focus:border-primary-500 focus:ring-4 focus:ring-primary-100 outline-none tracking-[1.5em] pl-[1.5em]"
|
||||
placeholder="0000"
|
||||
@input="otpCode = otpCode.replace(/\D/g, '')"
|
||||
>
|
||||
</div>
|
||||
<div class="mb-8">
|
||||
<input
|
||||
v-model="otpCode"
|
||||
type="text"
|
||||
maxlength="4"
|
||||
class="w-full h-14 px-4 text-center text-3xl font-bold border border-slate-300 rounded-lg focus:border-primary-500 focus:ring-4 focus:ring-primary-100 outline-none tracking-[1.5em] pl-[1.5em]"
|
||||
placeholder="0000"
|
||||
@input="otpCode = otpCode.replace(/\D/g, '')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="text-center mb-8">
|
||||
<button class="text-sm text-slate-500 hover:text-primary-600">59s 后重新获取</button>
|
||||
</div>
|
||||
|
||||
<button
|
||||
@click="login"
|
||||
class="w-full flex justify-center py-3 px-4 border border-transparent rounded-lg shadow-sm text-lg font-medium text-white bg-primary-600 hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500"
|
||||
>
|
||||
登录 / 注册
|
||||
<div class="text-center mb-8">
|
||||
<button class="text-sm text-slate-500 hover:text-primary-600">
|
||||
59s 后重新获取
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button
|
||||
@click="login"
|
||||
class="w-full flex justify-center py-3 px-4 border border-transparent rounded-lg shadow-sm text-lg font-medium text-white bg-primary-600 hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500"
|
||||
>
|
||||
登录 / 注册
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<Toast />
|
||||
|
||||
Reference in New Issue
Block a user