Files
tootaio.com/app/pages/index.vue
Kingsmai f9e02372b2 feat(about): add team member profile page
This commit introduces a new section to showcase team members, starting with the founder's profile.

- Adds a dynamic page route `/about/` to display individual member profiles.
- Creates a new `about` content collection to source profile information from Markdown files.
- Adds the first profile for 'Xiaomai', including a detailed resume and background image.
- Integrates a 'Teams' dropdown into the main navigation header.
- Implements a `copyToClipboard` utility with a toast notification for sharing profile links.
2025-11-08 13:40:23 +08:00

143 lines
3.7 KiB
Vue

<template>
<div>
<!-- 全幅 Hero - Page 布局之外 -->
<UPageHero
:title="page?.title"
:description="page?.description"
:ui="{
root: 'relative before:absolute before:inset-0 before:bg-[image:var(--bg-image)] before:bg-cover before:bg-center before:-z-10 before:opacity-40',
}"
:style="{
'--bg-image': `url('${currentBgImage}')`,
}"
/>
<UPageSection
:title="page?.capabilities.title"
:features="page?.capabilities.features"
/>
<UPageSection :title="page?.featuredProjects.title">
<UCarousel
v-slot="{ item }"
:items="page?.featuredProjects.projects"
:ui="{ item: 'basis-full sm:basis-1/2 lg:basis-1/3' }"
>
<UPageCard
class="my-2"
:title="item.title"
:description="item.description"
:highlight="item.highlight"
:spotlight="item.spotlight"
>
<img :src="item.image" :alt="item.title" />
<UButton
v-if="item.demoLink"
:href="item.demoLink"
target="_blank"
rel="noopener"
size="sm"
>
{{ $t("index.featuredProjects.viewDemo") }}
</UButton>
</UPageCard>
</UCarousel>
</UPageSection>
<UPageSection :title="page?.techStack.title">
<UMarquee>
<UIcon
v-for="icon in techIcons"
:key="icon"
:name="icon"
class="size-16"
/>
</UMarquee>
<UMarquee reverse>
<UIcon
v-for="icon in toolsIcons"
:key="icon"
:name="icon"
class="size-16"
/>
</UMarquee>
</UPageSection>
<UPageSection
:title="page?.whyChooseUs.title"
:features="page?.whyChooseUs.features"
/>
</div>
</template>
<script lang="ts" setup>
const { data: page } = await useLocalizedCollection("index", {
throwOnMissing: false,
});
useSeoMeta({
title: page.value?.seo.title,
});
const backgroundImages = [
"https://img.tootaio.com/i/2025/11/05/avc5ld.png",
"https://img.tootaio.com/i/2025/11/05/avcaff.png",
"https://img.tootaio.com/i/2025/11/05/avcjbw.png",
"https://img.tootaio.com/i/2025/11/05/avcp16.png",
"https://img.tootaio.com/i/2025/11/05/avcv1q.png",
"https://img.tootaio.com/i/2025/11/05/avd47a.png",
"https://img.tootaio.com/i/2025/11/05/avdx6a.png",
"https://img.tootaio.com/i/2025/11/05/avegxy.png",
"https://img.tootaio.com/i/2025/11/05/avemgn.png",
"https://img.tootaio.com/i/2025/11/05/avf3wl.png",
];
const currentBgImage = ref<string | undefined>("");
// 随机选择背景
const randomBg = () => {
const randomIndex = Math.floor(Math.random() * backgroundImages.length);
currentBgImage.value = backgroundImages[randomIndex];
};
// 轮播背景
onMounted(() => {
randomBg();
});
const techIcons = computed(() => [
"skill-icons:html",
"skill-icons:css",
"skill-icons:javascript",
"skill-icons:typescript",
"skill-icons:docker",
"skill-icons:vuejs-light",
"skill-icons:nuxtjs-light",
"skill-icons:tailwindcss-light",
"skill-icons:nodejs-light",
"skill-icons:cs",
"skill-icons:python-light",
]);
const toolsIcons = ref([
"skill-icons:photoshop",
"skill-icons:illustrator",
"skill-icons:git",
"skill-icons:vscode-light",
"skill-icons:visualstudio-light",
"skill-icons:github-light",
"skill-icons:godot-light",
"skill-icons:unity-light",
"skill-icons:blender-light",
"skill-icons:androidstudio-light",
"skill-icons:windows-light",
"skill-icons:linux-light",
"skill-icons:apple-light",
"skill-icons:idea-light",
"skill-icons:pycharm-light",
"skill-icons:rider-light",
]);
</script>
<style></style>