feat(modal): 添加居中模态框组件及游戏相关弹窗功能
- 新增 CenterModal 组件,支持标题、关闭按钮、背景图片等功能 - 添加键盘 ESC 键关闭模态框和页面滚动锁定功能 - 创建桌面端登录、注册和用户信息三个业务模态框 - 集成 lottie-web 动画库并创建 LottiePlayer 组件 - 在样式文件中添加模态框相关的 CSS 类和输入框样式 - 更新桌面入口文件集成登录和用户信息模态框 - 调整桌面控制组件间距和样式配置
This commit is contained in:
@@ -63,7 +63,7 @@ export function DesktopControl() {
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
'flex h-design-100 w-full items-center gap-design-16 overflow-hidden'
|
||||
'flex h-design-100 w-full items-center gap-design-12 overflow-hidden'
|
||||
}
|
||||
>
|
||||
<div
|
||||
|
||||
@@ -3,6 +3,9 @@ import { DesktopAnimal } from '@/features/game/components/desktop/desktop-animal
|
||||
import { DesktopControl } from '@/features/game/components/desktop/desktop-control.tsx'
|
||||
import { DesktopGameHistory } from '@/features/game/components/desktop/desktop-game-history.tsx'
|
||||
import { DesktopStatusLine } from '@/features/game/components/desktop/desktop-status.tsx'
|
||||
import DesktopLoginModal from '@/features/game/modal/desktop/desktop-login-modal.tsx'
|
||||
import DesktopRegisterModal from '@/features/game/modal/desktop/desktop-register-modal.tsx'
|
||||
import DesktopUserInfoModal from '@/features/game/modal/desktop/desktop-userInfo-modal.tsx'
|
||||
|
||||
export function PcEntry() {
|
||||
return (
|
||||
@@ -36,6 +39,12 @@ export function PcEntry() {
|
||||
>
|
||||
<DesktopControl />
|
||||
</div>
|
||||
{/*登录弹窗*/}
|
||||
<DesktopLoginModal />
|
||||
{/*注册弹窗 */}
|
||||
{/*<DesktopRegisterModal />*/}
|
||||
{/* 用户信息弹窗 */}
|
||||
<DesktopUserInfoModal />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
101
src/features/game/modal/desktop/desktop-login-modal.tsx
Normal file
101
src/features/game/modal/desktop/desktop-login-modal.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
import { motion } from 'motion/react'
|
||||
import { useState } from 'react'
|
||||
import loginBg from '@/assets/system/login-bg.webp'
|
||||
import rightImg from '@/assets/system/right.webp'
|
||||
import { CenterModal } from '@/components/center-modal.tsx'
|
||||
import { SmartImage } from '@/components/smart-image.tsx'
|
||||
|
||||
function DesktopLoginModal() {
|
||||
const [open, setOpen] = useState(false)
|
||||
|
||||
function handleSubmit() {
|
||||
setOpen(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<CenterModal
|
||||
open={open}
|
||||
onClose={() => {}}
|
||||
title={<div className={'modal-title-glow'}>登录</div>}
|
||||
titleAlign="center"
|
||||
className={'w-design-980 h-design-540'}
|
||||
>
|
||||
<div
|
||||
className={
|
||||
'flex flex-col items-center justify-between gap-design-20 px-design-20'
|
||||
}
|
||||
>
|
||||
<div
|
||||
className={
|
||||
'h-design-375 flex flex-col gap-design-45 w-full bg-[#060B0F]/50 p-design-50'
|
||||
}
|
||||
>
|
||||
<div className={'flex items-center'}>
|
||||
<div
|
||||
className={
|
||||
'w-design-160 shrink-0 text-left text-design-24 text-[#58ADAF]'
|
||||
}
|
||||
>
|
||||
Akun/TEL:
|
||||
</div>
|
||||
<input
|
||||
className={'flex-1 text-left'}
|
||||
placeholder={'Silakan masukkan akun atau nomor ponsel Anda.'}
|
||||
/>
|
||||
</div>
|
||||
<div className={'flex items-center'}>
|
||||
<div
|
||||
className={
|
||||
'w-design-160 shrink-0 text-left text-design-24 text-[#58ADAF]'
|
||||
}
|
||||
>
|
||||
Kata Sandi:
|
||||
</div>
|
||||
<input
|
||||
className={'flex-1 text-left'}
|
||||
placeholder={'Masukkan Kata Sandi'}
|
||||
/>
|
||||
</div>
|
||||
<div className={'flex items-center justify-around'}>
|
||||
<div className={'flex items-center gap-design-10'}>
|
||||
<div
|
||||
className={
|
||||
'flex items-center justify-center bg-[#040B0F] border border-[#549195] rounded-md w-design-38 h-design-38'
|
||||
}
|
||||
>
|
||||
<SmartImage alt={'right'} src={rightImg} />
|
||||
</div>
|
||||
<div className={'text-[#549195]'}>Daftar Akun</div>
|
||||
</div>
|
||||
<div className={'flex items-center gap-design-10'}>
|
||||
<div
|
||||
className={
|
||||
'flex items-center justify-center bg-[#040B0F] border border-[#549195] rounded-md w-design-38 h-design-38'
|
||||
}
|
||||
>
|
||||
<SmartImage alt={'right'} src={rightImg} />
|
||||
</div>
|
||||
<div className={'text-[#549195]'}>Ingat Kata Sandi</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<motion.div
|
||||
onClick={handleSubmit}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
style={{
|
||||
backgroundImage: `url(${loginBg})`,
|
||||
backgroundSize: '100% 100%',
|
||||
}}
|
||||
className={
|
||||
'w-design-390 h-design-110 flex items-center justify-center text-design-32 modal-title-glow font-bold cursor-pointer'
|
||||
}
|
||||
>
|
||||
MASUK
|
||||
</motion.div>
|
||||
</div>
|
||||
</CenterModal>
|
||||
)
|
||||
}
|
||||
|
||||
export default DesktopLoginModal
|
||||
125
src/features/game/modal/desktop/desktop-register-modal.tsx
Normal file
125
src/features/game/modal/desktop/desktop-register-modal.tsx
Normal file
@@ -0,0 +1,125 @@
|
||||
import { motion } from 'motion/react'
|
||||
import { useState } from 'react'
|
||||
import loginBg from '@/assets/system/login-bg.webp'
|
||||
import rightImg from '@/assets/system/right.webp'
|
||||
import { CenterModal } from '@/components/center-modal.tsx'
|
||||
import { SmartImage } from '@/components/smart-image.tsx'
|
||||
|
||||
function DesktopRegisterModal() {
|
||||
const [open, setOpen] = useState(true)
|
||||
|
||||
function handleSubmit() {
|
||||
setOpen(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<CenterModal
|
||||
open={open}
|
||||
onClose={() => {}}
|
||||
title={<div className={'modal-title-glow'}>注册</div>}
|
||||
titleAlign="center"
|
||||
className={'w-design-980 h-design-740'}
|
||||
>
|
||||
<div
|
||||
className={'flex flex-col items-center justify-between px-design-20'}
|
||||
>
|
||||
<div
|
||||
className={
|
||||
'h-design-490 flex flex-col gap-design-30 w-full bg-[#060B0F]/50 p-design-50'
|
||||
}
|
||||
>
|
||||
<div className={'flex items-center'}>
|
||||
<div
|
||||
className={
|
||||
'w-design-160 shrink-0 text-left text-design-24 text-[#58ADAF]'
|
||||
}
|
||||
>
|
||||
Akun/TEL:
|
||||
</div>
|
||||
<input
|
||||
className={'flex-1 text-left'}
|
||||
placeholder={'Silakan masukkan akun atau nomor ponsel Anda.'}
|
||||
/>
|
||||
</div>
|
||||
<div className={'flex items-center'}>
|
||||
<div
|
||||
className={
|
||||
'w-design-160 shrink-0 text-left text-design-24 text-[#58ADAF]'
|
||||
}
|
||||
>
|
||||
Kata Sandi:
|
||||
</div>
|
||||
<input
|
||||
className={'flex-1 text-left'}
|
||||
placeholder={'Masukkan Kata Sandi'}
|
||||
/>
|
||||
</div>
|
||||
<div className={'flex items-center'}>
|
||||
<div
|
||||
className={
|
||||
'w-design-160 shrink-0 text-left text-design-24 text-[#58ADAF]'
|
||||
}
|
||||
>
|
||||
Kata Sandi:
|
||||
</div>
|
||||
<input
|
||||
className={'flex-1 text-left'}
|
||||
placeholder={'Masukkan Kata Sandi'}
|
||||
/>
|
||||
</div>
|
||||
<div className={'flex items-center'}>
|
||||
<div
|
||||
className={
|
||||
'w-design-160 shrink-0 text-left text-design-24 text-[#58ADAF]'
|
||||
}
|
||||
>
|
||||
Kata Sandi:
|
||||
</div>
|
||||
<input
|
||||
className={'flex-1 text-left'}
|
||||
placeholder={'Masukkan Kata Sandi'}
|
||||
/>
|
||||
</div>
|
||||
<div className={'flex items-center justify-around'}>
|
||||
<div className={'flex items-center gap-design-10'}>
|
||||
<div
|
||||
className={
|
||||
'flex items-center justify-center bg-[#040B0F] border border-[#549195] rounded-md w-design-38 h-design-38'
|
||||
}
|
||||
>
|
||||
<SmartImage alt={'right'} src={rightImg} />
|
||||
</div>
|
||||
<div className={'text-[#549195]'}>Daftar Akun</div>
|
||||
</div>
|
||||
<div className={'flex items-center gap-design-10'}>
|
||||
<div
|
||||
className={
|
||||
'flex items-center justify-center bg-[#040B0F] border border-[#549195] rounded-md w-design-38 h-design-38'
|
||||
}
|
||||
>
|
||||
<SmartImage alt={'right'} src={rightImg} />
|
||||
</div>
|
||||
<div className={'text-[#549195]'}>Ingat Kata Sandi</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<motion.div
|
||||
onClick={handleSubmit}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
style={{
|
||||
backgroundImage: `url(${loginBg})`,
|
||||
backgroundSize: '100% 100%',
|
||||
}}
|
||||
className={
|
||||
'w-design-390 h-design-110 flex items-center justify-center text-design-32 modal-title-glow font-bold cursor-pointer'
|
||||
}
|
||||
>
|
||||
MASUK
|
||||
</motion.div>
|
||||
</div>
|
||||
</CenterModal>
|
||||
)
|
||||
}
|
||||
|
||||
export default DesktopRegisterModal
|
||||
136
src/features/game/modal/desktop/desktop-userInfo-modal.tsx
Normal file
136
src/features/game/modal/desktop/desktop-userInfo-modal.tsx
Normal file
@@ -0,0 +1,136 @@
|
||||
import { CircleUserRound, Mail } from 'lucide-react'
|
||||
import { useState } from 'react'
|
||||
import userInfoBg from '@/assets/system/userInfo-bg.webp'
|
||||
import { CenterModal } from '@/components/center-modal.tsx'
|
||||
import { cn } from '@/lib/untils'
|
||||
|
||||
type UserInfoTabKey = 'profile' | 'message'
|
||||
|
||||
const USER_INFO_TABS: Array<{
|
||||
key: UserInfoTabKey
|
||||
label: string
|
||||
icon: typeof CircleUserRound
|
||||
}> = [
|
||||
{
|
||||
key: 'profile',
|
||||
label: '个人信息',
|
||||
icon: CircleUserRound,
|
||||
},
|
||||
{
|
||||
key: 'message',
|
||||
label: '站内消息',
|
||||
icon: Mail,
|
||||
},
|
||||
]
|
||||
|
||||
function DesktopUserInfoModal() {
|
||||
const [open, setOpen] = useState(true)
|
||||
const [activeTab, setActiveTab] = useState<UserInfoTabKey>('profile')
|
||||
|
||||
function handleSubmit() {
|
||||
setOpen(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<CenterModal
|
||||
open={open}
|
||||
onClose={handleSubmit}
|
||||
title={
|
||||
<div className={'modal-title-glow text-design-26'}>Biomond Balance</div>
|
||||
}
|
||||
isNormalBg={true}
|
||||
titleAlign="left"
|
||||
className={'w-design-980 h-design-590'}
|
||||
>
|
||||
<div className={'relative flex h-[96%] w-full'}>
|
||||
<div className={'relative w-design-230 shrink-0'}>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="absolute right-0 top-0 h-full w-[calc(var(--design-unit)*2)] bg-[linear-gradient(180deg,rgba(68,244,255,0)_0%,rgba(68,244,255,0.55)_12%,rgba(130,255,255,0.95)_50%,rgba(68,244,255,0.55)_88%,rgba(68,244,255,0)_100%)] shadow-[0_0_calc(var(--design-unit)*8)_rgba(49,208,255,0.45)]"
|
||||
/>
|
||||
|
||||
{USER_INFO_TABS.map((tab) => {
|
||||
const Icon = tab.icon
|
||||
const isActive = tab.key === activeTab
|
||||
|
||||
return (
|
||||
<button
|
||||
key={tab.key}
|
||||
type="button"
|
||||
onClick={() => setActiveTab(tab.key)}
|
||||
className={cn(
|
||||
'relative flex h-design-150 w-full flex-col items-center justify-center gap-design-10 overflow-hidden transition',
|
||||
isActive
|
||||
? 'text-[#FEEEB0]'
|
||||
: 'text-[#58ADAF] hover:text-[#BFEAEC]',
|
||||
)}
|
||||
>
|
||||
{isActive ? (
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="absolute inset-y-0 right-0 w-full bg-[linear-gradient(to_left,rgba(254,238,176,0.46)_0%,rgba(254,238,176,0.28)_42%,rgba(254,238,176,0.12)_68%,rgba(254,238,176,0)_100%)]"
|
||||
/>
|
||||
) : null}
|
||||
{isActive ? (
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="absolute right-0 top-1/2 h-[72%] w-[calc(var(--design-unit)*3)] -translate-y-1/2 rounded-l-full bg-[linear-gradient(180deg,rgba(255,248,214,0.96)_0%,rgba(254,238,176,0.92)_48%,rgba(232,188,112,0.88)_100%)] shadow-[-2px_0_calc(var(--design-unit)*8)_rgba(254,238,176,0.36)]"
|
||||
/>
|
||||
) : null}
|
||||
|
||||
<Icon
|
||||
size={60}
|
||||
className={cn(
|
||||
'relative z-10 transition',
|
||||
isActive &&
|
||||
'drop-shadow-[0_0_calc(var(--design-unit)*8)_rgba(254,238,176,0.5)]',
|
||||
)}
|
||||
/>
|
||||
<div
|
||||
className={cn(
|
||||
'relative z-10 text-design-24',
|
||||
isActive && 'modal-title-gold-glow',
|
||||
)}
|
||||
>
|
||||
{tab.label}
|
||||
</div>
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className={'flex-1'}>
|
||||
<div
|
||||
className={
|
||||
'flex h-full w-full items-start justify-start bg-top bg-no-repeat px-design-40 py-design-32'
|
||||
}
|
||||
style={{
|
||||
backgroundImage: `url(${userInfoBg})`,
|
||||
backgroundSize: '120% 100%',
|
||||
}}
|
||||
>
|
||||
{activeTab === 'profile' ? (
|
||||
<div className="space-y-3 text-design-22 text-[#D7FAFF]">
|
||||
<div className="modal-title-gold-glow text-design-28">
|
||||
个人信息
|
||||
</div>
|
||||
<div>UID: 10009231</div>
|
||||
<div>账户等级: VIP 3</div>
|
||||
<div>绑定手机: 138****8899</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-3 text-design-22 text-[#D7FAFF]">
|
||||
<div className="modal-title-gold-glow text-design-28">
|
||||
站内消息
|
||||
</div>
|
||||
<div>您当前没有新的站内消息。</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CenterModal>
|
||||
)
|
||||
}
|
||||
|
||||
export default DesktopUserInfoModal
|
||||
Reference in New Issue
Block a user