diff --git a/src/assets/images/mobile_version_background/banner_bg.png b/src/assets/images/mobile_version_background/banner_bg.png new file mode 100644 index 0000000..f13d735 Binary files /dev/null and b/src/assets/images/mobile_version_background/banner_bg.png differ diff --git a/src/lang/en.ts b/src/lang/en.ts index 049c590..602a998 100644 --- a/src/lang/en.ts +++ b/src/lang/en.ts @@ -220,6 +220,12 @@ export default { checkYourEmail: 'Check your email', enterSixDigitCode: 'Enter the 6-digit code sent to', verify: 'Verify', + verifyCode: 'Verify Code', + verifyPlaceholder: 'enter 6-digital code', + stepTabVerify: 'Verify', + stepTabProfile: 'Profile', + stepTabDesign: 'Design Material', + stepTabTerms: 'Terms', resendCode: 'Resend', resendCodeIn: 'Resend Code in', // 验证消息 @@ -251,6 +257,9 @@ export default { uploadVideoOnly: 'Please upload a MP4 file only.', fileSizeExceeds: 'File size exceeds {sizeLimit} limit. Please upload a smaller file.', videoDurationExceeds: 'Video duration exceeds 60 seconds limit. Please upload a shorter video.', - uploadFailed: 'Upload failed' + uploadFailed: 'Upload failed', + nextStep: 'Next Step', + stepTips: 'Please complete this form in one sitting.', + backToIntroduction: 'Back to Introduction' } } diff --git a/src/lang/zh-cn.ts b/src/lang/zh-cn.ts index 6a4430a..48d297c 100644 --- a/src/lang/zh-cn.ts +++ b/src/lang/zh-cn.ts @@ -7,7 +7,7 @@ export default { contactDesc: '无论是报名资格、参赛细则、评审标准,还是其他比赛相关问题,欢迎通过以下邮箱联络我们:', sendEmail: '发送邮件', - copyMail:'已成功复制到剪贴板', + copyMail: '已成功复制到剪贴板', sendEmailFailed: '无法打开邮件客户端,我们已将邮箱地址复制到您的剪贴板。', applicationDeadline: '申请期限:\n2026年7月15日', howToApply: '申请方法', @@ -209,6 +209,12 @@ export default { checkYourEmail: '请查看您的邮箱', enterSixDigitCode: '请输入发送到邮箱的 6 位验证码', verify: '验证', + verifyCode: '验证码', + verifyPlaceholder: '输入6位数字的验证码', + stepTabVerify: '验证', + stepTabProfile: '资料', + stepTabDesign: '设计材料', + stepTabTerms: '条款', resendCode: '重新发送', resendCodeIn: '重新发送', // 验证消息 @@ -240,6 +246,9 @@ export default { uploadVideoOnly: '请仅上传 MP4 文件。', fileSizeExceeds: '文件大小超过 {sizeLimit} 限制。请上传较小的文件。', videoDurationExceeds: '视频时长不可超过60秒', - uploadFailed: '上传失败' + uploadFailed: '上传失败', + nextStep: '下一步', + stepTips: '请一次性完成这个表单。', + backToIntroduction: '返回赛事介绍' } } diff --git a/src/utils/isMobile.ts b/src/utils/isMobile.ts index 190d9d4..cf3a77e 100644 --- a/src/utils/isMobile.ts +++ b/src/utils/isMobile.ts @@ -6,25 +6,22 @@ export const useIsMobile = () => { let resizeTimer: ReturnType | null = null const checkDevice = () => { - // 使用防抖避免频繁触发 if (resizeTimer) { clearTimeout(resizeTimer) } resizeTimer = setTimeout(() => { - // 1. 现代 Client Hints API(Chrome/Edge 最准) - // if (navigator.userAgentData?.mobile !== undefined) { - // isMobile.value = navigator.userAgentData.mobile - // console.log('使用 userAgentData:', isMobile.value) - // } - // 2. 综合判断(兼容所有浏览器) const ua = navigator.userAgent.toLowerCase() - const mobileRegex = /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i + const mobileRegex = /android|webos|iphone|ipod|blackberry|iemobile|opera mini/i + const tabletRegex = /ipad|tablet|playbook|silk/i const hasTouch = 'ontouchstart' in window || navigator.maxTouchPoints > 1 - const smallScreen = window.innerWidth <= 1200 // 你可以改成 1024 等 + const smallScreen = window.innerWidth <= 768 + const tabletScreen = window.innerWidth > 768 && window.innerWidth <= 1200 - const uaCheck = mobileRegex.test(ua) - isMobile.value = uaCheck || smallScreen + const uaMobile = mobileRegex.test(ua) + const uaTablet = tabletRegex.test(ua) + + isMobile.value = (uaMobile && !uaTablet) || smallScreen }, 100) } @@ -35,7 +32,7 @@ export const useIsMobile = () => { onMounted(() => { checkDevice() window.addEventListener('resize', handleResize) - window.addEventListener('orientationchange', checkDevice) // 手机旋转必备 + window.addEventListener('orientationchange', checkDevice) }) onUnmounted(() => { @@ -46,10 +43,55 @@ export const useIsMobile = () => { } }) - // 处理 keep-alive 缓存的组件重新激活场景 onActivated(() => { checkDevice() }) return { isMobile } } + +export const useIsTablet = () => { + const isTablet = ref(false) + + let resizeTimer: ReturnType | null = null + + const checkDevice = () => { + if (resizeTimer) { + clearTimeout(resizeTimer) + } + resizeTimer = setTimeout(() => { + const ua = navigator.userAgent.toLowerCase() + const tabletRegex = /ipad|tablet|playbook|silk/i + const hasTouch = 'ontouchstart' in window || navigator.maxTouchPoints > 0 + const tabletScreen = window.innerWidth >= 769 && window.innerWidth <= 1200 + + const uaTablet = tabletRegex.test(ua) + + isTablet.value = (uaTablet && tabletScreen) || (hasTouch && tabletScreen) + }, 100) + } + + const handleResize = () => { + checkDevice() + } + + onMounted(() => { + checkDevice() + window.addEventListener('resize', handleResize) + window.addEventListener('orientationchange', checkDevice) + }) + + onUnmounted(() => { + window.removeEventListener('resize', handleResize) + window.removeEventListener('orientationchange', checkDevice) + if (resizeTimer) { + clearTimeout(resizeTimer) + } + }) + + onActivated(() => { + checkDevice() + }) + + return { isTablet } +} diff --git a/src/views/AwardPage/components/Step.vue b/src/views/AwardPage/components/Step.vue new file mode 100644 index 0000000..5ef1e86 --- /dev/null +++ b/src/views/AwardPage/components/Step.vue @@ -0,0 +1,162 @@ + + + + + diff --git a/src/views/AwardPage/container.vue b/src/views/AwardPage/container.vue index 73f5574..56716ce 100644 --- a/src/views/AwardPage/container.vue +++ b/src/views/AwardPage/container.vue @@ -132,7 +132,12 @@ type BtnType = 'index' | 'form' const btnType = ref('index') const btnText = computed(() => { if (isMobile.value) { - return t('AwardsPage.submitMobile') + if (btnType.value === 'index') { + return t('AwardsPage.submitMobile') + } + if (btnType.value === 'form') { + return locale.value === 'CHINESE_SIMPLIFIED' ? '赛事介绍' : 'Back' + } } else { if (btnType.value === 'index') { return t('AwardsPage.submitApplication') @@ -262,6 +267,9 @@ const handleBtnClick = () => {