feat: topic page
This commit is contained in:
parent
d615565b50
commit
51edb891ca
|
@ -15,7 +15,7 @@ export async function postEditNewTopicApi(
|
|||
newTopicData
|
||||
)
|
||||
|
||||
// 返回创建好的话题数据
|
||||
// 返回创建好的话题 tid
|
||||
return response
|
||||
} catch (error) {
|
||||
// 处理错误
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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[]>
|
||||
|
|
|
@ -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 传递
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
|
|
|
@ -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 重置状态
|
||||
|
|
|
@ -38,9 +38,9 @@ onBeforeMount(() => {
|
|||
|
||||
<template>
|
||||
<!-- 回复面板组件 -->
|
||||
<ReplyPanel />
|
||||
<!-- 总容器 -->
|
||||
<div class="main-wrapper">
|
||||
<ReplyPanel />
|
||||
<!-- 下面话题详情区的容器 -->
|
||||
<div class="topic-wrapper">
|
||||
<!-- 下方可视内容区的容器 -->
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -31,6 +31,7 @@ const props = defineProps<{
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0 20px;
|
||||
margin-bottom: 20px;
|
||||
color: var(--kungalgame-font-color-3);
|
||||
}
|
||||
/* 头像 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
<script setup lang="ts">
|
||||
import { Icon } from '@iconify/vue'
|
||||
|
||||
const props = defineProps<{
|
||||
time: number
|
||||
defineProps<{
|
||||
time?: number
|
||||
}>()
|
||||
</script>
|
||||
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue