feat: ranking page topic
This commit is contained in:
parent
fc395aac33
commit
f14f548ba0
|
@ -2,7 +2,7 @@ export interface RankingGetTopicsRequestData {
|
|||
page: number
|
||||
limit: number
|
||||
sortField: string
|
||||
sortOrder: string
|
||||
sortOrder: 'asc' | 'desc'
|
||||
}
|
||||
|
||||
export interface RankingTopics {
|
||||
|
|
|
@ -34,13 +34,13 @@ export const navSortItem: Sort[] = [
|
|||
index: 5,
|
||||
icon: 'line-md:thumbs-up-twotone',
|
||||
name: 'likes',
|
||||
sortField: 'likes',
|
||||
sortField: 'likes_count',
|
||||
},
|
||||
{
|
||||
index: 6,
|
||||
icon: 'ri:reply-line',
|
||||
name: 'replies',
|
||||
sortField: 'replies',
|
||||
sortField: 'replies_count',
|
||||
},
|
||||
{
|
||||
index: 7,
|
||||
|
|
|
@ -6,7 +6,7 @@ import KUNgalgamer from './KUNGalgamer.vue'
|
|||
<!-- 用户排行 -->
|
||||
<div class="kungalgamer-ranking">
|
||||
<!-- 用户排行标题 -->
|
||||
<div class="kungalgamer-title">最萌的萝莉</div>
|
||||
<div class="kungalgamer-title">用户</div>
|
||||
<!-- 用户排行的交互 -->
|
||||
<div class="kungalgamer-nav">
|
||||
<!-- 萌萌点 -->
|
||||
|
|
|
@ -10,7 +10,7 @@ const props = defineProps<{
|
|||
|
||||
const topics = computed(() => props.topics)
|
||||
|
||||
const icons: Record<string, string> = {
|
||||
const iconMap: Record<string, string> = {
|
||||
popularity: 'bi:fire',
|
||||
upvotes_count: 'bi:rocket',
|
||||
views: 'ic:outline-remove-red-eye',
|
||||
|
@ -26,8 +26,10 @@ const parseTopicNumber = (field: string | string[]) => {
|
|||
</script>
|
||||
|
||||
<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">
|
||||
{{ topic.title }}
|
||||
|
@ -35,24 +37,39 @@ const parseTopicNumber = (field: string | string[]) => {
|
|||
<!-- 话题的其它信息 -->
|
||||
<div class="detail">
|
||||
<!-- 浏览数 -->
|
||||
<span>
|
||||
<Icon :icon="icons[props.field]" />
|
||||
{{ parseTopicNumber(topic.field) }}
|
||||
</span>
|
||||
|
||||
<Icon :icon="iconMap[props.field]" />
|
||||
<span>{{ parseTopicNumber(topic.field) }}</span>
|
||||
</div>
|
||||
</RouterLink>
|
||||
</div>
|
||||
</TransitionGroup>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 单个话题 */
|
||||
.single-topic {
|
||||
a {
|
||||
flex-shrink: 0;
|
||||
height: 37px;
|
||||
border-bottom: 1px solid var(--kungalgame-blue-4);
|
||||
margin: 7px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
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 {
|
||||
|
@ -60,16 +77,31 @@ const parseTopicNumber = (field: string | string[]) => {
|
|||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
/* 话题的其它信息 */
|
||||
.v-l-c-t {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.detail {
|
||||
display: flex;
|
||||
span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: var(--kungalgame-blue-4);
|
||||
span {
|
||||
color: var(--kungalgame-font-color-3);
|
||||
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>
|
||||
|
|
|
@ -9,8 +9,10 @@ import { storeToRefs } from 'pinia'
|
|||
import type { RankingTopics } from '@/api'
|
||||
import { topicNavSortItem } from './navSortItem'
|
||||
|
||||
const { topic, user } = storeToRefs(useKUNGalgameRankingStore())
|
||||
const { topic } = storeToRefs(useKUNGalgameRankingStore())
|
||||
const topics = ref<RankingTopics[]>([])
|
||||
// 升序降序
|
||||
const isAscending = ref(false)
|
||||
|
||||
// 获取话题
|
||||
const getTopics = async () => {
|
||||
|
@ -18,6 +20,15 @@ const getTopics = async () => {
|
|||
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(
|
||||
() => topic,
|
||||
|
@ -31,29 +42,53 @@ watch(
|
|||
onMounted(async () => {
|
||||
topics.value = await getTopics()
|
||||
})
|
||||
|
||||
// 切换排序方式
|
||||
const handleClickSortOrder = () => {
|
||||
isAscending.value = !isAscending.value
|
||||
if (isAscending.value) {
|
||||
topic.value.sortOrder = 'asc'
|
||||
} else {
|
||||
topic.value.sortOrder = 'desc'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 话题排行 -->
|
||||
<div class="topic">
|
||||
<!-- 话题排行标题 -->
|
||||
<div class="title">最萌的话题</div>
|
||||
<div class="title">话题</div>
|
||||
<!-- 话题排行的交互 -->
|
||||
<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
|
||||
class="sort-item"
|
||||
class="item"
|
||||
v-for="kun in topicNavSortItem"
|
||||
:key="kun.index"
|
||||
@click="topic.sortField = kun.sortField"
|
||||
>
|
||||
<span><Icon class="icon-item" :icon="kun.icon" /></span>
|
||||
<span>按时间排序</span>
|
||||
<span><Icon class="icon" :icon="kun.icon" /></span>
|
||||
<span>{{ kun.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -69,6 +104,7 @@ onMounted(async () => {
|
|||
/* 话题排行 */
|
||||
.topic {
|
||||
width: 50%;
|
||||
height: calc(100% - 50px - 20px - 40px);
|
||||
}
|
||||
/* 话题排行标题 */
|
||||
.title {
|
||||
|
@ -82,8 +118,75 @@ onMounted(async () => {
|
|||
}
|
||||
/* 话题排行的交互 */
|
||||
.nav {
|
||||
height: 40px;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
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-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>
|
||||
|
|
Loading…
Reference in a new issue