feat: ranking page topic
This commit is contained in:
parent
e401702c0a
commit
9d4a34aa72
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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">
|
||||||
<!-- 萌萌点 -->
|
<!-- 萌萌点 -->
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in a new issue