|
@@ -120,18 +120,25 @@ const handleLogin = async () => {
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
|
<template>
|
|
|
- <div class="min-h-screen bg-gradient-to-br from-slate-50 to-slate-100">
|
|
|
|
|
- <div class="mx-auto flex min-h-screen max-w-md flex-col justify-center px-4 py-10">
|
|
|
|
|
- <div class="rounded-3xl border border-slate-200 bg-white p-6 shadow-lg">
|
|
|
|
|
|
|
+ <div class="fixed inset-0 overflow-y-auto bg-gradient-to-br from-slate-50 via-slate-50 to-slate-100">
|
|
|
|
|
+ <!-- 装饰性背景渐变 -->
|
|
|
|
|
+ <div class="pointer-events-none fixed inset-0 -z-10">
|
|
|
|
|
+ <div class="absolute top-0 left-0 w-96 h-96 bg-cyan-500/10 rounded-full blur-3xl"></div>
|
|
|
|
|
+ <div class="absolute bottom-0 right-0 w-96 h-96 bg-indigo-500/10 rounded-full blur-3xl"></div>
|
|
|
|
|
+ <div class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[600px] h-[600px] bg-cyan-400/5 rounded-full blur-3xl"></div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="relative z-0 mx-auto flex min-h-screen max-w-md flex-col justify-center px-4 py-10">
|
|
|
|
|
+ <div class="rounded-3xl border border-slate-200/80 bg-white/80 backdrop-blur-sm p-6 shadow-xl shadow-slate-200/50">
|
|
|
<!-- 标题 -->
|
|
<!-- 标题 -->
|
|
|
<div class="mb-6 text-center">
|
|
<div class="mb-6 text-center">
|
|
|
<div class="text-2xl font-bold text-slate-900">QR Code Management</div>
|
|
<div class="text-2xl font-bold text-slate-900">QR Code Management</div>
|
|
|
<div class="mt-1 text-sm text-slate-500">Register or login to manage your QR codes</div>
|
|
<div class="mt-1 text-sm text-slate-500">Register or login to manage your QR codes</div>
|
|
|
<!-- 首次扫码提示 -->
|
|
<!-- 首次扫码提示 -->
|
|
|
- <div v-if="qrCode" class="mt-4 rounded-2xl bg-slate-50 border border-slate-200 px-4 py-3">
|
|
|
|
|
|
|
+ <div v-if="qrCode" class="mt-4 rounded-2xl bg-cyan-50/50 border border-cyan-200/50 px-4 py-3 backdrop-blur-sm">
|
|
|
<div class="flex items-center gap-2.5">
|
|
<div class="flex items-center gap-2.5">
|
|
|
- <i class="pi pi-info-circle text-base text-slate-500"></i>
|
|
|
|
|
- <div class="flex-1 text-sm text-slate-700 leading-relaxed">
|
|
|
|
|
|
|
+ <i class="pi pi-info-circle text-base text-cyan-600"></i>
|
|
|
|
|
+ <div class="flex-1 text-sm text-cyan-900 leading-relaxed">
|
|
|
First time activating QR code, please log in to bind your account for future management
|
|
First time activating QR code, please log in to bind your account for future management
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -139,7 +146,7 @@ const handleLogin = async () => {
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<!-- 模式切换(仅在无二维码参数时显示) -->
|
|
<!-- 模式切换(仅在无二维码参数时显示) -->
|
|
|
- <div v-if="!qrCode" class="mb-6 flex rounded-xl bg-slate-100 p-1">
|
|
|
|
|
|
|
+ <div v-if="!qrCode" class="mb-6 flex rounded-xl bg-slate-100/80 p-1 backdrop-blur-sm">
|
|
|
<button
|
|
<button
|
|
|
type="button"
|
|
type="button"
|
|
|
class="flex-1 rounded-lg px-4 py-2 text-sm font-medium transition-all"
|
|
class="flex-1 rounded-lg px-4 py-2 text-sm font-medium transition-all"
|
|
@@ -165,7 +172,7 @@ const handleLogin = async () => {
|
|
|
<input
|
|
<input
|
|
|
v-model="loginName"
|
|
v-model="loginName"
|
|
|
type="text"
|
|
type="text"
|
|
|
- class="w-full rounded-xl border border-slate-200 px-3 py-2 outline-none focus:border-slate-900"
|
|
|
|
|
|
|
+ class="w-full rounded-xl border border-slate-200 px-3 py-2.5 outline-none focus:border-slate-900 focus:ring-2 focus:ring-slate-900/10 transition-colors bg-white"
|
|
|
placeholder="Enter username"
|
|
placeholder="Enter username"
|
|
|
autocomplete="username"
|
|
autocomplete="username"
|
|
|
/>
|
|
/>
|
|
@@ -176,7 +183,7 @@ const handleLogin = async () => {
|
|
|
<input
|
|
<input
|
|
|
v-model="loginPassword"
|
|
v-model="loginPassword"
|
|
|
:type="showLoginPassword ? 'text' : 'password'"
|
|
:type="showLoginPassword ? 'text' : 'password'"
|
|
|
- class="w-full rounded-xl border border-slate-200 px-3 py-2 pr-10 outline-none focus:border-slate-900"
|
|
|
|
|
|
|
+ class="w-full rounded-xl border border-slate-200 px-3 py-2.5 pr-10 outline-none focus:border-slate-900 focus:ring-2 focus:ring-slate-900/10 transition-colors bg-white"
|
|
|
placeholder="Enter password"
|
|
placeholder="Enter password"
|
|
|
autocomplete="current-password"
|
|
autocomplete="current-password"
|
|
|
/>
|
|
/>
|
|
@@ -192,7 +199,7 @@ const handleLogin = async () => {
|
|
|
|
|
|
|
|
<button
|
|
<button
|
|
|
type="submit"
|
|
type="submit"
|
|
|
- class="w-full rounded-xl bg-slate-900 px-4 py-2 text-sm font-semibold text-white hover:bg-slate-800 disabled:opacity-60"
|
|
|
|
|
|
|
+ class="w-full rounded-xl bg-slate-900 px-4 py-2.5 text-sm font-semibold text-white hover:bg-slate-800 transition-colors disabled:opacity-60 shadow-sm"
|
|
|
:disabled="loginLoading"
|
|
:disabled="loginLoading"
|
|
|
>
|
|
>
|
|
|
{{ loginLoading ? 'Logging in...' : 'Login' }}
|
|
{{ loginLoading ? 'Logging in...' : 'Login' }}
|
|
@@ -204,7 +211,7 @@ const handleLogin = async () => {
|
|
|
Don't have an account?
|
|
Don't have an account?
|
|
|
<button
|
|
<button
|
|
|
type="button"
|
|
type="button"
|
|
|
- class="ml-1 font-semibold text-blue-600 hover:text-blue-800 transition-colors"
|
|
|
|
|
|
|
+ class="ml-1 font-semibold text-cyan-600 hover:text-cyan-700 transition-colors"
|
|
|
@click="mode = 'register'"
|
|
@click="mode = 'register'"
|
|
|
>
|
|
>
|
|
|
Click to register
|
|
Click to register
|
|
@@ -226,7 +233,7 @@ const handleLogin = async () => {
|
|
|
<input
|
|
<input
|
|
|
v-model="registerName"
|
|
v-model="registerName"
|
|
|
type="text"
|
|
type="text"
|
|
|
- class="w-full rounded-xl border border-slate-200 px-3 py-2 outline-none focus:border-slate-900"
|
|
|
|
|
|
|
+ class="w-full rounded-xl border border-slate-200 px-3 py-2.5 outline-none focus:border-slate-900 focus:ring-2 focus:ring-slate-900/10 transition-colors bg-white"
|
|
|
placeholder="Enter username"
|
|
placeholder="Enter username"
|
|
|
autocomplete="username"
|
|
autocomplete="username"
|
|
|
/>
|
|
/>
|
|
@@ -237,7 +244,7 @@ const handleLogin = async () => {
|
|
|
<input
|
|
<input
|
|
|
v-model="registerPassword"
|
|
v-model="registerPassword"
|
|
|
:type="showRegisterPassword ? 'text' : 'password'"
|
|
:type="showRegisterPassword ? 'text' : 'password'"
|
|
|
- class="w-full rounded-xl border border-slate-200 px-3 py-2 pr-10 outline-none focus:border-slate-900"
|
|
|
|
|
|
|
+ class="w-full rounded-xl border border-slate-200 px-3 py-2.5 pr-10 outline-none focus:border-slate-900 focus:ring-2 focus:ring-slate-900/10 transition-colors bg-white"
|
|
|
placeholder="At least 8 characters, including uppercase, lowercase letters and numbers"
|
|
placeholder="At least 8 characters, including uppercase, lowercase letters and numbers"
|
|
|
autocomplete="new-password"
|
|
autocomplete="new-password"
|
|
|
/>
|
|
/>
|
|
@@ -256,7 +263,7 @@ const handleLogin = async () => {
|
|
|
<input
|
|
<input
|
|
|
v-model="registerConfirmPassword"
|
|
v-model="registerConfirmPassword"
|
|
|
:type="showRegisterConfirmPassword ? 'text' : 'password'"
|
|
:type="showRegisterConfirmPassword ? 'text' : 'password'"
|
|
|
- class="w-full rounded-xl border border-slate-200 px-3 py-2 pr-10 outline-none focus:border-slate-900"
|
|
|
|
|
|
|
+ class="w-full rounded-xl border border-slate-200 px-3 py-2.5 pr-10 outline-none focus:border-slate-900 focus:ring-2 focus:ring-slate-900/10 transition-colors bg-white"
|
|
|
placeholder="Re-enter password"
|
|
placeholder="Re-enter password"
|
|
|
autocomplete="new-password"
|
|
autocomplete="new-password"
|
|
|
/>
|
|
/>
|
|
@@ -272,7 +279,7 @@ const handleLogin = async () => {
|
|
|
|
|
|
|
|
<button
|
|
<button
|
|
|
type="submit"
|
|
type="submit"
|
|
|
- class="w-full rounded-xl bg-slate-900 px-4 py-2 text-sm font-semibold text-white hover:bg-slate-800 disabled:opacity-60"
|
|
|
|
|
|
|
+ class="w-full rounded-xl bg-slate-900 px-4 py-2.5 text-sm font-semibold text-white hover:bg-slate-800 transition-colors disabled:opacity-60 shadow-sm"
|
|
|
:disabled="registerLoading"
|
|
:disabled="registerLoading"
|
|
|
>
|
|
>
|
|
|
{{ registerLoading ? 'Registering...' : 'Register' }}
|
|
{{ registerLoading ? 'Registering...' : 'Register' }}
|
|
@@ -284,7 +291,7 @@ const handleLogin = async () => {
|
|
|
Already have an account?
|
|
Already have an account?
|
|
|
<button
|
|
<button
|
|
|
type="button"
|
|
type="button"
|
|
|
- class="ml-1 font-semibold text-blue-600 hover:text-blue-800 transition-colors"
|
|
|
|
|
|
|
+ class="ml-1 font-semibold text-cyan-600 hover:text-cyan-700 transition-colors"
|
|
|
@click="mode = 'login'"
|
|
@click="mode = 'login'"
|
|
|
>
|
|
>
|
|
|
Click to login
|
|
Click to login
|