feat: topic page

This commit is contained in:
KUN1007 2023-08-27 22:27:13 +08:00
parent d615565b50
commit 51edb891ca
14 changed files with 128 additions and 93 deletions

View file

@ -15,7 +15,7 @@ export async function postEditNewTopicApi(
newTopicData
)
// 返回创建好的话题数据
// 返回创建好的话题 tid
return response
} catch (error) {
// 处理错误

View file

@ -7,7 +7,7 @@ const topicURLs = {
}
// 获取单个话题
export async function getTopicByTid(
export async function getTopicByTidApi(
tid: number
): Promise<Topic.TopicDetailResponseData> {
try {
@ -23,8 +23,8 @@ export async function getTopicByTid(
}
// 根据话题 id 获取话题回复
export async function getRepliesByPid(
request: Topic.ReplyRequestData
export async function getRepliesByPidApi(
request: Topic.TopicReplyRequestData
): Promise<Topic.TopicReplyResponseData> {
try {
const url = `${topicURLs.getRepliesByPid}/${request.tid}/reply`
@ -39,8 +39,8 @@ export async function getRepliesByPid(
}
// 获取一个回复下面的评论
export async function getCommentsByReplyRid(
request: Topic.ReplyRequestData
export async function getCommentsByReplyRidApi(
request: Topic.TopicReplyRequestData
): Promise<Topic.TopicReplyResponseData> {
try {
const url = `${topicURLs.getRepliesByPid}/${request.tid}/reply`

View file

@ -42,13 +42,16 @@ export interface TopicReplyRequestData {
export interface TopicReply {
rid: number
tid: number
floor: number
r_user: TopicUserInfo
to_user: TopicToUserInfo
edited: string
edited: number
content: string
upvote: number
likes: number
dislikes: number
tags: string
tags: string[]
time: number
cid: number[]
}
@ -58,5 +61,5 @@ export interface TopicComment {}
// 获取单个话题响应数据的格式
export type TopicDetailResponseData = KUNGalgameResponseData<TopicDetail>
// 单个话题回复响应数据的格式
export type TopicReplyResponseData = KUNGalgameResponseData<TopicReply>
// 单个话题回复响应数据的格式,返回的是多条回复数据,是一个数组
export type TopicReplyResponseData = KUNGalgameResponseData<TopicReply[]>

View file

@ -7,11 +7,10 @@ const topic: RouteRecordRaw[] = [
{
path: '/topic',
component: Layout,
redirect: '/topic/:tid',
children: [
{
name: 'Topic',
path: 'index',
path: ':tid',
// 路由懒加载
component: () => import('@/views/topic/KUNGalgameTopicPage.vue'),
// 使路由参数作为组件的 props 传递

View file

@ -1,8 +1,12 @@
/* 话题详情的 store */
import { defineStore } from 'pinia'
import { getRepliesByPid } from '@/api/index'
import { TopicReplyRequestData, TopicReplyResponseData } from '@/api/index'
import { getRepliesByPidApi, getTopicByTidApi } from '@/api/index'
import {
TopicDetailResponseData,
TopicReplyRequestData,
TopicReplyResponseData,
} from '@/api/index'
// 回复的缓存
interface ReplyDraft {
@ -59,6 +63,18 @@ export const useKUNGalgameTopicStore = defineStore({
},
}),
actions: {
// 获取单个话题
getTopicByTid(tid: number): Promise<TopicDetailResponseData> {
return new Promise((resolve, reject) => {
getTopicByTidApi(tid)
.then((res) => {
resolve(res)
})
.catch((error) => {
reject(error)
})
})
},
// 获取回复
getReplies(tid: number): Promise<TopicReplyResponseData> {
return new Promise((resolve, reject) => {
@ -69,7 +85,7 @@ export const useKUNGalgameTopicStore = defineStore({
sortField: this.replyRequest.sortField,
sortOrder: this.replyRequest.sortOrder,
}
getRepliesByPid(requestData)
getRepliesByPidApi(requestData)
.then((res) => {
resolve(res)
})

View file

@ -41,8 +41,15 @@ const handlePublish = async () => {
// tid
const tid = createdTopic.data.tid
console.log(tid)
// push tid
router.push({ name: 'Topic', params: { tid } })
router.push({
name: 'Topic',
params: {
tid: tid,
},
})
message.info('AlertInfo.edit.publishSuccess')
// 使 pinia $reset

View file

@ -38,9 +38,9 @@ onBeforeMount(() => {
<template>
<!-- 回复面板组件 -->
<ReplyPanel />
<!-- 总容器 -->
<div class="main-wrapper">
<ReplyPanel />
<!-- 下面话题详情区的容器 -->
<div class="topic-wrapper">
<!-- 下方可视内容区的容器 -->

View file

@ -6,24 +6,21 @@
页面被拆成 3 个大组件这是话题部分
-->
<script setup lang="ts">
import { onMounted, ref, watch } from 'vue'
import { onMounted, ref, watch, computed } from 'vue'
import Master from './components/Master.vue'
import Reply from './components/Reply.vue'
import { getTopicByTid } from '@/api/topic/index'
import { TopicDetailResponseData } from '@/api/topic/types/topic'
import { HomeTopic } from '@/api/index'
import { TopicReplyRequestData, TopicReplyResponseData } from '@/api/index'
import { TopicDetail, TopicReply } from '@/api/index'
// topic store
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
import { storeToRefs } from 'pinia'
const requestData = storeToRefs(useKUNGalgameTopicStore())
import { useRoute } from 'vue-router'
//
const topics = ref<HomeTopic[]>([])
const route = useRoute()
const requestData = storeToRefs(useKUNGalgameTopicStore())
// fetchTopics watch
// watch(
@ -34,23 +31,43 @@ const topics = ref<HomeTopic[]>([])
// { immediate: true }
// )
const topicData = ref<TopicDetailResponseData>()
const tid = computed(() => {
return Number(route.params.tid)
})
//
const topicData = ref<TopicDetail>()
//
const repliesData = ref<TopicReply[]>([])
/** 这里拿到的已经是后端返回回来的 data 数据了 */
onMounted(async () => {
const res = await getTopicByTid(1)
topicData.value = res
//
const topicResponseData = (
await useKUNGalgameTopicStore().getTopicByTid(tid.value)
).data
topicData.value = topicResponseData
//
const replyResponseData = (
await useKUNGalgameTopicStore().getReplies(tid.value)
).data
repliesData.value = replyResponseData
})
</script>
<template>
<div class="content-right-part">
<div class="content">
<Master v-if="topicData" :topicData="topicData" />
<Reply v-if="topicData" :replyIDs="topicData.data.rid" />
<Reply v-if="repliesData" :repliesData="repliesData" />
</div>
</template>
<style scoped>
<style lang="scss" scoped>
/* 右侧内容区 */
.content-right-part {
.content {
height: 100%;
width: 1px;
flex-grow: 4;

View file

@ -31,6 +31,7 @@ const props = defineProps<{
display: flex;
flex-direction: column;
padding: 0 20px;
margin-bottom: 20px;
color: var(--kungalgame-font-color-3);
}
/* 头像 */

View file

@ -6,8 +6,6 @@
import TopicFooter from '../components/TopicFooter.vue'
//
import Rewrite from '../components/Rewrite.vue'
//
import TopicContent from '../components/TopicContent.vue'
//
import KUNGalgamerInfo from '../components/KUNGalgamerInfo.vue'
//
@ -15,9 +13,9 @@ import Time from '../components/Time.vue'
//
import Tags from '../components/Tags.vue'
import { TopicDetailResponseData } from '@/api/topic/types/topic'
import { TopicDetail } from '@/api/topic/types/topic'
const topicData = defineProps<{
topicData: TopicDetailResponseData
topicData: TopicDetail
}>()
const {
@ -34,9 +32,7 @@ const {
edited,
user,
rid,
} = topicData.topicData?.data
console.log(topicData.topicData.data)
} = topicData.topicData
</script>
<template>
@ -74,7 +70,7 @@ console.log(topicData.topicData.data)
<!-- 话题的点赞数等信息 -->
<TopicFooter
:isOthersTopic="false"
:topicInfo="{ views, likes, dislikes, replies, upvotes }"
:info="{ views, likes, dislikes, replies, upvotes }"
/>
</div>
</div>
@ -96,6 +92,7 @@ console.log(topicData.topicData.data)
}
/* 楼主话题内容区的容器 */
.content-container {
flex-grow: 1;
width: 100%;
display: flex;
flex-direction: column;

View file

@ -12,24 +12,30 @@ import TopicFooter from './../components/TopicFooter.vue'
import Time from './../components/Time.vue'
//
import Tags from './../components/Tags.vue'
//
import TopicContent from './../components/TopicContent.vue'
//
import Rewrite from './../components/Rewrite.vue'
//
import KUNGalgamerInfo from './../components/KUNGalgamerInfo.vue'
const props = defineProps<{
replyIDs: number[]
import { TopicReply } from '@/api/index'
defineProps<{
repliesData: TopicReply[]
}>()
</script>
<template>
<!-- 其它人的回复 -->
<div class="other-topic-container">
<div
class="other-topic-container"
v-for="(reply, index) in repliesData"
:key="index"
>
<!-- 每个人的单个话题 -->
<!-- 楼层标志 -->
<div class="floor"><span>F1</span></div>
<div class="floor">
<span>F{{ reply.floor }}</span>
</div>
<!-- 其他人话题内容区的容器 -->
<div class="container">
<!-- 其它人回复的内容区 -->
@ -37,7 +43,7 @@ const props = defineProps<{
<!-- 其他人回复的上部 -->
<div class="article">
<!-- 其它人回复的上部左侧区域 -->
<KUNGalgamerInfo />
<KUNGalgamerInfo :user="reply.r_user" />
<!-- 其它人回复的上部右侧区域 -->
<div class="right">
<!-- 右侧的上部区域 -->
@ -46,24 +52,35 @@ const props = defineProps<{
<div class="reply">
<!-- TODO: 跳转到页面中话题的位置 -->
<span
>回复给@<router-link to="#">啊这可海星啊这</router-link></span
>回复给 @
<router-link to="#">{{
reply.to_user.name
}}</router-link></span
>
</div>
<!-- 上部区域的右边 -->
<Rewrite />
<Rewrite v-if="reply.edited" :time="reply.edited" />
</div>
<!-- 右侧部分分文本 -->
<TopicContent />
<div class="text" v-html="reply.content"></div>
</div>
</div>
<!-- 其他人回复的下部 -->
<div class="bottom">
<Tags />
<Time />
<Tags :tags="reply.tags" />
<Time :time="reply.time" />
</div>
</div>
<!-- 其它人回复的底部 -->
<TopicFooter :isOthersTopic="true" />
<TopicFooter
:isOthersTopic="true"
:info="{
likes: reply.likes,
dislikes: reply.dislikes,
replies: reply.cid.length,
upvotes: reply.upvote,
}"
/>
<Comments />
</div>
</div>
@ -163,6 +180,14 @@ const props = defineProps<{
}
}
/* 内容区右侧的话题展示区 */
.text {
font-size: 15px;
padding: 17px;
border-left: 1px solid var(--kungalgame-blue-1);
color: var(--kungalgame-font-color-3);
}
@media (max-width: 1000px) {
.top {
flex-direction: column;

View file

@ -2,8 +2,8 @@
<script setup lang="ts">
import { Icon } from '@iconify/vue'
const props = defineProps<{
time: number
defineProps<{
time?: number
}>()
</script>

View file

@ -1,31 +0,0 @@
<!-- 这是话题的内容区 -->
<script setup lang="ts"></script>
<template>
<!-- 内容区右侧的话题展示区 -->
<div class="text">
啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星
啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星
啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星
啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星
啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星
啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星
啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星
啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星
啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星
啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星
啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星
啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星
啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星啊这可海星
</div>
</template>
<style lang="scss" scoped>
/* 内容区右侧的话题展示区 */
.text {
font-size: 15px;
padding: 17px;
border-left: 1px solid var(--kungalgame-blue-1);
color: var(--kungalgame-font-color-3);
}
</style>

View file

@ -15,12 +15,13 @@ const { isEdit } = storeToRefs(settingsStore)
//
defineProps<{
isOthersTopic?: boolean
topicInfo?: {
views: number
info?: {
views?: number
likes: number
dislikes: number
replies: number
upvotes: number
components?: number
}
}>()
@ -38,22 +39,22 @@ const handelReply = () => {
<!-- 查看数量 -->
<li>
<span class="icon"><Icon icon="ic:outline-remove-red-eye" /></span>
{{ topicInfo?.views }}
{{ info?.views }}
</li>
<!-- 推话题 -->
<li>
<span class="icon"><Icon icon="bi:rocket" /></span>
{{ topicInfo?.upvotes }}
{{ info?.upvotes }}
</li>
<!-- 点赞 -->
<li>
<span class="icon"><Icon icon="line-md:thumbs-up-twotone" /></span>
{{ topicInfo?.likes }}
{{ info?.likes }}
</li>
<!-- -->
<li>
<span class="icon"><Icon icon="line-md:thumbs-down-twotone" /></span>
{{ topicInfo?.dislikes }}
{{ info?.dislikes }}
</li>
</ul>
</div>