dma_handbook/docs/.vuepress/components/PageSwitcher.vue
2026-07-16 17:18:40 +08:00

167 lines
3.7 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.

<template>
<div class="api-reference-container">
<!-- 顶部标题+搜索栏 -->
<div class="header-bar">
<div class="main-title">{{ mainTitle }}</div>
<div v-if="showFilter" class="filter-wrap">
<span class="filter-label">过滤</span>
<input
v-model="filterKeyword"
class="filter-input"
placeholder="搜索内容"
/>
</div>
</div>
<!-- 各个大分组全局API、组合式API -->
<div class="group-wrapper" v-for="group in filteredGroupList" :key="group.groupTitle">
<div class="group-title">{{ group.groupTitle }}</div>
<div class="card-row">
<!-- 子卡片 -->
<div class="sub-card" v-for="card in group.list" :key="card.subTitle">
<div class="sub-title">{{ card.subTitle }}</div>
<RouteLink
class="item-line"
v-for="item in card.items"
:key="item.link"
:to="item.link"
>
{{ item.name }}
</RouteLink>
</div>
</div>
<hr class="group-divider" />
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
import { RouteLink } from 'vuepress/client'
const props = defineProps({
mainTitle: {
type: String,
required: true,
default: 'API 参考'
},
pageData: {
type: Array,
required: true,
default: () => []
},
showFilter: {
type: Boolean,
default: false
}
})
const filterKeyword = ref('')
// 搜索过滤逻辑:匹配分组标题、子卡片标题、条目名称
const filteredGroupList = computed(() => {
if (!filterKeyword.value) return props.pageData
const kw = filterKeyword.value.toLowerCase()
return props.pageData
.map(group => {
const filteredCards = group.list
.map(card => {
const matchItems = card.items.filter(i => i.name.toLowerCase().includes(kw))
const cardMatch = card.subTitle.toLowerCase().includes(kw)
return {
...card,
items: cardMatch ? card.items : matchItems
}
})
.filter(card => card.items.length > 0 || card.subTitle.toLowerCase().includes(kw))
return { ...group, list: filteredCards }
})
.filter(g => g.list.length > 0 || g.groupTitle.toLowerCase().includes(kw))
})
</script>
<style scoped>
.api-reference-container {
width: 100%;
margin: 16px 0;
}
.header-bar {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
}
.main-title {
width: 100%;
font-size: 32px;
font-weight: 600;
color: #1f2937;
padding-bottom: 40px;
margin: 20px 0;
border-bottom: 1px solid #e7e7e7;
}
.filter-wrap {
display: flex;
align-items: center;
gap: 8px;
}
.filter-label {
color: #6b7280;
font-size: 15px;
}
.filter-input {
border: 1px solid #d1d5db;
border-radius: 6px;
padding: 6px 10px;
width: 180px;
font-size: 15px;
}
.filter-input:focus {
outline: none;
border-color: #3eaf7c;
box-shadow: 0 0 0 2px rgba(62, 175, 124, 0.15);
}
.group-title {
font-size: 22px;
font-weight: 600;
color: #1f2937;
margin: 24px 0 14px;
}
.card-row {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.sub-card {
background: #f7f8f9;
border-radius: 8px;
padding: 18px 20px;
min-width: 240px;
flex: 1;
max-width: calc(33% - 12px);
}
.sub-title {
color: #3eaf7c;
font-weight: 600;
font-size: 16px;
margin-bottom: 12px;
}
.item-line {
display: block;
color: #334155;
font-size: 15px;
line-height: 1.7;
margin: 4px 0;
text-decoration: none;
}
.item-line:hover {
color: #3eaf7c;
}
.group-divider {
border: none;
border-top: 1px solid #e5e7eb;
margin: 28px 0;
}
</style>