Skip to content

Commit 6ef71dc

Browse files
committed
update docs
1 parent 769e327 commit 6ef71dc

File tree

6 files changed

+371
-32
lines changed

6 files changed

+371
-32
lines changed

docs/.vuepress/client.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
import { defineClientConfig } from 'vuepress/client'
1+
import {defineClientConfig} from 'vuepress/client'
22
import RepoCard from 'vuepress-theme-plume/features/RepoCard.vue'
33

44
import './styles/custom.css'
5+
import Swiper from "./components/Swiper.vue";
56

67
export default defineClientConfig({
7-
enhance({ app }) {
8+
enhance({app}) {
89
app.component('RepoCard', RepoCard)
10+
app.component('Swiper', Swiper)
911
},
1012
})

docs/.vuepress/components/Swiper.vue

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
<script setup lang="ts">
2+
import type {AutoplayOptions, SwiperModule, Swiper as SwiperType} from 'swiper/types'
3+
import {
4+
Autoplay,
5+
EffectCards,
6+
EffectCoverflow,
7+
EffectCreative,
8+
EffectCube,
9+
EffectFade,
10+
Mousewheel,
11+
Navigation,
12+
Pagination,
13+
} from 'swiper/modules'
14+
import {Swiper, SwiperSlide} from 'swiper/vue'
15+
import {computed} from 'vue'
16+
17+
import 'swiper/css'
18+
import 'swiper/css/navigation'
19+
import 'swiper/css/pagination'
20+
import 'swiper/css/effect-fade'
21+
import 'swiper/css/effect-cube'
22+
import 'swiper/css/effect-flip'
23+
import 'swiper/css/effect-coverflow'
24+
import 'swiper/css/effect-cards'
25+
import 'swiper/css/effect-creative'
26+
27+
interface SlideItem {
28+
/**
29+
* 图片地址
30+
*/
31+
link?: string
32+
/**
33+
* 文字内容(当没有图片时使用)
34+
*/
35+
text?: string
36+
/**
37+
* 跳转链接
38+
*/
39+
href: string
40+
alt: string
41+
}
42+
43+
interface Props {
44+
items?: (string | SlideItem)[]
45+
width?: number | string // 轮播区域宽度,单位 px
46+
height?: number | string // 轮播区域高度,单位 px
47+
mode?: 'banner' | 'carousel' | 'broadcast' // banner: 轮播图模式; carousel: 走马灯模式; broadcast: 信息展播模式
48+
navigation?: boolean // 是否显示导航
49+
effect?: 'slide' | 'fade' | 'cube' | 'flip' | 'coverflow' | 'cards' | 'creative' // 切换动画效果
50+
delay?: number // 自动切换的时间间隔,仅当 mode: 'banner' 时生效,单位 ms
51+
speed?: number // 切换过渡的动画持续时间,单位 ms
52+
loop?: boolean // 是否循环切换
53+
pauseOnMouseEnter?: boolean // 当鼠标移入走马灯时,是否暂停自动轮播,仅当 mode: 'banner' 或 mode: 'carousel' 时生效
54+
swipe?: boolean // 是否可以鼠标拖动
55+
}
56+
57+
const props = withDefaults(defineProps<Props>(), {
58+
width: '100%',
59+
height: '100%',
60+
mode: 'banner',
61+
navigation: true,
62+
effect: 'slide',
63+
delay: 3000,
64+
speed: 300,
65+
loop: true,
66+
pauseOnMouseEnter: false,
67+
swipe: true,
68+
})
69+
70+
const slideList = computed<SlideItem[]>(() => {
71+
return props.items?.map((link) => {
72+
if (typeof link === 'string')
73+
return {link}
74+
return link
75+
}) ?? []
76+
})
77+
78+
function parseSize(size: number | string) {
79+
if (typeof size === 'number') {
80+
return `${size}px`
81+
}
82+
return size
83+
}
84+
85+
const styles = computed(() => ({
86+
width: parseSize(props.width),
87+
height: parseSize(props.height),
88+
}))
89+
90+
const modules = computed<SwiperModule[]>(() => {
91+
if (props.mode === 'carousel')
92+
return [Autoplay]
93+
94+
if (props.mode === 'broadcast')
95+
return [Navigation, Pagination, Mousewheel]
96+
97+
const modules: SwiperModule[] = [Navigation, Pagination, Autoplay]
98+
const effectMoudles = {
99+
fade: EffectFade,
100+
cube: EffectCube,
101+
flip: EffectFlip,
102+
coverflow: EffectCoverflow,
103+
cards: EffectCards,
104+
creative: EffectCreative,
105+
}
106+
if (props.effect !== 'slide') {
107+
modules.push(effectMoudles[props.effect])
108+
}
109+
return modules
110+
})
111+
112+
const autoplay = computed<AutoplayOptions | boolean>(() => {
113+
if (props.mode === 'banner') {
114+
return {
115+
delay: props.delay,
116+
disableOnInteraction: false, // 用户操作 swiper 之后,是否禁止 autoplay。默认为 true:停止。
117+
pauseOnMouseEnter: props.pauseOnMouseEnter, // 鼠标置于 swiper 时暂停自动切换,鼠标离开时恢复自动切换,默认 false
118+
}
119+
} else if (props.mode === 'carousel') {
120+
return {
121+
delay: 0,
122+
disableOnInteraction: false,
123+
}
124+
}
125+
return false
126+
})
127+
128+
const hasNavigation = computed(() =>
129+
props.mode === 'banner' || props.mode === 'broadcast' ? props.navigation : false,
130+
)
131+
132+
function onSwiper(swiper: SwiperType) {
133+
if (props.mode === 'carousel' && props.pauseOnMouseEnter) {
134+
swiper.el.onmouseenter = () => swiper.autoplay.stop()
135+
swiper.el.onmouseleave = () => swiper.autoplay.start()
136+
}
137+
}
138+
</script>
139+
140+
<template>
141+
<ClientOnly>
142+
<Swiper
143+
class="vp-swiper"
144+
:class="{ 'swiper-no-swiping': mode === 'banner' ? !swipe : mode === 'carousel' }"
145+
:style="styles"
146+
:modules="modules"
147+
:autoplay="autoplay"
148+
:navigation="hasNavigation"
149+
:pagination="props.mode !== 'carousel' ? {
150+
dynamicBullets: true,
151+
clickable: true,
152+
} : false"
153+
:speed="speed"
154+
:loop="loop"
155+
:effect="mode === 'banner' ? effect : 'slide'"
156+
lazy
157+
v-bind="$attrs"
158+
@swiper="onSwiper"
159+
>
160+
<SwiperSlide v-for="(item, index) in slideList" :key="item.link + index">
161+
<a v-if="item.href && item.link" :href="item.href" target="_blank" rel="noopener noreferrer"
162+
class="swiper-slide-link no-icon">
163+
<img class="swiper-slide-custom-container swiper-slide-img" :src="item.link" :alt="item.alt" loading="lazy">
164+
</a>
165+
<div v-else-if="item.text" class="swiper-slide-custom-container">
166+
<a v-if="item.href" :href="item.href" target="_blank" rel="noopener noreferrer"
167+
class="swiper-slide-text-link">
168+
<div class="swiper-slide-text">{{ item.text }}</div>
169+
</a>
170+
<div v-else class="swiper-slide-text">{{ item.text }}</div>
171+
</div>
172+
</SwiperSlide>
173+
</Swiper>
174+
</ClientOnly>
175+
</template>
176+
177+
<style>
178+
.vp-swiper {
179+
margin: 24px 0;
180+
}
181+
182+
.swiper-slide-link {
183+
display: block;
184+
height: 100%;
185+
}
186+
187+
.swiper-slide-img {
188+
width: 100%;
189+
height: 100%;
190+
cursor: default !important;
191+
object-fit: cover;
192+
}
193+
194+
.swiper-slide-link .swiper-slide-img {
195+
cursor: pointer !important;
196+
}
197+
198+
.swiper-slide-custom-container {
199+
width: 100%;
200+
height: 100%;
201+
border: 2px solid #ccc;
202+
border-radius: 8px;
203+
}
204+
205+
.swiper-slide-text {
206+
color: #888;
207+
font-size: 18px;
208+
text-align: center;
209+
position: absolute;
210+
top: 50%;
211+
left: 50%;
212+
transform: translate(-50%, -50%);
213+
width: 100%;
214+
}
215+
216+
.swiper-slide-text-link {
217+
display: block;
218+
height: 100%;
219+
text-decoration: none;
220+
}
221+
222+
.swiper {
223+
--swiper-theme-color: var(--vp-c-bg);
224+
--swiper-pagination-bullet-inactive-color: var(--vp-c-bg);
225+
--swiper-pagination-bullet-inactive-opacity: 0.4;
226+
}
227+
228+
.swiper-wrapper {
229+
-webkit-transition-timing-function: linear;
230+
transition-timing-function: linear;
231+
}
232+
233+
.swiper-pagination-bullet {
234+
width: 12px;
235+
height: 12px;
236+
}
237+
</style>

docs/.vuepress/styles/custom.css

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
11
:root {
2-
--vp-bulletin-width: 385px;
2+
--vp-bulletin-width: 385px; /* 公告宽度 */
3+
--vp-c-brand-1: rgba(0, 148, 133, 1); /* 链接颜色、强调色 */
4+
--vp-c-brand-2: rgba(0, 148, 133, 1); /* 链接、按钮 hover 颜色 */
5+
--vp-c-brand-3: rgba(0, 148, 133, 1); /* 背景色、边框色 */
6+
}
7+
8+
[data-theme="dark"] {
9+
--vp-c-brand-1: rgba(0, 148, 133, 1); /* 链接颜色、强调色 */
10+
--vp-c-brand-2: rgba(0, 148, 133, 1); /* 链接、按钮 hover 颜色 */
11+
--vp-c-brand-3: rgba(0, 148, 133, 1); /* 背景色、边框色 */
312
}

0 commit comments

Comments
 (0)