386 lines
8.5 KiB
Vue
386 lines
8.5 KiB
Vue
<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>
|