diff --git a/client/mobile/mobile_app.tsx b/client/mobile/mobile_app.tsx index a9fb809..1cb6824 100644 --- a/client/mobile/mobile_app.tsx +++ b/client/mobile/mobile_app.tsx @@ -16,6 +16,7 @@ import 'dayjs/locale/zh-cn'; import { AuthProvider, ThemeProvider, useAuth } from './hooks.tsx'; import HomePage from './pages_index.tsx'; import LoginPage from './pages_login.tsx'; +import RegisterPage from './pages_register.tsx'; import { GlobalConfig } from "../share/types.ts"; import { ExclamationTriangleIcon, HomeIcon, BellIcon, UserIcon } from '@heroicons/react/24/outline'; import { NotificationsPage } from './pages_messages.tsx'; @@ -254,6 +255,11 @@ const App = () => { element: , errorElement: }, + { + path: '/mobile/register', + element: , + errorElement: + }, { path: '/mobile', element: ( diff --git a/client/mobile/pages_login.tsx b/client/mobile/pages_login.tsx index ade9ac8..ba2c46a 100644 --- a/client/mobile/pages_login.tsx +++ b/client/mobile/pages_login.tsx @@ -146,7 +146,7 @@ const LoginPage: React.FC = () => { diff --git a/client/mobile/pages_register.tsx b/client/mobile/pages_register.tsx new file mode 100644 index 0000000..263310e --- /dev/null +++ b/client/mobile/pages_register.tsx @@ -0,0 +1,193 @@ +import React, { useState } from 'react'; +import { useNavigate } from 'react-router'; +import { ArrowRightIcon, EnvelopeIcon, LockClosedIcon, UserIcon } from '@heroicons/react/24/outline'; +import { AuthAPI } from './api.ts'; +import { handleApiError } from './utils.ts'; + +const RegisterPage: React.FC = () => { + const navigate = useNavigate(); + const [username, setUsername] = useState(''); + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [confirmPassword, setConfirmPassword] = useState(''); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + const handleRegister = async (e: React.FormEvent) => { + e.preventDefault(); + + // 表单验证 + if (!username.trim()) { + setError('用户名不能为空'); + return; + } + + if (!email.trim()) { + setError('邮箱不能为空'); + return; + } + + if (!password.trim()) { + setError('密码不能为空'); + return; + } + + if (password !== confirmPassword) { + setError('两次输入的密码不一致'); + return; + } + + setLoading(true); + setError(null); + + try { + await AuthAPI.register(username, email, password); + // 注册成功后跳转到登录页 + navigate('/mobile/login'); + } catch (err) { + setError(handleApiError(err)); + } finally { + setLoading(false); + } + }; + + return ( +
+ {/* 顶部Logo和标题 */} +
+
+ + + + + +
+

+ {window.CONFIG?.APP_NAME || '移动应用'} +

+

创建您的账户

+
+ + {/* 注册表单 */} +
+ {error && ( +
+ {error} +
+ )} + +
+
+ +
+
+ +
+ setUsername(e.target.value)} + className="w-full pl-10 pr-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500" + placeholder="请输入用户名" + /> +
+
+ +
+ +
+
+ +
+ setEmail(e.target.value)} + className="w-full pl-10 pr-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500" + placeholder="请输入邮箱" + /> +
+
+ +
+ +
+
+ +
+ setPassword(e.target.value)} + className="w-full pl-10 pr-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500" + placeholder="请输入密码" + /> +
+
+ +
+ +
+
+ +
+ setConfirmPassword(e.target.value)} + className="w-full pl-10 pr-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500" + placeholder="请再次输入密码" + /> +
+
+ + +
+ +
+ +
+
+ + {/* 底部文本 */} +
+ © {new Date().getFullYear()} {window.CONFIG?.APP_NAME || '移动应用'} +

保留所有权利

+
+
+ ); +}; + +export default RegisterPage; \ No newline at end of file diff --git a/test/pages_know_info.test.ts b/test/admin/know_info.spec.ts similarity index 100% rename from test/pages_know_info.test.ts rename to test/admin/know_info.spec.ts diff --git a/test/mobile/register.spec.ts b/test/mobile/register.spec.ts new file mode 100644 index 0000000..ab62d42 --- /dev/null +++ b/test/mobile/register.spec.ts @@ -0,0 +1,24 @@ + +import { test } from '@playwright/test'; +import { expect } from '@playwright/test'; + +test('移动端注册测试', async ({ page, context }) => { + + // Navigate to URL + await page.goto('https://pre-117-77-template.r.d8d.fun/mobile/register'); + + // Fill input field + await page.fill('#username', 'testuser'); + + // Fill input field + await page.fill('#email', 'testuser@example.com'); + + // Fill input field + await page.fill('#password', 'Test1234!'); + + // Fill input field + await page.fill('#confirmPassword', 'Test1234!'); + + // Click element + await page.click('button[type='submit']'); +}); \ No newline at end of file