feat: enhance mobile responsiveness across settings and image pages

This commit is contained in:
ShiYu
2025-05-19 17:34:42 +08:00
parent 61f254450c
commit 7a93a03903
7 changed files with 252 additions and 308 deletions

View File

@@ -1,13 +1,15 @@
import { useState, useRef, useMemo, useCallback } from 'react';
import { Typography, Button, Dropdown, message } from 'antd';
import { Typography, Button, Dropdown, message, Row, Col } from 'antd';
import { SortAscendingOutlined, UploadOutlined } from '@ant-design/icons';
import type { PictureResponse } from '../../api';
import ImageUploadDialog from '../../components/upload/ImageUploadDialog';
import ImageGrid from '../../components/image/ImageGrid';
import useIsMobile from '../../hooks/useIsMobile';
const { Title } = Typography;
function AllImages() {
const isMobile = useIsMobile();
const [images, setImages] = useState<PictureResponse[]>([]);
const [currentPage, setCurrentPage] = useState(1);
const [pageSize, setPageSize] = useState(20);
@@ -76,60 +78,66 @@ function AllImages() {
return (
<>
<div style={{
marginBottom: 50,
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: isMobile ? 30 : 50,
position: 'relative',
zIndex: 1
}}>
<div>
<Title level={2} style={{
margin: 0,
marginBottom: 10,
fontWeight: 600,
letterSpacing: '0.5px',
fontSize: 32,
background: 'linear-gradient(120deg, #000000, #444444)',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
}}></Title>
</div>
<div style={{ display: 'flex', gap: 12 }}>
<Button
type="primary"
icon={<UploadOutlined />}
style={{
borderRadius: 10,
height: 46,
padding: '0 24px',
display: 'flex',
alignItems: 'center',
gap: 8,
fontSize: 15
}}
onClick={() => setIsUploadDialogVisible(true)}
>
</Button>
<Dropdown menu={sortMenu} placement="bottomRight">
<Button style={{
borderRadius: 10,
height: 46,
border: '1px solid #f0f0f0',
padding: '0 24px',
display: 'flex',
alignItems: 'center',
gap: 8,
fontSize: 15,
boxShadow: '0 2px 8px rgba(0,0,0,0.02)',
background: '#ffffff'
<Row gutter={[16, 16]} align="middle">
<Col xs={24} sm={24} md={12} lg={12}>
<Title level={2} style={{
margin: 0,
marginBottom: isMobile ? 5 : 10,
fontWeight: 600,
letterSpacing: '0.5px',
fontSize: isMobile ? 24 : 32,
background: 'linear-gradient(120deg, #000000, #444444)',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
textAlign: isMobile ? 'center' : 'left',
}}></Title>
</Col>
<Col xs={24} sm={24} md={12} lg={12}>
<div style={{
display: 'flex',
gap: isMobile ? 8 : 12,
justifyContent: isMobile ? 'center' : 'flex-end'
}}>
<SortAscendingOutlined />
</Button>
</Dropdown>
</div>
<Button
type="primary"
icon={<UploadOutlined />}
style={{
borderRadius: 10,
height: isMobile ? 40 : 46,
padding: isMobile ? '0 15px' : '0 24px',
display: 'flex',
alignItems: 'center',
gap: 8,
fontSize: isMobile ? 14 : 15
}}
onClick={() => setIsUploadDialogVisible(true)}
>
</Button>
<Dropdown menu={sortMenu} placement="bottomRight">
<Button style={{
borderRadius: 10,
height: isMobile ? 40 : 46,
border: '1px solid #f0f0f0',
padding: isMobile ? '0 15px' : '0 24px',
display: 'flex',
alignItems: 'center',
gap: 8,
fontSize: isMobile ? 14 : 15,
boxShadow: '0 2px 8px rgba(0,0,0,0.02)',
background: '#ffffff'
}}>
<SortAscendingOutlined />
{!isMobile && "排序方式"}
</Button>
</Dropdown>
</div>
</Col>
</Row>
</div>
<ImageGrid

View File

@@ -19,12 +19,14 @@ import {
import ImageGrid from '../../components/image/ImageGrid';
import type { PictureResponse } from '../../api/types';
import { getFilteredTags } from '../../api/tagApi';
import useIsMobile from '../../hooks/useIsMobile';
const { Title, Text, Paragraph } = Typography;
const { Search } = Input;
const { Option } = Select;
const PixHub: React.FC = () => {
const isMobile = useIsMobile();
const [activeCategory, setActiveCategory] = useState('全部');
const [sortBy, setSortBy] = useState('newest');
const [searchQuery, setSearchQuery] = useState('');
@@ -84,28 +86,50 @@ const PixHub: React.FC = () => {
return (
<div className="image-square">
<div className="page-header" style={{ marginBottom: 32 }}>
<Row gutter={[24, 24]} align="middle">
<div className="page-header" style={{ marginBottom: isMobile ? 20 : 32 }}>
<Row gutter={[24, isMobile ? 12 : 24]} align="middle">
<Col lg={10} md={12} sm={24} xs={24}>
<Title level={2} style={{ marginBottom: 8, fontWeight: 600 }}>
<Title level={2} style={{
marginBottom: 8,
fontWeight: 600,
fontSize: isMobile ? 24 : 30,
textAlign: isMobile ? 'center' : 'left'
}}>
广
<Text style={{ fontSize: 16, fontWeight: 400, marginLeft: 12, color: '#8c8c8c' }}>
{!isMobile && (
<Text style={{ fontSize: 16, fontWeight: 400, marginLeft: 12, color: '#8c8c8c' }}>
</Text>
)}
</Title>
{isMobile && (
<Text style={{
fontSize: 14,
fontWeight: 400,
color: '#8c8c8c',
display: 'block',
textAlign: 'center'
}}>
</Text>
</Title>
<Paragraph style={{ color: '#666666' }}>
)}
<Paragraph style={{
color: '#666666',
textAlign: isMobile ? 'center' : 'left',
marginBottom: isMobile ? 5 : 'inherit'
}}>
</Paragraph>
</Col>
<Col lg={14} md={12} sm={24} xs={24}>
<Row gutter={[16, 16]} justify="end">
<Row gutter={[16, 16]} justify={isMobile ? "center" : "end"}>
<Col lg={16} md={16} sm={16} xs={24}>
<Search
placeholder="搜索图片、标签或创作者"
allowClear
enterButton={<SearchOutlined />}
size="large"
size={isMobile ? "middle" : "large"}
onSearch={(value) => setSearchQuery(value)}
style={{ width: '100%' }}
/>
@@ -113,7 +137,7 @@ const PixHub: React.FC = () => {
<Col lg={8} md={8} sm={8} xs={24}>
<Select
style={{ width: '100%' }}
size="large"
size={isMobile ? "middle" : "large"}
value={sortBy}
onChange={(value) => setSortBy(value)}
suffixIcon={<FilterOutlined />}
@@ -128,18 +152,22 @@ const PixHub: React.FC = () => {
</Row>
</div>
<div className="category-nav" style={{ marginBottom: 28, overflowX: 'auto' }}>
<Space size={[12, 20]} wrap style={{ justifyContent: 'center' }}>
<div className="category-nav" style={{
marginBottom: isMobile ? 20 : 28,
overflowX: 'auto',
paddingBottom: 8
}}>
<Space size={[isMobile ? 8 : 12, isMobile ? 10 : 20]} wrap style={{ justifyContent: 'center' }}>
{categories.map(category => (
<Button
key={category}
type={activeCategory === category ? "primary" : "default"}
shape="round"
size="large"
size={isMobile ? "middle" : "large"}
onClick={() => setActiveCategory(category)}
style={{
fontWeight: 500,
minWidth: 80,
minWidth: isMobile ? 70 : 80,
boxShadow: activeCategory === category ? '0 4px 12px rgba(0,0,0,0.15)' : 'none',
}}
icon={category === '全部' ? <ThunderboltOutlined /> : null}
@@ -151,12 +179,12 @@ const PixHub: React.FC = () => {
</Space>
</div>
<Divider style={{ margin: '24px 0' }} />
<Divider style={{ margin: isMobile ? '16px 0' : '24px 0' }} />
<div className="results-info" style={{ marginBottom: 24 }}>
<div className="results-info" style={{ marginBottom: isMobile ? 16 : 24 }}>
<Row justify="space-between" align="middle">
<Col>
<Text style={{ fontSize: 15 }}>
<Text style={{ fontSize: isMobile ? 14 : 15 }}>
<strong>{totalCount}</strong>
{activeCategory !== '全部' && <span> · {activeCategory}</span>}
{searchQuery && <span> · "{searchQuery}"</span>}

View File

@@ -1,219 +0,0 @@
// 模拟图片数据
export const mockImages = [
{
id: 1,
title: '湖畔日落',
url: 'https://images.unsplash.com/photo-1501785888041-af3ef285b470?ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80',
category: '风景',
tags: ['风景', '日落', '自然'],
likes: 342,
views: 1205,
favorited: false,
liked: true,
createdAt: '2023-09-15T10:30:00Z',
description: '湖边美丽的日落景色,金色的阳光洒在水面上,形成了壮观的景象。',
author: {
id: 101,
name: '王摄影',
avatar: 'https://randomuser.me/api/portraits/men/32.jpg',
}
},
{
id: 2,
title: '都市天际线',
url: 'https://images.unsplash.com/photo-1477959858617-67f85cf4f1df?ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80',
category: '城市',
tags: ['城市', '建筑', '天际线'],
likes: 278,
views: 890,
favorited: true,
liked: false,
createdAt: '2023-10-02T14:45:00Z',
description: '现代城市的壮观天际线,高楼大厦在夕阳映衬下显得格外壮观。',
author: {
id: 102,
name: '城市猎影',
avatar: 'https://randomuser.me/api/portraits/women/44.jpg',
}
},
{
id: 3,
title: '山谷晨雾',
url: 'https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80',
category: '自然',
tags: ['山', '晨雾', '自然'],
likes: 432,
views: 1560,
favorited: false,
liked: false,
createdAt: '2023-08-05T06:15:00Z',
description: '清晨的山谷被薄雾笼罩,阳光穿透云层形成光束,构成一幅绝美的画面。',
author: {
id: 103,
name: '山野行者',
avatar: 'https://randomuser.me/api/portraits/men/76.jpg',
}
},
{
id: 4,
title: '意式咖啡',
url: 'https://images.unsplash.com/photo-1513558161293-cdaf765ed2fd?ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80',
category: '美食',
tags: ['咖啡', '美食', '生活'],
likes: 189,
views: 745,
favorited: true,
liked: true,
createdAt: '2023-10-12T09:20:00Z',
description: '精心制作的意式浓缩咖啡,香气四溢,是一天完美的开始。',
author: {
id: 104,
name: '美食家',
avatar: 'https://randomuser.me/api/portraits/women/91.jpg',
}
},
{
id: 5,
title: '森林小径',
url: 'https://images.unsplash.com/photo-1441974231531-c6227db76b6e?ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80',
category: '自然',
tags: ['森林', '自然', '小径'],
likes: 256,
views: 920,
favorited: false,
liked: false,
createdAt: '2023-09-28T15:30:00Z',
description: '穿过茂密森林的小径,阳光透过树叶形成斑驳的光影效果。',
author: {
id: 105,
name: '自然探索者',
avatar: 'https://randomuser.me/api/portraits/men/55.jpg',
}
},
{
id: 6,
title: '古典建筑',
url: 'https://images.unsplash.com/photo-1496568816309-51d7c20e3b21?ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80',
category: '建筑',
tags: ['建筑', '古典', '艺术'],
likes: 312,
views: 1105,
favorited: true,
liked: false,
createdAt: '2023-07-19T11:40:00Z',
description: '充满历史感的欧洲古典建筑,精美的细节和宏伟的设计令人惊叹。',
author: {
id: 106,
name: '建筑师',
avatar: 'https://randomuser.me/api/portraits/women/22.jpg',
}
},
{
id: 7,
title: '夏日海滩',
url: 'https://images.unsplash.com/photo-1520454974749-611b7248ffdb?ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80',
category: '旅行',
tags: ['海滩', '旅行', '夏日'],
likes: 385,
views: 1320,
favorited: false,
liked: true,
createdAt: '2023-08-22T13:50:00Z',
description: '阳光明媚的夏日海滩,湛蓝的海水和金色的沙滩构成完美的度假胜地。',
author: {
id: 107,
name: '旅行摄影师',
avatar: 'https://randomuser.me/api/portraits/men/29.jpg',
}
},
{
id: 8,
title: '雨后街景',
url: 'https://images.unsplash.com/photo-1520116468816-95b69f847357?ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80',
category: '城市',
tags: ['城市', '雨天', '生活'],
likes: 197,
views: 876,
favorited: true,
liked: true,
createdAt: '2023-10-05T18:25:00Z',
description: '雨后的城市街道,湿漉漉的路面反射着霓虹灯光,营造出独特的都市氛围。',
author: {
id: 108,
name: '城市观察者',
avatar: 'https://randomuser.me/api/portraits/women/67.jpg',
}
},
{
id: 9,
title: '宁静湖泊',
url: 'https://images.unsplash.com/photo-1508739773434-c26b3d09e071?ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80',
category: '风景',
tags: ['湖泊', '风景', '宁静'],
likes: 274,
views: 945,
favorited: false,
liked: false,
createdAt: '2023-08-30T07:10:00Z',
description: '清晨宁静的湖泊,平静的湖面如同一面镜子,倒映着周围的山景和天空。',
author: {
id: 109,
name: '风景摄影家',
avatar: 'https://randomuser.me/api/portraits/men/42.jpg',
}
},
{
id: 10,
title: '人像写真',
url: 'https://images.unsplash.com/photo-1531746020798-e6953c6e8e04?ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80',
category: '人像',
tags: ['人像', '艺术', '写真'],
likes: 364,
views: 1230,
favorited: true,
liked: false,
createdAt: '2023-09-18T16:40:00Z',
description: '艺术风格的人像摄影,通过光影和构图展现主题的个性与魅力。',
author: {
id: 110,
name: '人像摄影师',
avatar: 'https://randomuser.me/api/portraits/women/33.jpg',
}
},
{
id: 11,
title: '繁星夜空',
url: 'https://images.unsplash.com/photo-1489549132488-d00b7eee80f1?ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80',
category: '自然',
tags: ['夜空', '星星', '自然'],
likes: 412,
views: 1480,
favorited: false,
liked: true,
createdAt: '2023-07-28T22:15:00Z',
description: '壮丽的夜空星河,数以万计的星星点缀着黑色的天幕,令人叹为观止。',
author: {
id: 111,
name: '星空摄影师',
avatar: 'https://randomuser.me/api/portraits/men/18.jpg',
}
},
{
id: 12,
title: '历史建筑',
url: 'https://images.unsplash.com/photo-1526378722484-bd91ca387e72?ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80',
category: '建筑',
tags: ['建筑', '历史', '艺术'],
likes: 287,
views: 1050,
favorited: true,
liked: false,
createdAt: '2023-08-12T10:05:00Z',
description: '充满历史感的古老建筑,每一块砖石都诉说着岁月的故事。',
author: {
id: 112,
name: '历史摄影',
avatar: 'https://randomuser.me/api/portraits/women/52.jpg',
}
}
];

View File

@@ -11,13 +11,15 @@ interface ConfigGroupProps {
descriptions: {
[key: string]: string;
};
isMobile?: boolean;
}
const ConfigGroup: React.FC<ConfigGroupProps> = ({
groupName,
configs,
onSave,
descriptions
descriptions,
isMobile = false
}) => {
const [form] = Form.useForm();
@@ -48,9 +50,10 @@ const ConfigGroup: React.FC<ConfigGroupProps> = ({
form={form}
layout="vertical"
initialValues={configs}
size={isMobile ? "middle" : "large"}
>
{Object.keys(configs).map(key => (
<Row key={key} gutter={16} align="middle">
<Row key={key} gutter={isMobile ? [8, 8] : [16, 16]} align="middle">
<Col xs={24} lg={16}>
<Form.Item
name={key}
@@ -72,12 +75,20 @@ const ConfigGroup: React.FC<ConfigGroupProps> = ({
)}
</Form.Item>
</Col>
<Col xs={24} lg={8} style={{ textAlign: 'right' }}>
<Col xs={24} lg={8} style={{
textAlign: isMobile ? 'left' : 'right',
marginTop: isMobile ? -10 : 0,
marginBottom: isMobile ? 10 : 0
}}>
<Button
type="primary"
icon={<SaveOutlined />}
onClick={() => handleSaveSingle(key)}
style={{ marginBottom: 24 }}
style={{
marginBottom: isMobile ? 16 : 24,
width: isMobile ? '100%' : 'auto'
}}
size={isMobile ? "middle" : "large"}
>
</Button>
@@ -89,8 +100,9 @@ const ConfigGroup: React.FC<ConfigGroupProps> = ({
<Button
type="primary"
onClick={handleSaveAll}
style={{ marginTop: 16 }}
style={{ marginTop: isMobile ? 8 : 16 }}
block
size={isMobile ? "middle" : "large"}
>
</Button>

View File

@@ -1,9 +1,10 @@
import { Tabs, Layout, Menu } from 'antd';
import { Tabs, Layout, Menu, Space } from 'antd';
import { useAuth } from '../../api/AuthContext';
import { UserRole } from '../../api/types';
import { useState, type SetStateAction } from 'react';
import SystemConfig from './SystemConfig.tsx';
import UserProfile from './UserProfile.tsx';
import useIsMobile from '../../hooks/useIsMobile';
import {
UserOutlined,
SettingOutlined,
@@ -16,6 +17,7 @@ const { Sider, Content } = Layout;
function Settings() {
const { hasRole } = useAuth();
const isMobile = useIsMobile();
const [activeMenu, setActiveMenu] = useState('profile');
const [activeTab, setActiveTab] = useState('basic');
@@ -106,7 +108,45 @@ function Settings() {
break;
}
};
// 手机版使用Tabs作为顶部导航
if (isMobile) {
return (
<div style={{ padding: 0 }}>
<Tabs
activeKey={activeMenu}
onChange={(key) => handleMenuChange(key)}
centered
size="large"
tabBarStyle={{
marginBottom: 16,
fontWeight: 500,
backgroundColor: '#f5f5f5',
padding: '8px 0',
borderRadius: '8px'
}}
>
{menuItems.map((item) => (
<TabPane
tab={
<Space size={4}>
{item?.icon}
<span>{item?.label}</span>
</Space>
}
key={item?.key || ''}
>
<div style={{ padding: '0 4px' }}>
{renderContent()}
</div>
</TabPane>
))}
</Tabs>
</div>
);
}
// 桌面版使用侧边栏
return (
<Layout style={{
background: '#fff',

View File

@@ -3,6 +3,7 @@ import { Tabs, Card, message, Spin, Select } from 'antd';
import { CloudOutlined, DatabaseOutlined } from '@ant-design/icons';
import { getAllConfigs, setConfig } from '../../api';
import ConfigGroup from './ConfigGroup.tsx';
import useIsMobile from '../../hooks/useIsMobile';
const { TabPane } = Tabs;
const { Option } = Select;
@@ -14,6 +15,7 @@ interface ConfigStructure {
}
const SystemConfig: React.FC = () => {
const isMobile = useIsMobile();
const [loading, setLoading] = useState(true);
const [configs, setConfigs] = useState<ConfigStructure>({});
const [activeKey, setActiveKey] = useState('AI');
@@ -92,13 +94,27 @@ const SystemConfig: React.FC = () => {
}, []);
return (
<Card title="系统配置" className="system-config-card">
<Card
title="系统配置"
className="system-config-card"
bodyStyle={{
padding: isMobile ? '12px 8px' : '24px'
}}
>
{loading ? (
<div style={{ textAlign: 'center', padding: '20px' }}>
<Spin tip="加载配置中..." />
</div>
) : (
<Tabs activeKey={activeKey} onChange={setActiveKey}>
<Tabs
activeKey={activeKey}
onChange={setActiveKey}
size={isMobile ? "small" : "middle"}
tabPosition={isMobile ? "top" : "left"}
style={{
minHeight: isMobile ? 'auto' : 400
}}
>
<TabPane tab="AI 设置" key="AI">
<ConfigGroup
groupName="AI"
@@ -115,6 +131,7 @@ const SystemConfig: React.FC = () => {
Model: 'AI 模型名称',
EmbeddingModel: '嵌入向量模型名称'
}}
isMobile={isMobile}
/>
</TabPane>
@@ -166,14 +183,28 @@ const SystemConfig: React.FC = () => {
</TabPane>
<TabPane tab="存储设置" key="Storage">
<div style={{ marginBottom: 20 }}>
<span style={{ marginRight: 8, display: 'inline-block', width: 100 }}>:</span>
<div style={{
marginBottom: isMobile ? 16 : 20,
display: 'flex',
flexDirection: isMobile ? 'column' : 'row',
alignItems: isMobile ? 'flex-start' : 'center',
gap: isMobile ? 8 : 0
}}>
<span style={{
marginRight: isMobile ? 0 : 8,
display: 'inline-block',
width: isMobile ? 'auto' : 100,
marginBottom: isMobile ? 4 : 0
}}>
:
</span>
<Select
value={configs.Storage?.DefaultStorage || 'Telegram'}
onChange={(value) => {
handleSaveConfig('Storage', 'DefaultStorage', value);
}}
style={{ width: 200 }}
style={{ width: isMobile ? '100%' : 200 }}
size={isMobile ? "middle" : "large"}
>
{storageOptions.map(option => (
<Option key={option.value} value={option.value}>
@@ -186,14 +217,28 @@ const SystemConfig: React.FC = () => {
</Select>
</div>
<div style={{ marginBottom: 20 }}>
<span style={{ marginRight: 8, display: 'inline-block', width: 100 }}>:</span>
<div style={{
marginBottom: isMobile ? 16 : 20,
display: 'flex',
flexDirection: isMobile ? 'column' : 'row',
alignItems: isMobile ? 'flex-start' : 'center',
gap: isMobile ? 8 : 0
}}>
<span style={{
marginRight: isMobile ? 0 : 8,
display: 'inline-block',
width: isMobile ? 'auto' : 100,
marginBottom: isMobile ? 4 : 0
}}>
:
</span>
<Select
value={storageType}
onChange={(value) => {
setStorageType(value);
}}
style={{ width: 200 }}
style={{ width: isMobile ? '100%' : 200 }}
size={isMobile ? "middle" : "large"}
>
{storageOptions.map(option => (
<Option key={option.value} value={option.value}>
@@ -218,6 +263,7 @@ const SystemConfig: React.FC = () => {
"TelegramStorageBotToken": 'Telegram 机器人令牌',
"TelegramStorageChatId": 'Telegram 聊天ID'
}}
isMobile={isMobile}
/>
)}
</TabPane>

View File

@@ -2,24 +2,44 @@ import React from 'react';
import { Card, Form, Input, Button } from 'antd';
import { useAuth } from '../../api/AuthContext';
import UserAvatar from '../../components/UserAvatar';
import useIsMobile from '../../hooks/useIsMobile';
const UserProfile: React.FC = () => {
const { user } = useAuth();
const isMobile = useIsMobile();
return (
<Card title="个人资料" style={{ maxWidth: 600 }}>
<div style={{ display: 'flex', justifyContent: 'center', marginBottom: 24 }}>
<Card
title="个人资料"
style={{
maxWidth: '100%',
margin: isMobile ? '0 auto' : '0 auto',
boxShadow: isMobile ? 'none' : '0 1px 3px rgba(0,0,0,0.1)'
}}
bodyStyle={{
padding: isMobile ? '16px 12px' : '24px'
}}
>
<div style={{
display: 'flex',
justifyContent: 'center',
marginBottom: isMobile ? 16 : 24
}}>
<UserAvatar
size={100}
size={isMobile ? 80 : 100}
email={user?.email}
text={user?.userName}
/>
</div>
<Form layout="vertical" initialValues={{
username: user?.userName || '',
email: user?.email || '',
}}>
<Form
layout="vertical"
initialValues={{
username: user?.userName || '',
email: user?.email || '',
}}
size={isMobile ? "middle" : "large"}
>
<Form.Item name="username" label="用户名">
<Input placeholder="用户名" />
</Form.Item>
@@ -37,7 +57,16 @@ const UserProfile: React.FC = () => {
</Form.Item>
<Form.Item>
<Button type="primary"></Button>
<Button
type="primary"
block={isMobile}
size={isMobile ? "middle" : "large"}
style={{
height: isMobile ? 40 : 'auto'
}}
>
</Button>
</Form.Item>
</Form>
</Card>