Files
gloabl_award_front/src/views/AwardPage/container.vue
2026-03-16 15:17:13 +08:00

494 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="award-container">
<div class="header-wrapper">
<div class="header flex align-center space-between">
<div class="header-left">
<img src="@/assets/images/award/code_create_logo.png" class="logo" />
</div>
<div class="header-right flex align-center">
<div class="contact flex align-center" @click="handleContactClick">
<img src="@/assets/images/award/mail.png" class="contact-icon" />
<div class="text" v-if="!isMobile">{{ $t('AwardsPage.contactUs') }}</div>
</div>
<div class="gap" />
<div class="language flex align-center">
<div
class="text"
:class="{ active: locale === 'CHINESE_SIMPLIFIED' }"
@click="handleChangeLanguage('CHINESE_SIMPLIFIED')"
>
中文
</div>
<span class="text">/</span>
<div
class="text"
:class="{ active: locale === 'ENGLISH' }"
@click="handleChangeLanguage('ENGLISH')"
>
EN
</div>
</div>
<div class="gap" />
<div class="submit flex align-center" @click="handleBtnClick">
<div class="text">{{ btnText }}</div>
<img src="@/assets/images/award/arrow.png" alt="" class="arrow" />
</div>
</div>
</div>
<div class="header-placeholder"></div>
</div>
<router-view />
<div class="footer flex space-between align-center">
<div class="social-list flex">
<a href="https://xhslink.com/m/5Ony2FapizV" target="_blank">
<img src="@/assets/images/award/xiaohongshu.svg" alt="" />
</a>
<a href="https://www.linkedin.com/company/code-create-limited" target="_blank">
<img src="@/assets/images/award/linkdin.svg" alt="" />
</a>
<a href="https://www.facebook.com/CodeCreateAI" target="_blank">
<img src="@/assets/images/award/facebook.svg" alt="" />
</a>
<a href="https://www.tiktok.com/@aida_codecreate" target="_blank">
<img src="@/assets/images/award/tiktok.svg" alt="" />
</a>
<a href="javascript:void(0)" @click="showQRcode = true">
<img src="@/assets/images/award/weichat.svg" alt="" />
</a>
<a href="https://www.instagram.com/aida_codecreate?igsh=MzRlODBiNWFlZA==" target="_blank">
<img src="@/assets/images/award/instagram.png" alt="" />
</a>
</div>
<div class="copyright">© Code-Create 2026</div>
</div>
<div class="qrcode-mask flex flex-center" v-if="showQRcode">
<div class="code-wrapper flex flex-col align-center">
<img src="@/assets/images/award/close.svg" class="close-icon" @click="handleCloseQRcode" />
<div class="code-title">{{ $t('AwardsPage.wechatTitle') }}</div>
<img src="@/assets/images/award/qrcode.jpg" class="qrcode" />
<div class="tips">{{ $t('AwardsPage.wechatDesc') }}</div>
</div>
</div>
</div>
<div class="contact-modal flex flex-center" v-if="showContactModal">
<div class="contact-modal-wrapper">
<img
src="@/assets/images/award/close.svg"
class="close-icon"
@click="showContactModal = false"
/>
<div class="header">
{{ $t('AwardsPage.contactHeader') }}
</div>
<div class="desc">
{{ $t('AwardsPage.contactDesc') }}
</div>
<div class="mail flex align-center space-between">
<div class="mail-address">awards2026@code-createcom.hk</div>
<img src="@/assets/images/award/copy.png" class="copy-icon" @click="handleClickCopyEmail" />
</div>
<div class="send-btn" @click="handleContactUs">
{{ $t('AwardsPage.sendEmail') }}
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { getCookie, setCookie } from '@/utils/cookie'
import { useMessage } from '@/components/Message/message'
import { useIsMobile } from '@/utils/isMobile'
const { isMobile } = useIsMobile()
const { success, error } = useMessage()
const route = useRoute()
const router = useRouter()
const { locale, t } = useI18n()
onMounted(() => {
// 初始化语言设置
const loginLanguage = localStorage.getItem('loginLanguage')
if (loginLanguage) {
locale.value = loginLanguage
} else {
const userLanguage = getCookie('language')
if (userLanguage) {
locale.value = userLanguage
}
}
})
const showQRcode = ref(false)
const handleCloseQRcode = () => {
showQRcode.value = false
}
type BtnType = 'index' | 'form'
const btnType = ref<BtnType>('index')
const btnText = computed(() => {
if (isMobile.value) {
return t('AwardsPage.submitMobile')
} else {
if (btnType.value === 'index') {
return t('AwardsPage.submitApplication')
}
if (btnType.value === 'form') {
return locale.value === 'CHINESE_SIMPLIFIED' ? '赛事介绍' : 'Back to Introduction'
}
}
})
watch(
() => route.path,
(val) => {
if (val.includes('contestants')) {
btnType.value = 'form'
} else {
btnType.value = 'index'
}
},
{
immediate: true
}
)
const showContactModal = ref(false)
const handleContactClick = () => {
showContactModal.value = true
}
const handleContactUs = () => {
const email = 'awards2026@code-createcom.hk'
const mailtoLink = `mailto:${email}`
// 检测是否有邮件客户端
let hasEmailClient = false
let blurTimer = null
// 监听窗口失去焦点事件(如果打开了邮件客户端,窗口会失去焦点)
const handleBlur = () => {
hasEmailClient = true
if (blurTimer) {
clearTimeout(blurTimer)
}
window.removeEventListener('blur', handleBlur)
}
window.addEventListener('blur', handleBlur)
// 尝试打开邮件客户端(使用临时链接元素,避免页面跳转)
try {
const tempLink = document.createElement('a')
tempLink.href = mailtoLink
tempLink.style.display = 'none'
document.body.appendChild(tempLink)
tempLink.click()
document.body.removeChild(tempLink)
} catch (e) {
// 如果打开失败,直接复制邮箱
hasEmailClient = false
}
// 设置超时检测如果500ms内窗口没有失去焦点说明没有邮件客户端
blurTimer = setTimeout(() => {
window.removeEventListener('blur', handleBlur)
if (!hasEmailClient) {
// 没有邮件客户端,复制邮箱到剪贴板
console.log('没有客户端')
copyToClipboard(email)
error(t('AwardsPage.sendEmailFailed'))
}
}, 2000)
}
const copyToClipboard = (text) => {
if (navigator.clipboard && window.isSecureContext) {
// 使用现代 Clipboard API
navigator.clipboard.writeText(text).catch(() => {
// 如果失败,使用传统方法
fallbackCopyToClipboard(text)
})
} else {
// 使用传统方法
fallbackCopyToClipboard(text)
}
}
const fallbackCopyToClipboard = (text) => {
const textArea = document.createElement('textarea')
textArea.value = text
textArea.style.position = 'fixed'
textArea.style.left = '-999999px'
textArea.style.top = '-999999px'
document.body.appendChild(textArea)
textArea.focus()
textArea.select()
try {
document.execCommand('copy')
} catch (err) {
console.error('复制失败:', err)
}
document.body.removeChild(textArea)
}
const handleClickCopyEmail = () => {
copyToClipboard('awards2026@code-createcom.hk')
success(t('AwardsPage.copyMail'))
}
const handleChangeLanguage = (language) => {
if (language === 'CHINESE_SIMPLIFIED') {
locale.value = 'CHINESE_SIMPLIFIED'
} else {
locale.value = 'ENGLISH'
}
localStorage.setItem('loginLanguage', language)
setCookie('language', language)
}
const handleBtnClick = () => {
const lang = route.params.lang ? `/${route.params.lang}` : ''
if (btnType.value === 'index') {
router.push(`${lang}/contestants`)
} else {
router.push(`${lang}/`)
}
}
</script>
<style lang="less" scoped>
.award-container {
overflow: auto;
height: 100vh;
// 隐藏滚动条箭头,只显示滚动条本体
box-sizing: border-box;
&::-webkit-scrollbar {
display: none;
width: 0;
height: 0;
}
scrollbar-width: none;
-ms-overflow-style: none;
}
.header-wrapper {
.header-placeholder {
height: 8rem;
}
.header {
height: 8rem;
background-color: #232323;
padding-left: 21.5rem;
padding-right: 21.4rem;
box-sizing: border-box;
position: fixed;
top: 0;
width: 100%;
z-index: 9;
.header-left {
.logo {
width: 13rem;
height: 5rem;
}
}
.header-right {
column-gap: 1.2rem;
color: #fff;
.gap {
width: 0.05rem;
height: 2.4rem;
background-color: #979797;
// border: 0.05rem solid #979797
}
.text {
font-size: 1.6rem;
}
.contact {
column-gap: 1rem;
cursor: pointer;
}
.language {
column-gap: 0.8rem;
padding: 0 1.25rem;
span.text {
user-select: none;
}
div.text {
cursor: pointer;
&.active {
color: #979797;
}
}
}
.submit {
cursor: pointer;
column-gap: 1rem;
.arrow {
width: 2.4rem;
height: 2.4rem;
}
}
}
}
}
.footer {
height: 10rem;
padding-left: 21.5rem;
box-sizing: border-box;
padding-right: 22rem;
background-color: #232323;
.social-list {
column-gap: 2rem;
img {
width: 2rem;
height: 2rem;
}
}
.copyright {
color: #fff;
font-family: 'Arial';
font-weight: 400;
font-size: 1.2rem;
}
}
.qrcode-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.45);
.code-wrapper {
width: 60rem;
height: 49.4rem;
background-color: #fff;
position: relative;
border-radius: 0.8rem;
padding-top: 6rem;
.close-icon {
width: 2.4rem;
height: 2.4rem;
position: absolute;
top: 2rem;
right: 2rem;
cursor: pointer;
}
.code-title {
font-family: 'PoppinsBold';
font-weight: 600;
font-size: 3rem;
color: #232323;
}
.qrcode {
width: 25.8rem;
height: 25.8rem;
margin: 3rem 0 1rem;
}
.tips {
font-family: Arial;
font-weight: 400;
font-size: 1.4rem;
color: #585858;
}
}
}
.contact-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.45);
z-index: 9;
.contact-modal-wrapper {
width: 60rem;
height: 49.4rem;
background-color: #fff;
border-radius: 0.8rem;
padding: 8.2rem 8.6rem;
position: relative;
.close-icon {
width: 2.4rem;
height: 2.4rem;
position: absolute;
top: 2rem;
right: 2rem;
cursor: pointer;
}
.header {
text-align: center;
font-family: 'PoppinsBold';
font-size: 3rem;
color: #232323;
margin-bottom: 2.2rem;
}
.desc {
text-align: center;
font-family: 'Arial';
font-weight: 400;
font-size: 1.6rem;
color: #585858;
white-space: pre-line;
line-height: 2rem;
margin-bottom: 4rem;
}
.mail {
height: 6rem;
line-height: 6rem;
background-color: #f6f6f4;
border: 0.2rem solid #e6e6e6;
border-radius: 0.8rem;
padding: 0 2rem 0 3rem;
font-family: 'ArialBold';
font-weight: 700;
margin-bottom: 5.3rem;
.copy-icon {
width: 2.4rem;
height: 2.4rem;
cursor: pointer;
}
}
.send-btn {
height: 4.2rem;
line-height: 4.2rem;
text-align: center;
color: #fff;
background-color: #232323;
border-radius: 0.8rem;
font-family: 'ArialBold';
font-weight: 700;
cursor: pointer;
}
}
}
@media screen and (max-width: 1200px) {
.header-wrapper {
.header {
padding-left: 6.6rem;
padding-right: 6.6rem;
.header-right {
column-gap: 2rem;
.contact-icon {
width: 3.4rem;
height: 2.6rem;
}
.language{
padding: 0 0.56rem;
}
}
}
}
.footer{
row-gap: 0.8rem;
flex-direction: column;
justify-content: center;
}
}
</style>