| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502 |
- import React, { useEffect, useState } from 'react';
- import { Icon } from '@iconify/react';
- import mdiAccount from '@iconify-icons/mdi/account';
- import mdiBell from '@iconify-icons/mdi/bell';
- import mdiHeart from '@iconify-icons/mdi/heart';
- import mdiHome from '@iconify-icons/mdi/home';
- import mdiLoading from '@iconify-icons/mdi/loading';
- import mdiSettings from '@iconify-icons/mdi/settings';
- import Button from 'antd/es/button';
- import Card from 'antd/es/card';
- import Space from 'antd/es/space';
- import Typography from 'antd/es/typography';
- import { useTranslation } from 'react-i18next';
- import { useNavigate } from 'react-router-dom';
- import multiColorIcon from '@/assets/iconify/multi-color/logo.svg';
- import singleColorIcon from '@/assets/iconify/single-color/home.svg';
- import infoIcon from '@/assets/iconify/single-color/info.svg';
- import LanguageSwitch from '@/components/LanguageSwitch';
- import { reportEvent } from '@/firebase';
- import { dialogModel } from '@/models/dialogModel';
- import { userModel } from '@/models/userModel';
- import { fetchLogin } from '@/services/login';
- import { createLocalTools } from '@/utils/localUtils';
- const { Title } = Typography;
- const Home: React.FC = () => {
- const { t, i18n } = useTranslation();
- const navigate = useNavigate();
- const user = userModel.useModel();
- const { openDialog, closeDialog } = dialogModel.useModel();
- const [loading, setLoading] = useState(false);
- const [loginStatus, setLoginStatus] = useState<string>('');
- const [storageStatus, setStorageStatus] = useState<string>('');
- useEffect(() => {
- console.log('✅ home组件挂载:componentDidMount');
- reportEvent('homePage_show');
- return () => {
- console.log('❌ home组件卸载:componentWillUnmount');
- reportEvent('homePage_hide');
- };
- }, []);
- // 创建加密存储工具实例
- const encryptedLs = createLocalTools({
- encryptKey: true,
- encryptData: true,
- });
- // 创建明文存储工具实例
- const plainLs = createLocalTools({
- encryptKey: false,
- encryptData: false,
- });
- // 演示加密存储 - 添加数据
- const handleEncryptedStorageAdd = () => {
- encryptedLs.setLocal('encryptedData', { name: '加密数据', timestamp: Date.now() });
- setStorageStatus('加密数据添加成功');
- };
- // 演示加密存储 - 获取数据
- const handleEncryptedStorageGet = () => {
- const data = encryptedLs.getLocal<{ name: string; timestamp: number }>('encryptedData');
- setStorageStatus(`获取加密数据: ${JSON.stringify(data)}`);
- };
- // 演示加密存储 - 删除数据
- const handleEncryptedStorageRemove = () => {
- encryptedLs.removeLocal('encryptedData');
- setStorageStatus('加密数据删除成功');
- };
- // 演示明文存储 - 添加数据
- const handlePlainStorageAdd = () => {
- plainLs.setLocal('plainData', { name: '明文数据', timestamp: Date.now() });
- setStorageStatus('明文数据添加成功');
- };
- // 演示明文存储 - 获取数据
- const handlePlainStorageGet = () => {
- const data = plainLs.getLocal<{ name: string; timestamp: number }>('plainData');
- setStorageStatus(`获取明文数据: ${JSON.stringify(data)}`);
- };
- // 演示明文存储 - 删除数据
- const handlePlainStorageRemove = () => {
- plainLs.removeLocal('plainData');
- setStorageStatus('明文数据删除成功');
- };
- // 演示清除所有数据
- const handleStorageClear = () => {
- encryptedLs.clearLocal();
- plainLs.clearLocal();
- setStorageStatus('所有数据清除成功');
- };
- // 演示网络请求
- const handleLoginDemo = async () => {
- setLoading(true);
- try {
- const result = await fetchLogin({
- username: 'test',
- password: '123456',
- captchaId: 'test-captcha',
- captchaCode: '1234',
- });
- setLoginStatus('登录成功');
- console.log('登录结果:', result);
- } catch (error) {
- setLoginStatus('登录失败');
- console.error('登录错误:', error);
- } finally {
- setLoading(false);
- }
- };
- // 演示路由跳转
- const handleNavigation = (path: string) => {
- navigate(path);
- };
- // 切换语言
- const handleLanguageChange = (lang: string) => {
- i18n.changeLanguage(lang);
- };
- // 对话框演示 - 单个按钮
- const handleOpenSingleButtonDialog = () => {
- openDialog({
- icon: infoIcon,
- title: 'Payment Failure',
- content: 'Oops! Your transaction failed due to some errors, please try again.',
- buttons: [
- {
- label: 'OK',
- onClick: (_event, id) => {
- closeDialog(id);
- },
- },
- ],
- });
- };
- // 对话框演示 - 两个按钮
- const handleOpenTwoButtonDialog = () => {
- openDialog({
- icon: infoIcon,
- title: 'Payment verification',
- content:
- 'Orders are being verified, if there is no response for a long time, please contact customer service if you have any questions!',
- buttons: [
- {
- label: 'Cancel',
- variant: 'secondary',
- onClick: (_event, id) => {
- closeDialog(id);
- },
- },
- {
- label: 'Contact us',
- onClick: (_event, id) => {
- closeDialog(id);
- },
- },
- ],
- });
- };
- // 对话框演示 - 无图标
- const handleOpenNoIconDialog = () => {
- openDialog({
- title: 'Simple Dialog',
- content: 'This is a dialog without an icon.',
- buttons: [
- {
- label: 'Close',
- onClick: (_event, id) => {
- closeDialog(id);
- },
- },
- ],
- });
- };
- // 对话框演示 - 自定义内容
- const handleOpenCustomContentDialog = () => {
- openDialog({
- icon: infoIcon,
- title: (
- <span>
- Custom <strong>Title</strong>
- </span>
- ),
- content: (
- <div>
- <p>This dialog has custom ReactNode content.</p>
- <ul className="list-disc list-inside mt-2">
- <li>Feature 1</li>
- <li>Feature 2</li>
- <li>Feature 3</li>
- </ul>
- </div>
- ),
- buttons: [
- {
- label: 'Got it',
- onClick: (_event, id) => {
- closeDialog(id);
- },
- },
- ],
- });
- };
- // 对话框演示 - 禁止点击遮罩层关闭
- const handleOpenNonClosableDialog = () => {
- openDialog({
- icon: infoIcon,
- title: 'Important Notice',
- content: 'This dialog cannot be closed by clicking the mask. You must click the button to close it.',
- maskClosable: false,
- buttons: [
- {
- label: 'I Understand',
- onClick: (_event, id) => {
- closeDialog(id);
- },
- },
- ],
- });
- };
- // 对话框演示 - 嵌套对话框
- const handleOpenNestedDialog = () => {
- openDialog({
- icon: infoIcon,
- title: 'First Dialog',
- content: 'This is the first dialog. Click the button below to open a nested dialog.',
- buttons: [
- {
- label: 'Open Nested Dialog',
- onClick: (_event, id) => {
- openDialog({
- icon: infoIcon,
- title: 'Nested Dialog',
- content: 'This is a nested dialog opened from the first dialog. Notice how the z-index is automatically managed.',
- buttons: [
- {
- label: 'Close Nested',
- variant: 'secondary',
- onClick: (_event, nestedId) => {
- closeDialog(nestedId);
- },
- },
- {
- label: 'Close All',
- onClick: (_event, nestedId) => {
- closeDialog(nestedId);
- closeDialog(id);
- },
- },
- ],
- });
- },
- },
- {
- label: 'Close First',
- variant: 'secondary',
- onClick: (_event, id) => {
- closeDialog(id);
- },
- },
- ],
- });
- };
- return (
- <div className="max-w-[1000px] mx-auto p-4">
- <div className="flex justify-between items-center mb-6">
- <h1 className="text-3xl font-bold text-gray-900">{t('pages.home.title')}</h1>
- <LanguageSwitch />
- </div>
- {/* 多语言演示卡片 */}
- <Card className="mb-6">
- <Title level={3}>多语言演示</Title>
- <div className="space-y-4">
- <p className="text-gray-600">{t('pages.home.description')}</p>
- <Space>
- <Button onClick={() => handleLanguageChange('en-US')}>English</Button>
- <Button onClick={() => handleLanguageChange('fa-IR')}>فارسی</Button>
- </Space>
- <div className="space-y-2">
- <p className="text-gray-600">{t('pages.home.features.title')}</p>
- <ul className="list-disc list-inside space-y-1 text-gray-600">
- <li>{t('pages.home.features.antd')}</li>
- <li>{t('pages.home.features.tailwind')}</li>
- <li>{t('pages.home.features.i18n')}</li>
- </ul>
- </div>
- </div>
- </Card>
- {/* 用户信息卡片 */}
- <Card className="mb-6">
- <Title level={3}>用户信息</Title>
- <div className="space-y-4">
- <p className="text-gray-600">姓名:{user.name}</p>
- <p className="text-gray-600">年龄:{user.age}</p>
- <Space wrap>
- <Button onClick={() => user.updateName('张三')}>修改名字</Button>
- <Button onClick={() => user.updateAge(25)}>修改年龄</Button>
- <Button onClick={user.incrementAge}>年龄+1</Button>
- </Space>
- </div>
- </Card>
- {/* 功能演示卡片 */}
- <Card className="mb-6">
- <Title level={3}>功能演示</Title>
- <div className="space-y-4">
- <div>
- <Title level={4}>本地存储演示</Title>
- <div className="space-y-4">
- <div>
- <Title level={5}>加密存储</Title>
- <Space wrap>
- <Button onClick={handleEncryptedStorageAdd}>
- 添加加密数据
- </Button>
- <Button onClick={handleEncryptedStorageGet}>
- 获取加密数据
- </Button>
- <Button onClick={handleEncryptedStorageRemove}>
- 删除加密数据
- </Button>
- </Space>
- </div>
- <div>
- <Title level={5}>明文存储</Title>
- <Space wrap>
- <Button onClick={handlePlainStorageAdd}>添加明文数据</Button>
- <Button onClick={handlePlainStorageGet}>获取明文数据</Button>
- <Button onClick={handlePlainStorageRemove}>删除明文数据</Button>
- </Space>
- </div>
- <div>
- <Button danger onClick={handleStorageClear}>
- 清除所有数据
- </Button>
- </div>
- </div>
- {storageStatus && <p className="mt-2 text-gray-600">{storageStatus}</p>}
- </div>
- <div>
- <Title level={4}>网络请求演示</Title>
- <Space>
- <Button type="primary" onClick={handleLoginDemo} loading={loading}>
- 测试登录
- </Button>
- {loginStatus && <span className="text-gray-600">{loginStatus}</span>}
- </Space>
- </div>
- <div>
- <Title level={4}>路由跳转演示</Title>
- <Space>
- <Button onClick={() => handleNavigation('/route-demo')}>
- 路由示例
- </Button>
- </Space>
- </div>
- </div>
- </Card>
- {/* 图标演示卡片 */}
- <Card className="mb-6">
- <Title level={3}>图标演示</Title>
- <div className="space-y-6">
- <div>
- <Title level={4}>离线图标</Title>
- <Space wrap>
- <Button icon={<Icon icon={mdiHome} />}>首页</Button>
- <Button icon={<Icon icon={mdiAccount} />}>用户</Button>
- <Button icon={<Icon icon={mdiSettings} />}>设置</Button>
- <Button icon={<Icon icon={mdiBell} />}>通知</Button>
- <Button icon={<Icon icon={mdiHeart} />}>收藏</Button>
- </Space>
- </div>
- <div>
- <Title level={4}>在线图标</Title>
- <Space wrap>
- <Button icon={<Icon icon="ri:home-line" />}>首页</Button>
- <Button icon={<Icon icon="ri:user-line" />}>用户</Button>
- <Button icon={<Icon icon="ri:settings-line" />}>设置</Button>
- <Button icon={<Icon icon="ri:notification-line" />}>通知</Button>
- <Button icon={<Icon icon="ri:heart-line" />}>收藏</Button>
- </Space>
- </div>
- <div>
- <Title level={4}>自定义图标</Title>
- <Space>
- <Icon
- icon={singleColorIcon}
- className="w-[40px] h-[40px] text-red-500"
- />
- <Icon icon={multiColorIcon} className="w-[40px] h-[40px]" />
- </Space>
- </div>
- <div>
- <Title level={4}>动画图标</Title>
- <Space>
- <Icon icon={mdiLoading} className="animate-spin" />
- <Icon icon={mdiHeart} className="animate-bounce" />
- <Icon icon={mdiBell} className="animate-pulse" />
- </Space>
- </div>
- </div>
- </Card>
- {/* 样式演示卡片 */}
- <Card className="mb-6">
- <Title level={3}>样式演示</Title>
- <div className="space-y-4">
- <div>
- <Title level={4}>Tailwind CSS 样式</Title>
- <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
- <div className="bg-blue-500 text-white p-4 rounded-lg shadow-md">
- 响应式卡片 1
- </div>
- <div className="bg-green-500 text-white p-4 rounded-lg shadow-md">
- 响应式卡片 2
- </div>
- <div className="bg-purple-500 text-white p-4 rounded-lg shadow-md">
- 响应式卡片 3
- </div>
- </div>
- </div>
- <div>
- <Title level={4}>Ant Design 组件</Title>
- <Space wrap>
- <Button type="primary">主要按钮</Button>
- <Button>默认按钮</Button>
- <Button type="dashed">虚线按钮</Button>
- <Button type="link">链接按钮</Button>
- </Space>
- </div>
- </div>
- </Card>
- {/* 对话框演示卡片 */}
- <Card className="mb-6">
- <Title level={3}>对话框演示</Title>
- <div className="space-y-4">
- <div>
- <Title level={4}>Dialog 组件示例</Title>
- <Space wrap>
- <Button type="primary" onClick={handleOpenSingleButtonDialog}>
- 单个按钮对话框
- </Button>
- <Button type="primary" onClick={handleOpenTwoButtonDialog}>
- 两个按钮对话框
- </Button>
- <Button onClick={handleOpenNoIconDialog}>无图标对话框</Button>
- <Button onClick={handleOpenCustomContentDialog}>
- 自定义内容对话框
- </Button>
- <Button onClick={handleOpenNonClosableDialog}>
- 禁止遮罩关闭对话框
- </Button>
- <Button onClick={handleOpenNestedDialog}>嵌套对话框</Button>
- </Space>
- </div>
- <div>
- <Title level={5}>使用说明</Title>
- <ul className="list-disc list-inside space-y-1 text-gray-600">
- <li>通过 dialogModel.openDialog() 打开对话框</li>
- <li>openDialog 返回对话框 id,可用于后续关闭</li>
- <li>按钮的 onClick 接收 (event, dialogId) 两个参数</li>
- <li>默认情况下,点击遮罩层可以关闭对话框</li>
- <li>设置 maskClosable: false 可禁止点击遮罩层关闭</li>
- <li>支持嵌套对话框,z-index 自动管理</li>
- <li>支持图标、标题、内容的自定义</li>
- </ul>
- </div>
- </div>
- </Card>
- </div>
- );
- };
- export default Home;
|