Skip to content

Commit bd8eb9f

Browse files
committed
feat: add galgame series page
1 parent 107b1b5 commit bd8eb9f

14 files changed

Lines changed: 439 additions & 91 deletions

File tree

components/kun/top-bar/hamburgerItem.ts

Lines changed: 0 additions & 87 deletions
This file was deleted.

components/series/Banner.vue

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<script setup lang="ts">
2+
import type { GalgameSample } from '~/types/api/series'
3+
4+
const props = defineProps<{
5+
isNSFW: boolean
6+
galgames: GalgameSample[]
7+
}>()
8+
9+
const banners = computed(() => props.galgames.map((g) => g.banner).slice(0, 5))
10+
11+
const hoverTranslations = [
12+
'group-hover:translate-x-0',
13+
'group-hover:translate-x-[50%] translate-x-[10%]',
14+
'group-hover:translate-x-[100%] translate-x-[20%]',
15+
'group-hover:translate-x-[150%] translate-x-[30%]',
16+
'group-hover:translate-x-[200%] translate-x-[40%]'
17+
]
18+
</script>
19+
20+
<template>
21+
<div class="relative mb-4 h-32 w-full">
22+
<KunBadge
23+
variant="solid"
24+
class="absolute top-2 left-2 z-100"
25+
:color="isNSFW ? 'danger' : 'success'"
26+
>
27+
{{ isNSFW ? 'NSFW' : 'SFW' }}
28+
</KunBadge>
29+
30+
<div class="absolute inset-0">
31+
<div
32+
v-for="(banner, index) in banners"
33+
:key="banner"
34+
:class="
35+
cn(
36+
'absolute aspect-video h-full rounded-lg shadow-lg transition-transform duration-500 ease-out',
37+
hoverTranslations[index]
38+
)
39+
"
40+
:style="{ zIndex: banners.length - index }"
41+
>
42+
<NuxtImg
43+
:src="banner"
44+
:alt="`Series Banner ${index + 1}`"
45+
class="ring-default/50 h-full w-full rounded-lg object-cover ring-2"
46+
loading="lazy"
47+
format="webp"
48+
quality="80"
49+
/>
50+
</div>
51+
</div>
52+
</div>
53+
</template>

components/series/Card.vue

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<script setup lang="ts">
2+
import type { GalgameSeries } from '~/types/api/series'
3+
4+
const props = defineProps<{
5+
series: GalgameSeries
6+
}>()
7+
8+
const includedGamesText = computed(() => {
9+
if (!props.series.sampleGalgame.length) {
10+
return '暂无 Galgame'
11+
}
12+
const names = props.series.sampleGalgame.map(
13+
(g) => `《${getPreferredLanguageText(g.name)}》`
14+
)
15+
return `${names.join('')}${props.series.galgameCount > 5 ? '' : ''}`
16+
})
17+
</script>
18+
19+
<template>
20+
<KunCard
21+
:is-pressable="true"
22+
:href="`/series/${series.id}`"
23+
class-name="group relative flex h-full flex-col overflow-hidden backdrop-blur-none"
24+
:is-transparent="true"
25+
>
26+
<div class="relative mb-4 h-32 w-full">
27+
<KunBadge
28+
variant="solid"
29+
class="absolute top-2 left-2 z-100"
30+
:color="series.isNSFW ? 'danger' : 'success'"
31+
>
32+
{{ series.isNSFW ? 'NSFW' : 'SFW' }}
33+
</KunBadge>
34+
35+
<SeriesBanner
36+
:is-n-s-f-w="series.isNSFW"
37+
:galgames="series.sampleGalgame"
38+
/>
39+
</div>
40+
41+
<div class="flex flex-grow flex-col px-1 pb-1">
42+
<h3
43+
class="group-hover:text-primary mb-2 line-clamp-2 text-xl font-bold transition-colors"
44+
>
45+
{{ series.name }}
46+
</h3>
47+
48+
<p class="text-default-500 mb-4 line-clamp-1 text-xs">
49+
{{ includedGamesText }}
50+
</p>
51+
52+
<div class="mt-auto flex items-center justify-between">
53+
<div class="text-default-500 flex items-center gap-2 text-sm">
54+
<KunIcon name="lucide:gamepad-2" class="h-4 w-4" />
55+
<span>共 {{ series.galgameCount }} 部 Galgame</span>
56+
</div>
57+
58+
<div
59+
class="group-hover:text-primary flex items-center gap-1.5 transition-all group-hover:translate-x-1"
60+
>
61+
<span class="text-sm font-medium">查看详情</span>
62+
<KunIcon name="lucide:arrow-right" class="h-4 w-4" />
63+
</div>
64+
</div>
65+
</div>
66+
</KunCard>
67+
</template>

components/series/Container.vue

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<script setup lang="ts">
2+
const { data } = await useFetch('/api/series', {
3+
method: 'GET',
4+
...kungalgameResponseHandler
5+
})
6+
</script>
7+
8+
<template>
9+
<KunCard
10+
:is-hoverable="false"
11+
:is-pressable="false"
12+
:is-transparent="false"
13+
content-class="space-y-3"
14+
>
15+
<KunHeader
16+
name="Galgame 系列"
17+
description="Galgame 全系列所有 Galgame 作品。例如美少女万华镜 1, 2, 3, 4, 5, 雪女, 外传 就是一个 Galgame 系列"
18+
/>
19+
20+
<div class="grid grid-cols-1 gap-6 lg:grid-cols-2">
21+
<SeriesCard
22+
v-for="(series, index) in data"
23+
:key="series.id"
24+
:style="{ animationDelay: `${index * 50}ms` }"
25+
:series="series"
26+
/>
27+
</div>
28+
</KunCard>
29+
</template>

components/series/Detail.vue

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<script setup lang="ts">
2+
import type { GalgameSeriesDetail } from '~/types/api/series'
3+
4+
defineProps<{
5+
data: GalgameSeriesDetail
6+
}>()
7+
</script>
8+
9+
<template>
10+
<KunCard
11+
:is-hoverable="false"
12+
:is-pressable="false"
13+
:is-transparent="false"
14+
content-class="space-y-3"
15+
>
16+
<KunHeader :name="data.name" :description="data.description">
17+
<template #endContent>
18+
<div class="flex flex-col flex-wrap gap-3 text-sm">
19+
<div class="text-default-500 flex items-center gap-2">
20+
<KunIcon name="lucide:gamepad-2" />
21+
<span class="font-medium">
22+
共计 {{ data.galgame.length }} 部 Galgame
23+
</span>
24+
</div>
25+
26+
<div class="text-default-500 space-x-2">
27+
<span>
28+
创建于
29+
{{ formatDate(data.created, { isShowYear: true }) }}
30+
</span>
31+
·
32+
<span>
33+
更新于
34+
{{ formatTimeDifference(data.updated) }}
35+
</span>
36+
</div>
37+
</div>
38+
</template>
39+
</KunHeader>
40+
41+
<GalgameCard :galgames="data.galgame" />
42+
</KunCard>
43+
</template>

constants/layout.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,15 @@ export const kunLayoutItem: KunLayoutItem[] = [
1616
router: '/galgame',
1717
label: 'Galgame'
1818
},
19+
{
20+
name: 'series',
21+
icon: 'lucide:columns-4',
22+
router: '/series',
23+
label: 'Galgame 系列'
24+
},
1925
{
2026
name: 'topic',
21-
icon: 'lucide:square-library',
27+
icon: 'icon-park-outline:topic',
2228
router: '/topic',
2329
label: '话题'
2430
},

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "kun-galgame-nuxt3",
3-
"version": "4.0.24",
3+
"version": "4.0.25",
44
"packageManager": "pnpm@10.4.1",
55
"private": true,
66
"scripts": {

pages/series/[id].vue

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<script setup lang="ts">
2+
const route = useRoute()
3+
const seriesId = route.params.id
4+
5+
const { data } = await useFetch(`/api/series/${seriesId}`, {
6+
method: 'GET',
7+
query: { seriesId },
8+
...kungalgameResponseHandler
9+
})
10+
11+
useHead({
12+
link: [
13+
{
14+
rel: 'canonical',
15+
href: `${kungal.domain.main}/series/${seriesId}`
16+
}
17+
]
18+
})
19+
20+
useKunSeoMeta({
21+
title: `${data.value?.name} - 资源 wiki`,
22+
description: data.value?.description
23+
})
24+
</script>
25+
26+
<template>
27+
<SeriesDetail :data="data" v-if="data" />
28+
29+
<KunNull v-else description="未找到这个 Galgame 系列" />
30+
</template>

pages/series/index.vue

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<script setup lang="ts">
2+
useHead({
3+
link: [
4+
{
5+
rel: 'canonical',
6+
href: `${kungal.domain.main}/series`
7+
}
8+
]
9+
})
10+
11+
useKunSeoMeta({
12+
title: 'Galgame 系列',
13+
description:
14+
'Galgame 全系列所有 Galgame 作品, Galgame 全系列资源下载。例如美少女万华镜系列, 灰色系列, 近月少女的礼仪系列, 巧克力与香子兰系列, 9 nine 系列, 巧克甜恋系列等等'
15+
})
16+
</script>
17+
18+
<template>
19+
<SeriesContainer />
20+
</template>

server/api/search/_search.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export const searchTopic = async (
5757
id: topic.id,
5858
title: topic.title,
5959
view: topic.view,
60-
updateTime: topic.update_time,
60+
statusUpdateTime: topic.status_update_time,
6161
tag: topic.tag,
6262
section: topic.section.map((s) => s.topic_section.name),
6363
user: topic.user,
@@ -137,7 +137,7 @@ export const searchGalgame = async (
137137
const languages = [...new Set(galgame.resource.map((r) => r.language))]
138138

139139
return {
140-
gid: galgame.id,
140+
id: galgame.id,
141141
name: {
142142
'en-us': galgame.name_en_us,
143143
'ja-jp': galgame.name_ja_jp,

0 commit comments

Comments
 (0)