feat: 迭代

This commit is contained in:
2026-05-15 19:06:32 +08:00
parent 8c908ea557
commit 848df4c873
22 changed files with 1545 additions and 355 deletions
+319
View File
@@ -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;
}
}
+100 -27
View File
@@ -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>
);
};