Files
my-page/src/pages/styles/CandyPage.vue
2026-08-12 19:18:35 +08:00

386 lines
8.5 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.
<script setup>
import { profile } from '../../data/profile'
const candy = ['#ffb3c6', '#a8e6cf', '#ffe8a3', '#c5cbf7']
</script>
<template>
<div class="candy">
<span class="mochi m1" aria-hidden="true"><i class="eye"></i><i class="eye"></i><b class="mouth"></b></span>
<span class="mochi m2" aria-hidden="true"><i class="eye"></i><i class="eye"></i><b class="mouth"></b></span>
<span class="mochi m3" aria-hidden="true"><i class="eye"></i><i class="eye"></i><b class="mouth"></b></span>
<div class="wrap">
<nav class="ca-nav">
<router-link to="/" class="ca-back">← 回到合集</router-link>
<span class="ca-brand">🍡 年糕铺子</span>
</nav>
<header class="ca-hero">
<div class="ca-avatar">
<img :src="profile.avatars.cute" alt="年糕崽崽的头像" loading="lazy" />
</div>
<h1 class="ca-name">{{ profile.name }}</h1>
<p class="ca-tagline">一颗会写代码的小年糕~</p>
<div class="ca-badges">
<span class="ca-badge b1">{{ profile.job }}</span>
<span class="ca-badge b2">{{ profile.age }} 岁</span>
<span class="ca-badge b3">{{ profile.location.split('·')[1] }}</span>
</div>
<p class="ca-bio">{{ profile.bio }}</p>
</header>
<section class="ca-card">
<h2 class="ca-title">技能小罐子</h2>
<div class="ca-skills">
<div v-for="(sk, i) in profile.skills" :key="sk.name" class="ca-skill">
<div class="ca-skill-head">
<span>{{ sk.name }}</span>
<b :style="{ color: candy[i % 4] }">{{ sk.level }}%</b>
</div>
<div class="ca-track">
<div
class="ca-fill"
:style="{ width: sk.level + '%', background: candy[i % 4] }"
></div>
</div>
</div>
</div>
</section>
<section class="ca-card">
<h2 class="ca-title">作品点心盒</h2>
<div class="ca-works">
<article
v-for="(p, i) in profile.projects"
:key="p.name"
class="ca-work"
:style="{ '--c': candy[i % 4] }"
>
<div class="ca-work-img">
<img :src="p.image" :alt="p.name" loading="lazy" />
</div>
<h3>{{ p.name }}</h3>
<p class="ca-work-alias">{{ p.alias }} · {{ p.year }}</p>
<p class="ca-work-desc">{{ p.desc }}</p>
<div class="ca-tags">
<span v-for="t in p.tags" :key="t">{{ t }}</span>
</div>
</article>
</div>
</section>
<footer class="ca-footer">
<h2 class="ca-title">戳我玩呀</h2>
<div class="ca-contacts">
<span v-for="(c, i) in profile.contacts" :key="c.label" class="ca-contact" :style="{ background: candy[i % 4] }">
{{ c.label }} · {{ c.value }}
</span>
</div>
<p class="ca-bye">看到这里啦,请你吃一串年糕 🍡</p>
</footer>
</div>
</div>
</template>
<style scoped>
.candy {
min-height: 100vh;
background:
radial-gradient(circle at 12% 18%, rgba(255, 179, 198, 0.35), transparent 42%),
radial-gradient(circle at 88% 30%, rgba(168, 230, 207, 0.4), transparent 45%),
radial-gradient(circle at 50% 88%, rgba(255, 232, 163, 0.4), transparent 48%),
#fff7f0;
color: #7a5c66;
font-family: 'ZCOOL KuaiLe', 'PingFang SC', 'Microsoft YaHei', sans-serif;
position: relative;
overflow: clip;
padding: clamp(18px, 4vw, 48px);
}
.mochi {
position: absolute;
width: 74px;
height: 60px;
background: #fffefb;
border-radius: 50% 50% 46% 46% / 62% 62% 40% 40%;
box-shadow: 0 6px 0 rgba(240, 200, 210, 0.6), inset 0 -6px 8px rgba(255, 210, 222, 0.55);
pointer-events: none;
animation: bob 4.5s ease-in-out infinite;
}
.m1 { top: 12%; left: 6%; }
.m2 { top: 36%; right: 5%; animation-delay: 1.2s; transform: scale(0.82); }
.m3 { bottom: 10%; left: 9%; animation-delay: 2.3s; transform: scale(0.7); }
@keyframes bob {
50% { transform: translateY(-14px); }
}
.mochi .eye {
position: absolute;
width: 7px;
height: 9px;
background: #5a4a50;
border-radius: 50%;
top: 24px;
}
.mochi .eye:first-child { left: 22px; }
.mochi .eye:nth-child(2) { right: 22px; }
.mochi .mouth {
position: absolute;
width: 12px;
height: 6px;
border-bottom: 2.5px solid #5a4a50;
border-radius: 50%;
left: 50%;
transform: translateX(-50%);
top: 30px;
}
.wrap {
position: relative;
z-index: 1;
max-width: 880px;
margin: 0 auto;
}
.ca-nav {
position: sticky;
top: 0;
z-index: 40;
background: rgba(255, 247, 240, 0.92);
backdrop-filter: blur(6px);
padding: 10px 0;
border-radius: 0 0 18px 18px;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 36px;
}
.ca-back {
color: #d46a92;
background: #fff;
text-decoration: none;
font-size: 15px;
padding: 10px 22px;
border-radius: 999px;
box-shadow: 0 4px 14px rgba(255, 179, 198, 0.5);
transition: transform 0.18s;
}
.ca-back:hover {
transform: scale(1.06);
}
.ca-brand {
font-size: 16px;
color: #b98a9c;
}
.ca-hero {
text-align: center;
margin-bottom: 44px;
}
.ca-avatar {
width: 140px;
height: 140px;
margin: 0 auto 16px;
border-radius: 50%;
background: #fff;
padding: 8px;
box-shadow:
0 8px 24px rgba(255, 179, 198, 0.55),
inset 0 0 0 4px #ffe0ea;
animation: bob 5s ease-in-out infinite;
}
.ca-avatar img {
width: 100%;
height: 100%;
border-radius: 50%;
}
.ca-name {
font-size: clamp(38px, 7vw, 56px);
color: #d46a92;
margin: 0 0 8px;
text-shadow: 0 3px 0 #ffe0ea;
letter-spacing: 0.06em;
}
.ca-tagline {
font-size: 17px;
color: #b98a9c;
margin: 0 0 18px;
}
.ca-badges {
display: flex;
justify-content: center;
gap: 12px;
flex-wrap: wrap;
margin-bottom: 20px;
}
.ca-badge {
font-size: 14px;
padding: 8px 20px;
border-radius: 999px;
color: #7a5c66;
box-shadow: 0 4px 0 rgba(220, 180, 190, 0.45);
}
.b1 { background: #ffd9e4; }
.b2 { background: #cdefdf; }
.b3 { background: #ffefc2; }
.ca-bio {
max-width: 520px;
margin: 0 auto;
font-size: 15.5px;
line-height: 2.05;
}
.ca-card {
background: rgba(255, 255, 255, 0.85);
border-radius: 36px;
padding: clamp(24px, 4vw, 40px);
margin-bottom: 34px;
box-shadow: 0 10px 30px rgba(235, 190, 205, 0.35);
border: 3px dashed #ffd9e4;
}
.ca-title {
text-align: center;
font-size: 25px;
color: #d46a92;
margin: 0 0 26px;
letter-spacing: 0.08em;
}
.ca-skills {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 18px 36px;
}
.ca-skill-head {
display: flex;
justify-content: space-between;
font-size: 15px;
margin-bottom: 8px;
}
.ca-track {
height: 16px;
border-radius: 999px;
background: #f7e9ee;
overflow: hidden;
box-shadow: inset 0 2px 4px rgba(190, 150, 165, 0.25);
}
.ca-fill {
height: 100%;
border-radius: 999px;
/* 叠加白色斜条纹,营造糖果棒质感(底色来自内联样式) */
background-image: repeating-linear-gradient(
-45deg,
rgba(255, 255, 255, 0.42) 0 10px,
transparent 10px 20px
) !important;
}
.ca-works {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 24px;
}
.ca-work {
background: #fff;
border-radius: 28px;
padding: 16px;
box-shadow: 0 8px 0 var(--c);
transition: transform 0.18s;
}
.ca-work:hover {
transform: translateY(-6px) rotate(-1deg);
}
.ca-work-img {
border-radius: 20px;
overflow: hidden;
aspect-ratio: 16 / 10;
margin-bottom: 14px;
border: 4px solid var(--c);
}
.ca-work-img img {
width: 100%;
height: 100%;
object-fit: cover;
}
.ca-work h3 {
font-size: 21px;
margin: 0 0 2px;
color: #d46a92;
}
.ca-work-alias {
font-size: 13px;
color: #b98a9c;
margin: 0 0 10px;
}
.ca-work-desc {
font-size: 14px;
line-height: 1.9;
margin: 0 0 12px;
}
.ca-tags {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.ca-tags span {
font-size: 12.5px;
background: #fff2f6;
color: #d46a92;
border-radius: 999px;
padding: 4px 13px;
border: 2px solid #ffd9e4;
}
.ca-footer {
text-align: center;
padding-bottom: 20px;
}
.ca-contacts {
display: flex;
justify-content: center;
gap: 14px;
flex-wrap: wrap;
margin-bottom: 22px;
}
.ca-contact {
font-size: 14.5px;
color: #6d5560;
padding: 11px 22px;
border-radius: 999px;
box-shadow: 0 5px 0 rgba(220, 180, 190, 0.5);
transition: transform 0.15s;
}
.ca-contact:hover {
transform: translateY(-3px);
}
.ca-bye {
font-size: 15px;
color: #b98a9c;
margin: 0;
}
</style>