feat: ranking page topic

This commit is contained in:
KUN1007 2023-10-17 23:41:04 +08:00
parent e401702c0a
commit 9d4a34aa72
5 changed files with 190 additions and 40 deletions

View file

@ -2,7 +2,7 @@ export interface RankingGetTopicsRequestData {
page: number page: number
limit: number limit: number
sortField: string sortField: string
sortOrder: string sortOrder: 'asc' | 'desc'
} }
export interface RankingTopics { export interface RankingTopics {

View file

@ -34,13 +34,13 @@ export const navSortItem: Sort[] = [
index: 5, index: 5,
icon: 'line-md:thumbs-up-twotone', icon: 'line-md:thumbs-up-twotone',
name: 'likes', name: 'likes',
sortField: 'likes', sortField: 'likes_count',
}, },
{ {
index: 6, index: 6,
icon: 'ri:reply-line', icon: 'ri:reply-line',
name: 'replies', name: 'replies',
sortField: 'replies', sortField: 'replies_count',
}, },
{ {
index: 7, index: 7,

View file

@ -6,7 +6,7 @@ import KUNgalgamer from './KUNGalgamer.vue'
<!-- 用户排行 --> <!-- 用户排行 -->
<div class="kungalgamer-ranking"> <div class="kungalgamer-ranking">
<!-- 用户排行标题 --> <!-- 用户排行标题 -->
<div class="kungalgamer-title">最萌的萝莉</div> <div class="kungalgamer-title">用户</div>
<!-- 用户排行的交互 --> <!-- 用户排行的交互 -->
<div class="kungalgamer-nav"> <div class="kungalgamer-nav">
<!-- 萌萌点 --> <!-- 萌萌点 -->

View file

@ -10,7 +10,7 @@ const props = defineProps<{
const topics = computed(() => props.topics) const topics = computed(() => props.topics)
const icons: Record<string, string> = { const iconMap: Record<string, string> = {
popularity: 'bi:fire', popularity: 'bi:fire',
upvotes_count: 'bi:rocket', upvotes_count: 'bi:rocket',
views: 'ic:outline-remove-red-eye', views: 'ic:outline-remove-red-eye',
@ -26,8 +26,10 @@ const parseTopicNumber = (field: string | string[]) => {
</script> </script>
<template> <template>
<TransitionGroup name="list">
<!-- 单个话题 --> <!-- 单个话题 -->
<div class="single-topic" v-for="(topic, index) in topics" :key="index"> <div class="single-topic" v-for="topic in topics" :key="topic.tid">
<RouterLink :to="`/topic/${topic.tid}`">
<!-- 话题的名字 --> <!-- 话题的名字 -->
<div class="topic-name"> <div class="topic-name">
{{ topic.title }} {{ topic.title }}
@ -35,24 +37,39 @@ const parseTopicNumber = (field: string | string[]) => {
<!-- 话题的其它信息 --> <!-- 话题的其它信息 -->
<div class="detail"> <div class="detail">
<!-- 浏览数 --> <!-- 浏览数 -->
<span>
<Icon :icon="icons[props.field]" /> <Icon :icon="iconMap[props.field]" />
{{ parseTopicNumber(topic.field) }} <span>{{ parseTopicNumber(topic.field) }}</span>
</span>
</div> </div>
</RouterLink>
</div> </div>
</TransitionGroup>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
/* 单个话题 */ /* 单个话题 */
.single-topic { .single-topic {
a {
flex-shrink: 0; flex-shrink: 0;
height: 37px; height: 37px;
border-bottom: 1px solid var(--kungalgame-blue-4);
margin: 7px; margin: 7px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
background-color: var(--kungalgame-trans-blue-0);
border: 1px solid var(--kungalgame-trans-blue-0);
border-radius: 5px;
color: var(--kungalgame-font-color-3);
padding: 0 10px;
cursor: pointer;
&:hover {
transition: all 0.5s;
background-color: var(--kungalgame-trans-white-9);
border: 1px solid var(--kungalgame-blue-4);
color: var(--kungalgame-blue-4);
}
}
} }
/* 话题的名字 */ /* 话题的名字 */
.topic-name { .topic-name {
@ -60,16 +77,31 @@ const parseTopicNumber = (field: string | string[]) => {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
/* 话题的其它信息 */
.v-l-c-t {
flex-shrink: 0;
}
.detail { .detail {
display: flex;
span {
display: flex; display: flex;
align-items: center; align-items: center;
color: var(--kungalgame-blue-4);
span {
color: var(--kungalgame-font-color-3);
margin-left: 10px; margin-left: 10px;
} }
} }
.list-move, /* 对移动中的元素应用的过渡 */
.list-enter-active,
.list-leave-active {
transition: all 0.5s ease;
}
.list-enter-from,
.list-leave-to {
opacity: 0;
}
/*
以便能够正确地计算移动的动画 */
.list-leave-active {
position: absolute;
}
</style> </style>

View file

@ -9,8 +9,10 @@ import { storeToRefs } from 'pinia'
import type { RankingTopics } from '@/api' import type { RankingTopics } from '@/api'
import { topicNavSortItem } from './navSortItem' import { topicNavSortItem } from './navSortItem'
const { topic, user } = storeToRefs(useKUNGalgameRankingStore()) const { topic } = storeToRefs(useKUNGalgameRankingStore())
const topics = ref<RankingTopics[]>([]) const topics = ref<RankingTopics[]>([])
//
const isAscending = ref(false)
// //
const getTopics = async () => { const getTopics = async () => {
@ -18,6 +20,15 @@ const getTopics = async () => {
return responseData.data return responseData.data
} }
const iconMap: Record<string, string> = {
popularity: 'bi:fire',
upvotes_count: 'bi:rocket',
views: 'ic:outline-remove-red-eye',
likes_count: 'line-md:thumbs-up-twotone',
replies_count: 'ri:reply-line',
comments: 'fa-regular:comment-dots',
}
// //
watch( watch(
() => topic, () => topic,
@ -31,29 +42,53 @@ watch(
onMounted(async () => { onMounted(async () => {
topics.value = await getTopics() topics.value = await getTopics()
}) })
//
const handleClickSortOrder = () => {
isAscending.value = !isAscending.value
if (isAscending.value) {
topic.value.sortOrder = 'asc'
} else {
topic.value.sortOrder = 'desc'
}
}
</script> </script>
<template> <template>
<!-- 话题排行 --> <!-- 话题排行 -->
<div class="topic"> <div class="topic">
<!-- 话题排行标题 --> <!-- 话题排行标题 -->
<div class="title">最萌的话题</div> <div class="title">话题</div>
<!-- 话题排行的交互 --> <!-- 话题排行的交互 -->
<div class="nav"> <div class="nav">
<!-- 升序降序 --> <!-- 升序降序 -->
<div class="order">排序</div> <div class="order" @click="handleClickSortOrder">
<Transition name="order" mode="out-in">
<div v-if="isAscending">
<span>升序</span>
<Icon class="icon" icon="line-md:arrow-small-up" />
</div>
<div v-else-if="!isAscending">
<span>降序</span>
<Icon class="icon" icon="line-md:arrow-small-down" />
</div>
</Transition>
</div>
<div class="field"> <!-- 排序 -->
<div class="sort">
<Icon class="icon" :icon="iconMap[topic.sortField]" />
<span>筛选</span>
<!-- 排序子菜单 --> <!-- 排序子菜单 -->
<div class="sort-submenu"> <div class="submenu">
<div <div
class="sort-item" class="item"
v-for="kun in topicNavSortItem" v-for="kun in topicNavSortItem"
:key="kun.index" :key="kun.index"
@click="topic.sortField = kun.sortField" @click="topic.sortField = kun.sortField"
> >
<span><Icon class="icon-item" :icon="kun.icon" /></span> <span><Icon class="icon" :icon="kun.icon" /></span>
<span>按时间排序</span> <span>{{ kun.name }}</span>
</div> </div>
</div> </div>
</div> </div>
@ -69,6 +104,7 @@ onMounted(async () => {
/* 话题排行 */ /* 话题排行 */
.topic { .topic {
width: 50%; width: 50%;
height: calc(100% - 50px - 20px - 40px);
} }
/* 话题排行标题 */ /* 话题排行标题 */
.title { .title {
@ -82,8 +118,75 @@ onMounted(async () => {
} }
/* 话题排行的交互 */ /* 话题排行的交互 */
.nav { .nav {
height: 40px;
display: flex; display: flex;
justify-content: space-around;
align-items: center;
margin-left: 10px; margin-left: 10px;
border: 1px solid var(--kungalgame-blue-4);
border-radius: 5px;
}
.order {
width: 100%;
height: 100%;
cursor: pointer;
transition: all 0.2s;
display: flex;
align-items: center;
.icon {
font-size: 22px;
}
& > div {
width: 100%;
display: flex;
justify-content: space-around;
align-items: center;
}
}
.sort {
position: relative;
width: 100%;
height: 100%;
display: flex;
justify-content: space-around;
align-items: center;
cursor: pointer;
border-left: 1px solid var(--kungalgame-blue-4);
}
.sort:hover .submenu {
display: flex;
}
.icon {
color: var(--kungalgame-blue-4);
}
.submenu {
top: 40px;
position: absolute;
width: 100%;
display: none;
flex-direction: column;
border-radius: 5px;
border: 1px solid var(--kungalgame-blue-1);
box-shadow: var(--shadow);
background-color: var(--kungalgame-trans-white-5);
backdrop-filter: blur(5px);
.item {
transition: all 0.2s;
height: 40px;
display: flex;
justify-content: space-around;
align-items: center;
&:hover {
background-color: var(--kungalgame-trans-blue-1);
}
}
} }
/* 单个话题的容器 */ /* 单个话题的容器 */
@ -108,4 +211,19 @@ onMounted(async () => {
scrollbar-width: thin; scrollbar-width: thin;
scrollbar-color: var(--kungalgame-blue-4) var(--kungalgame-blue-1); scrollbar-color: var(--kungalgame-blue-4) var(--kungalgame-blue-1);
} }
.order-enter-active,
.order-leave-active {
transition: all 0.25s ease-out;
}
.order-enter-from {
opacity: 0;
transform: translateY(-30px);
}
.order-leave-to {
opacity: 0;
transform: translateY(30px);
}
</style> </style>