Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
134 lines
3.0 KiB
Vue
134 lines
3.0 KiB
Vue
<script lang="ts" setup>
|
|
import { onMounted } from 'vue'
|
|
import { getStaticImage } from '@/utils'
|
|
import { ImgButton } from '@/components'
|
|
|
|
defineOptions({
|
|
name: 'CertificateDetailPopup',
|
|
})
|
|
|
|
defineProps<{
|
|
date: string // '2026-06-18' 颁发日期
|
|
certificateNumber: string // '001' 证书编号
|
|
studentNumber: string // '001' 学员数量
|
|
}>()
|
|
|
|
const visible = defineModel<boolean>({ default: false })
|
|
|
|
const emit = defineEmits<{
|
|
close: []
|
|
}>()
|
|
|
|
const certificateDetailSrc = getStaticImage('components/medal/证书详情')
|
|
|
|
onMounted(() => {
|
|
const img = new Image()
|
|
img.src = certificateDetailSrc
|
|
})
|
|
|
|
const handleClose = () => {
|
|
visible.value = false
|
|
emit('close')
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<Transition name="certificate-fade">
|
|
<div
|
|
v-if="visible"
|
|
class="absolute inset-0 z-[120] flex items-center justify-center bg-black/45"
|
|
@click.stop
|
|
>
|
|
<div class="certificate-detail relative text-2xl">
|
|
<img
|
|
draggable="false"
|
|
:src="certificateDetailSrc"
|
|
class="certificate-detail-img object-contain"
|
|
alt=""
|
|
/>
|
|
<ImgButton
|
|
class="absolute right-0 top-0 z-10"
|
|
:image="'components/close'"
|
|
@click="handleClose"
|
|
/>
|
|
|
|
<!-- 证书编号 -->
|
|
<span class="absolute bottom-[154px] left-[390px]">
|
|
{{ certificateNumber }}
|
|
</span>
|
|
<!-- 颁发日期 -->
|
|
<span class="absolute bottom-[122px] left-[390px]">{{ date }}</span>
|
|
<!-- 多少位学员 -->
|
|
<!-- <span class="absolute bottom-[468px] left-[948px] text-3xl">
|
|
{{ studentNumber }}
|
|
</span>
|
|
<span class="absolute bottom-[380px] left-[1070px]">
|
|
{{ studentNumber }}
|
|
</span> -->
|
|
</div>
|
|
</div>
|
|
</Transition>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.certificate-fade-enter-active {
|
|
transition: opacity 220ms ease-out;
|
|
}
|
|
|
|
.certificate-fade-leave-active {
|
|
transition: opacity 160ms ease-in;
|
|
}
|
|
|
|
.certificate-fade-enter-from,
|
|
.certificate-fade-leave-to {
|
|
opacity: 0;
|
|
}
|
|
|
|
.certificate-fade-enter-active .certificate-detail,
|
|
.certificate-fade-leave-active .certificate-detail {
|
|
transition:
|
|
opacity 220ms ease,
|
|
transform 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
|
|
}
|
|
|
|
.certificate-fade-enter-from .certificate-detail {
|
|
opacity: 0;
|
|
transform: translate3d(0, 36px, 0) scale(0.96);
|
|
}
|
|
|
|
.certificate-fade-enter-to .certificate-detail,
|
|
.certificate-fade-leave-from .certificate-detail {
|
|
opacity: 1;
|
|
transform: translate3d(0, 0, 0) scale(1);
|
|
}
|
|
|
|
.certificate-fade-leave-to .certificate-detail {
|
|
opacity: 0;
|
|
transform: translate3d(0, 24px, 0) scale(0.98);
|
|
}
|
|
|
|
.certificate-detail {
|
|
transform: translateZ(0);
|
|
will-change: transform, opacity;
|
|
}
|
|
|
|
.certificate-detail::before {
|
|
content: '';
|
|
position: absolute;
|
|
inset: 8% 12%;
|
|
z-index: -1;
|
|
border-radius: 48px;
|
|
background: radial-gradient(
|
|
circle,
|
|
rgba(255, 255, 255, 0.35) 0%,
|
|
rgba(117, 235, 255, 0.2) 38%,
|
|
rgba(117, 235, 255, 0) 72%
|
|
);
|
|
}
|
|
|
|
.certificate-detail-img {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
</style>
|