forked from wangziqi/gongxue-base
style: align H5 auth entry with legacy UI
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useRouter } from '@tarojs/taro';
|
||||
import { Button, Input, Text, View } from '@tarojs/components';
|
||||
import { appEnv, ensureRuntimeConfigLoaded, type Portal } from '@/env';
|
||||
import { getTenantContext } from '@/services/api';
|
||||
import { loadCurrentUser, sendSmsCode, verifySmsCode } from '@/services/auth';
|
||||
import { landingPath, redirectAfterLogin } from '@/services/routeGuard';
|
||||
@@ -9,6 +10,8 @@ import '../student.css';
|
||||
export default function StudentLoginPage() {
|
||||
const router = useRouter();
|
||||
const tenant = getTenantContext();
|
||||
const [portal, setPortal] = useState<Portal>(appEnv.portal);
|
||||
const [runtimeReady, setRuntimeReady] = useState(false);
|
||||
const [phone, setPhone] = useState('');
|
||||
const [code, setCode] = useState('');
|
||||
const [debugCode, setDebugCode] = useState('');
|
||||
@@ -19,15 +22,54 @@ export default function StudentLoginPage() {
|
||||
const [verifying, setVerifying] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (router.params?.reason) {
|
||||
setReason(decodeURIComponent(router.params.reason));
|
||||
return;
|
||||
}
|
||||
loadCurrentUser()
|
||||
.then(() => redirectAfterLogin(router.params?.redirect || landingPath()))
|
||||
.catch(() => undefined);
|
||||
ensureRuntimeConfigLoaded()
|
||||
.then(() => {
|
||||
setPortal(appEnv.portal);
|
||||
setRuntimeReady(true);
|
||||
if (router.params?.reason) {
|
||||
setReason(decodeURIComponent(router.params.reason));
|
||||
return;
|
||||
}
|
||||
loadCurrentUser()
|
||||
.then(() => redirectAfterLogin(router.params?.redirect || landingPath()))
|
||||
.catch(() => undefined);
|
||||
})
|
||||
.catch(() => {
|
||||
setPortal(appEnv.portal);
|
||||
setRuntimeReady(true);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const isPlatformAdmin = portal === 'platform-admin';
|
||||
const isTenantAdmin = portal === 'tenant-admin';
|
||||
const isAdminPortal = isPlatformAdmin || isTenantAdmin;
|
||||
const loginCopy = isPlatformAdmin
|
||||
? {
|
||||
mark: '管',
|
||||
kicker: 'Platform Console',
|
||||
title: '平台后台登录',
|
||||
subtitle: '登录后管理租户、账务、公共题库和平台员工权限。',
|
||||
formTitle: '管理员手机号登录',
|
||||
formMeta: '短信验证码确认身份后,还会校验平台管理员权限。',
|
||||
}
|
||||
: isTenantAdmin
|
||||
? {
|
||||
mark: '题',
|
||||
kicker: 'Tenant Admin',
|
||||
title: '租户后台登录',
|
||||
subtitle: '登录后管理学生、题库内容、营销活动、财务和品牌设置。',
|
||||
formTitle: '后台手机号登录',
|
||||
formMeta: '短信验证码确认身份后,还会校验租户后台权限。',
|
||||
}
|
||||
: {
|
||||
mark: (tenant?.branding.shortName || tenant?.branding.brandName || '题').slice(0, 1),
|
||||
kicker: tenant?.branding.shortName || tenant?.branding.brandName || '题库系统',
|
||||
title: '欢迎回来',
|
||||
subtitle: '登录后继续刷题、查看错题和学习报告。',
|
||||
formTitle: '手机号登录',
|
||||
formMeta: '短信验证码将用于确认当前租户和账号身份。',
|
||||
};
|
||||
|
||||
async function handleSendCode() {
|
||||
setSending(true);
|
||||
setError('');
|
||||
@@ -58,19 +100,19 @@ export default function StudentLoginPage() {
|
||||
}
|
||||
|
||||
return (
|
||||
<View className='student-page login-page'>
|
||||
<View className={`student-page login-page ${isAdminPortal ? 'login-page-admin' : 'login-page-student'} ${runtimeReady ? 'runtime-ready' : ''}`}>
|
||||
<View className='login-hero'>
|
||||
<View className='login-avatar'>
|
||||
<Text className='login-avatar-mark'>{(tenant?.branding.shortName || tenant?.branding.brandName || '题').slice(0, 1)}</Text>
|
||||
<Text className='login-avatar-mark'>{loginCopy.mark}</Text>
|
||||
</View>
|
||||
<Text className='login-kicker'>{tenant?.branding.shortName || tenant?.branding.brandName || '题库系统'}</Text>
|
||||
<Text className='login-title'>欢迎回来</Text>
|
||||
<Text className='login-subtitle'>登录后继续刷题、查看错题和学习报告。</Text>
|
||||
<Text className='login-kicker'>{loginCopy.kicker}</Text>
|
||||
<Text className='login-title'>{loginCopy.title}</Text>
|
||||
<Text className='login-subtitle'>{loginCopy.subtitle}</Text>
|
||||
</View>
|
||||
|
||||
<View className='login-card list-stack'>
|
||||
<Text className='row-main'>手机号登录</Text>
|
||||
<Text className='row-meta'>短信验证码将用于确认当前租户和账号身份。</Text>
|
||||
<Text className='row-main'>{loginCopy.formTitle}</Text>
|
||||
<Text className='row-meta'>{loginCopy.formMeta}</Text>
|
||||
{reason ? <Text className='error-text'>{reason}</Text> : null}
|
||||
<Input className='input' type='number' maxlength={11} placeholder='请输入手机号' value={phone} onInput={event => setPhone(String(event.detail.value || ''))} />
|
||||
<View className='toolbar'>
|
||||
|
||||
@@ -114,6 +114,48 @@
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.login-page-admin {
|
||||
background:
|
||||
linear-gradient(to right, rgba(15, 23, 42, 0.035) 1px, transparent 1px),
|
||||
linear-gradient(to bottom, rgba(15, 23, 42, 0.035) 1px, transparent 1px),
|
||||
#f4f6f9;
|
||||
background-size: 40px 40px;
|
||||
}
|
||||
|
||||
.login-page-admin .login-hero {
|
||||
background: #111827;
|
||||
box-shadow: 0 16px 34px rgba(15, 23, 42, 0.18);
|
||||
}
|
||||
|
||||
.login-page-admin .login-hero::after {
|
||||
background: rgba(37, 99, 235, 0.26);
|
||||
}
|
||||
|
||||
.login-page-admin .login-avatar {
|
||||
border-color: rgba(255, 255, 255, 0.18);
|
||||
background: #1e293b;
|
||||
}
|
||||
|
||||
.login-page-admin .login-avatar-mark {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.login-page-admin .login-kicker {
|
||||
color: #93c5fd;
|
||||
}
|
||||
|
||||
.login-page-admin .login-card {
|
||||
border-color: #e5e7eb;
|
||||
}
|
||||
|
||||
.login-page-admin .login-card .row-main {
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
.login-page-admin .login-card .row-meta {
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.student-topbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -2026,6 +2068,71 @@
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.notifications-page .notification-row,
|
||||
.review-page .list-row,
|
||||
.video-page .list-row {
|
||||
border-left: 4px solid #1152d4;
|
||||
}
|
||||
|
||||
.notifications-page .notification-row:nth-child(2n),
|
||||
.review-page .list-row:nth-child(2n),
|
||||
.video-page .list-row:nth-child(2n) {
|
||||
border-left-color: #10b981;
|
||||
}
|
||||
|
||||
.notifications-page .notification-row:nth-child(3n),
|
||||
.review-page .list-row:nth-child(3n),
|
||||
.video-page .list-row:nth-child(3n) {
|
||||
border-left-color: #f59e0b;
|
||||
}
|
||||
|
||||
.checkout-page .quiet-panel,
|
||||
.reports-page .report-panel,
|
||||
.profile-page .profile-card,
|
||||
.vocabulary-overview-panel,
|
||||
.scoreline-filter-panel {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.checkout-page .quiet-panel::before,
|
||||
.reports-page .report-panel::before,
|
||||
.profile-page .profile-card::before,
|
||||
.vocabulary-overview-panel::before,
|
||||
.scoreline-filter-panel::before {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 56px;
|
||||
height: 4px;
|
||||
margin-bottom: 16px;
|
||||
border-radius: 999px;
|
||||
background: #1152d4;
|
||||
}
|
||||
|
||||
.assets-page .asset-preview-panel,
|
||||
.scoreline-page .scoreline-filter-panel,
|
||||
.vocabulary-page .vocabulary-card,
|
||||
.handbook-page .handbook-search-panel {
|
||||
border-top: 4px solid #1152d4;
|
||||
}
|
||||
|
||||
.video-page .video-frame {
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 1px 3px rgba(15, 23, 42, 0.08);
|
||||
}
|
||||
|
||||
.student-page .toolbar::-webkit-scrollbar,
|
||||
.scoreline-chip-row::-webkit-scrollbar,
|
||||
.handbook-outline::-webkit-scrollbar {
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
.student-page .toolbar::-webkit-scrollbar-thumb,
|
||||
.scoreline-chip-row::-webkit-scrollbar-thumb,
|
||||
.handbook-outline::-webkit-scrollbar-thumb {
|
||||
border-radius: 999px;
|
||||
background: #cbd5e1;
|
||||
}
|
||||
|
||||
@media (min-width: 900px) {
|
||||
.student-page {
|
||||
width: 100%;
|
||||
@@ -2068,6 +2175,10 @@
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.login-page-admin .login-hero {
|
||||
border-radius: 24px 0 0 24px;
|
||||
}
|
||||
|
||||
.login-card .input {
|
||||
height: 52px;
|
||||
font-size: 15px;
|
||||
|
||||
Reference in New Issue
Block a user