feat: 迭代
This commit is contained in:
@@ -0,0 +1,319 @@
|
||||
/* 商家后台 - 居中卡片布局 */
|
||||
.merchant-login-container {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, #fff5f0 0%, #ffe8dc 100%);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
padding: 40px 20px;
|
||||
}
|
||||
|
||||
/* 背景装饰 */
|
||||
.merchant-login-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
overflow: hidden;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.bg-decoration {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.bg-circle {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, rgba(255, 107, 107, 0.1) 0%, rgba(254, 202, 87, 0.1) 100%);
|
||||
animation: bgFloat 25s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.bg-circle.circle-1 {
|
||||
width: 600px;
|
||||
height: 600px;
|
||||
top: -200px;
|
||||
right: -200px;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.bg-circle.circle-2 {
|
||||
width: 450px;
|
||||
height: 450px;
|
||||
bottom: -150px;
|
||||
left: -150px;
|
||||
animation-delay: 8s;
|
||||
}
|
||||
|
||||
.bg-circle.circle-3 {
|
||||
width: 350px;
|
||||
height: 350px;
|
||||
top: 40%;
|
||||
left: 50%;
|
||||
animation-delay: 16s;
|
||||
}
|
||||
|
||||
@keyframes bgFloat {
|
||||
0%, 100% {
|
||||
transform: translate(0, 0) scale(1);
|
||||
}
|
||||
33% {
|
||||
transform: translate(30px, -30px) scale(1.05);
|
||||
}
|
||||
66% {
|
||||
transform: translate(-30px, 30px) scale(0.95);
|
||||
}
|
||||
}
|
||||
|
||||
/* 中央登录卡片 */
|
||||
.merchant-login-card {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
max-width: 480px;
|
||||
background: #fff;
|
||||
border-radius: 24px;
|
||||
box-shadow: 0 20px 60px rgba(255, 107, 107, 0.15);
|
||||
padding: 48px 40px;
|
||||
animation: cardSlideUp 0.6s ease-out;
|
||||
}
|
||||
|
||||
@keyframes cardSlideUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* 品牌区域 */
|
||||
.merchant-brand {
|
||||
text-align: center;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.merchant-brand-icon {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: linear-gradient(135deg, rgba(255, 107, 107, 0.1) 0%, rgba(254, 202, 87, 0.1) 100%);
|
||||
border-radius: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto 24px;
|
||||
border: 2px solid rgba(255, 107, 107, 0.2);
|
||||
}
|
||||
|
||||
.merchant-brand-title {
|
||||
font-size: 28px;
|
||||
font-weight: 800;
|
||||
color: #2d3436;
|
||||
margin: 0 0 8px;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.merchant-brand-subtitle {
|
||||
font-size: 15px;
|
||||
color: #636e72;
|
||||
margin: 0;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 表单区域 */
|
||||
.merchant-form-section {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.merchant-form {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.merchant-input {
|
||||
height: 50px;
|
||||
border-radius: 12px;
|
||||
font-size: 15px;
|
||||
border: 2px solid #f0f0f0;
|
||||
transition: all 0.3s;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.merchant-input:hover {
|
||||
border-color: #ff6b6b;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.merchant-input:focus,
|
||||
.merchant-input.ant-input-focused {
|
||||
border-color: #ff6b6b;
|
||||
background: #fff;
|
||||
box-shadow: 0 0 0 4px rgba(255, 107, 107, 0.1);
|
||||
}
|
||||
|
||||
.merchant-input input {
|
||||
height: 100%;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.merchant-input-icon {
|
||||
color: #ff6b6b;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.merchant-code-wrapper {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.merchant-code-input {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.merchant-code-button {
|
||||
height: 50px;
|
||||
border-radius: 12px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
padding: 0 24px;
|
||||
white-space: nowrap;
|
||||
border: 2px solid #f0f0f0;
|
||||
background: #fafafa;
|
||||
transition: all 0.3s;
|
||||
color: #ff6b6b;
|
||||
}
|
||||
|
||||
.merchant-code-button:hover:not(:disabled) {
|
||||
color: #fff;
|
||||
background: #ff6b6b;
|
||||
border-color: #ff6b6b;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(255, 107, 107, 0.3);
|
||||
}
|
||||
|
||||
.merchant-code-button:disabled {
|
||||
color: #bbb;
|
||||
background: #f5f5f5;
|
||||
border-color: #e8e8e8;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.merchant-login-button {
|
||||
height: 50px;
|
||||
border-radius: 12px;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
background: linear-gradient(135deg, #ff6b6b 0%, #feca57 100%);
|
||||
border: none;
|
||||
box-shadow: 0 6px 20px rgba(255, 107, 107, 0.35);
|
||||
transition: all 0.3s;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.merchant-login-button:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 8px 24px rgba(255, 107, 107, 0.45);
|
||||
}
|
||||
|
||||
.merchant-login-button:active {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.merchant-dev-tip {
|
||||
text-align: center;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.merchant-dev-tip p {
|
||||
font-size: 13px;
|
||||
color: #999;
|
||||
margin: 0;
|
||||
padding: 10px 18px;
|
||||
background: #fff5f0;
|
||||
border-radius: 10px;
|
||||
display: inline-block;
|
||||
border: 1px solid #ffe8dc;
|
||||
}
|
||||
|
||||
/* 特性展示 */
|
||||
.merchant-features {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 24px 0;
|
||||
margin-bottom: 24px;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.merchant-feature-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.merchant-feature-icon {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.merchant-feature-text {
|
||||
font-size: 13px;
|
||||
color: #636e72;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 底部 */
|
||||
.merchant-footer {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.merchant-footer p {
|
||||
font-size: 13px;
|
||||
color: #999;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 640px) {
|
||||
.merchant-login-card {
|
||||
padding: 36px 28px;
|
||||
}
|
||||
|
||||
.merchant-brand-title {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.merchant-code-wrapper {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.merchant-code-button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.merchant-features {
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.bg-circle.circle-1 {
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
.bg-circle.circle-2 {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.bg-circle.circle-3 {
|
||||
width: 250px;
|
||||
height: 250px;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Form, Input, Button, Card, message } from 'antd';
|
||||
import { MobileOutlined, SafetyOutlined } from '@ant-design/icons';
|
||||
import { Form, Input, Button, message } from 'antd';
|
||||
import { MobileOutlined, SafetyOutlined, ShopOutlined } from '@ant-design/icons';
|
||||
import { loginByCode, sendSellerCode } from '@/api/auth';
|
||||
import { useAuthStore } from '@/store/auth';
|
||||
import './Login.css';
|
||||
|
||||
const Login: React.FC = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
@@ -55,34 +56,106 @@ const Login: React.FC = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh', background: '#f0f2f5' }}>
|
||||
<Card style={{ width: 400 }} title={<div style={{ textAlign: 'center', fontSize: 20, fontWeight: 600 }}>商家管理后台</div>}>
|
||||
<Form form={form} onFinish={onFinish} size="large">
|
||||
<Form.Item name="phone" rules={[{ required: true, message: '请输入手机号' }, { pattern: /^1\d{10}$/, message: '手机号格式不正确' }]}>
|
||||
<Input prefix={<MobileOutlined />} placeholder="手机号" maxLength={11} />
|
||||
</Form.Item>
|
||||
<Form.Item name="code" rules={[{ required: true, message: '请输入验证码' }]}>
|
||||
<Input
|
||||
prefix={<SafetyOutlined />}
|
||||
placeholder="验证码"
|
||||
maxLength={6}
|
||||
addonAfter={
|
||||
<Button type="link" disabled={countdown > 0} onClick={handleSendCode} style={{ padding: 0, height: 'auto' }}>
|
||||
<div className="merchant-login-container">
|
||||
{/* 顶部装饰背景 */}
|
||||
<div className="merchant-login-bg">
|
||||
<div className="bg-decoration">
|
||||
<div className="bg-circle circle-1"></div>
|
||||
<div className="bg-circle circle-2"></div>
|
||||
<div className="bg-circle circle-3"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 中央登录卡片 */}
|
||||
<div className="merchant-login-card">
|
||||
{/* 品牌区域 */}
|
||||
<div className="merchant-brand">
|
||||
<div className="merchant-brand-icon">
|
||||
<ShopOutlined style={{ fontSize: 56, color: '#ff6b6b' }} />
|
||||
</div>
|
||||
<h1 className="merchant-brand-title">品住会商家后台</h1>
|
||||
<p className="merchant-brand-subtitle">轻松管理您的房源和订单</p>
|
||||
</div>
|
||||
|
||||
{/* 登录表单 */}
|
||||
<div className="merchant-form-section">
|
||||
<Form form={form} onFinish={onFinish} size="large" className="merchant-form">
|
||||
<Form.Item
|
||||
name="phone"
|
||||
rules={[
|
||||
{ required: true, message: '请输入手机号' },
|
||||
{ pattern: /^1\d{10}$/, message: '手机号格式不正确' }
|
||||
]}
|
||||
>
|
||||
<Input
|
||||
prefix={<MobileOutlined className="merchant-input-icon" />}
|
||||
placeholder="手机号"
|
||||
maxLength={11}
|
||||
className="merchant-input"
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="code"
|
||||
rules={[{ required: true, message: '请输入验证码' }]}
|
||||
>
|
||||
<div className="merchant-code-wrapper">
|
||||
<Input
|
||||
prefix={<SafetyOutlined className="merchant-input-icon" />}
|
||||
placeholder="验证码"
|
||||
maxLength={6}
|
||||
className="merchant-input merchant-code-input"
|
||||
/>
|
||||
<Button
|
||||
type="default"
|
||||
disabled={countdown > 0}
|
||||
onClick={handleSendCode}
|
||||
className="merchant-code-button"
|
||||
>
|
||||
{countdown > 0 ? `${countdown}s` : '获取验证码'}
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Button type="primary" htmlType="submit" loading={loading} block>
|
||||
登录
|
||||
</Button>
|
||||
</Form.Item>
|
||||
<div style={{ textAlign: 'center', color: '#999', fontSize: 12 }}>
|
||||
开发环境验证码: 123456
|
||||
</div>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="primary"
|
||||
htmlType="submit"
|
||||
loading={loading}
|
||||
block
|
||||
className="merchant-login-button"
|
||||
>
|
||||
登录
|
||||
</Button>
|
||||
</Form.Item>
|
||||
|
||||
<div className="merchant-dev-tip">
|
||||
<p>开发环境验证码: 123456</p>
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
{/* 特性展示 */}
|
||||
<div className="merchant-features">
|
||||
<div className="merchant-feature-item">
|
||||
<div className="merchant-feature-icon">📦</div>
|
||||
<div className="merchant-feature-text">房源管理</div>
|
||||
</div>
|
||||
</Form>
|
||||
</Card>
|
||||
<div className="merchant-feature-item">
|
||||
<div className="merchant-feature-icon">📋</div>
|
||||
<div className="merchant-feature-text">订单处理</div>
|
||||
</div>
|
||||
<div className="merchant-feature-item">
|
||||
<div className="merchant-feature-icon">💰</div>
|
||||
<div className="merchant-feature-text">财务结算</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 底部 */}
|
||||
<div className="merchant-footer">
|
||||
<p>© 2026 品住会. All rights reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user