feat(auth): 切换注册方式为手机验证码并添加客服功能

- 将注册表单从用户名改为手机号输入
- 集成短信验证码功能,添加验证码输入字段
- 实现发送短信验证码的API调用和倒计时逻辑
- 更新国际化配置以支持验证码相关文案
- 添加桌面端客服聊天弹窗功能
- 调整注册表单UI布局和样式优化
- 修改认证相关常量和类型定义以适配新流程
This commit is contained in:
JiaJun
2026-06-02 11:09:24 +08:00
parent 522b8a1f28
commit 68cf8c0be2
16 changed files with 410 additions and 72 deletions

View File

@@ -8,9 +8,11 @@ import {
Volume2,
VolumeX,
} from 'lucide-react'
import { motion } from 'motion/react'
import { useTranslation } from 'react-i18next'
import add from '@/assets/game/add.webp'
import avatar from '@/assets/system/avatar.webp'
import chatImage from '@/assets/system/chat.webp'
import diamond from '@/assets/system/diamond.webp'
import logo from '@/assets/system/logo.webp'
import { SmartImage } from '@/components/smart-image.tsx'
@@ -18,6 +20,7 @@ import {
useHeaderClockLabel,
useHeaderVm,
} from '@/features/game/hooks/use-header-vm'
import { useModalStore } from '@/store'
function HeaderClock() {
const systemTimeLabel = useHeaderClockLabel()
@@ -59,6 +62,7 @@ function SignalBars({
export function DesktopHeader() {
const { t } = useTranslation()
const setModalOpen = useModalStore((state) => state.setModalOpen)
const {
authStatus,
currentLanguageLabel,
@@ -173,6 +177,21 @@ export function DesktopHeader() {
)}
<div>{t('gameDesktop.header.fullscreen')}</div>
</button>
<motion.button
type="button"
onClick={() => setModalOpen('desktopSupport', true)}
whileTap={{
scale: 0.95,
}}
whileHover={{ scale: 1.05 }}
>
<SmartImage
className={'h-design-30 w-design-30 cursor-pointer'}
alt={'chatImage'}
src={chatImage}
/>
</motion.button>
</div>
{authStatus === 'authenticated' ? (

View File

@@ -14,6 +14,7 @@ import { DesktopPeriodHistoryDrawer } from '@/features/game/modal/desktop/deskto
import DesktopProceduresModal from '@/features/game/modal/desktop/desktop-procedures-modal.tsx'
import DesktopRegisterModal from '@/features/game/modal/desktop/desktop-register-modal.tsx'
import DesktopRulesModal from '@/features/game/modal/desktop/desktop-rules-modal.tsx'
import DesktopSupportModal from '@/features/game/modal/desktop/desktop-support-modal.tsx'
import DesktopUserInfoModal from '@/features/game/modal/desktop/desktop-userInfo-modal.tsx'
import DesktopWithdrawTopupModal from '@/features/game/modal/desktop/desktop-withdraw-topup-modal.tsx'
import { useDocumentMetadata } from '@/lib/head/document-metadata'
@@ -42,6 +43,8 @@ function EntryModalHost() {
<DesktopProceduresModal />
{/* 桌面端充值/提现业务弹窗:承载具体的充值或提现内容 */}
<DesktopWithdrawTopupModal />
{/* 桌面端客服弹窗:承载在线客服 iframe */}
<DesktopSupportModal />
{/* 强制弹窗 */}
<EntryNoticeGateModal />
{/* 历史开奖信息弹窗 */}

View File

@@ -0,0 +1,75 @@
import { useCallback, useEffect, useRef, useState } from 'react'
import { CenterModal } from '@/components/center-modal.tsx'
import { DataLoadingIndicator } from '@/components/ui/data-loading-indicator'
import { useModalStore } from '@/store'
const SUPPORT_CHAT_URL =
'https://tawk.to/chat/6a1d23d9e29f411c2ce86772/1jq0t82lu'
const IFRAME_READY_DELAY_MS = 2_000
function DesktopSupportModal() {
const [isLoading, setIsLoading] = useState(true)
const readyTimerRef = useRef<number | null>(null)
const open = useModalStore((state) => state.modals.desktopSupport)
const setModalOpen = useModalStore((state) => state.setModalOpen)
const clearReadyTimer = useCallback(() => {
if (readyTimerRef.current === null) {
return
}
window.clearTimeout(readyTimerRef.current)
readyTimerRef.current = null
}, [])
const handleClose = () => {
setModalOpen('desktopSupport', false)
}
const handleLoaded = () => {
clearReadyTimer()
readyTimerRef.current = window.setTimeout(() => {
setIsLoading(false)
readyTimerRef.current = null
}, IFRAME_READY_DELAY_MS)
}
useEffect(() => {
if (open) {
clearReadyTimer()
setIsLoading(true)
}
return clearReadyTimer
}, [clearReadyTimer, open])
return (
<CenterModal
open={open}
isNormalBg={true}
onClose={handleClose}
titleAlign="left"
title={<div className="modal-title-glow text-design-30">线</div>}
className="h-design-760 w-design-980"
>
<div className="h-full px-design-24 pb-design-40 pt-design-10">
<div className="relative h-full overflow-hidden rounded-[calc(var(--design-unit)*14)] border border-[#2A6D73] bg-[linear-gradient(180deg,rgba(5,22,31,0.98),rgba(2,10,17,0.98))] shadow-[inset_0_0_calc(var(--design-unit)*22)_rgba(88,205,218,0.13),0_0_calc(var(--design-unit)*18)_rgba(31,156,174,0.14)]">
{isLoading ? (
<div className="absolute inset-0 z-10 flex items-center justify-center bg-[radial-gradient(circle_at_center,rgba(20,92,105,0.38),rgba(2,10,17,0.98)_58%)]">
<DataLoadingIndicator label="客服连线中" />
</div>
) : null}
<iframe
title="customer-service-chat"
src={SUPPORT_CHAT_URL}
onLoad={handleLoaded}
className="h-full w-full bg-[linear-gradient(180deg,#061923,#020A11)]"
allow="microphone; camera; clipboard-read; clipboard-write"
/>
</div>
</div>
</CenterModal>
)
}
export default DesktopSupportModal