494 lines
12 KiB
Vue
494 lines
12 KiB
Vue
<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>
|