complete main page fetch topic data

This commit is contained in:
KUN1007 2023-06-08 22:39:53 +08:00
parent ee14725f5f
commit f696e50ddc
8 changed files with 1989 additions and 44 deletions

File diff suppressed because it is too large Load diff

View file

@ -13,3 +13,25 @@ export async function getTopicReplyApi(id: number) {
export async function getTopicCommentApi(id: number) { export async function getTopicCommentApi(id: number) {
return await request<KUNGalgameTopic>(`/topic/comment/${id}`) return await request<KUNGalgameTopic>(`/topic/comment/${id}`)
} }
// 获取指定范围内的帖子数据
export async function getTopicRangeApi(
start: number,
count: number
): Promise<KUNGalgameTopic[]> {
const url = `http://127.0.0.1:10007/topic/topics/kun?start=${start}&count=${count}`
const options = {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
}
try {
const response = await request<KUNGalgameTopic[]>(url, options)
return response
} catch (error) {
console.error('Error fetching topics:', error)
throw error
}
}

23
src/utils/formatTime.ts Normal file
View file

@ -0,0 +1,23 @@
import dayjs from 'dayjs'
export const formatPublishTime = (time: number) => {
const publishTime = dayjs(time)
const now = dayjs()
const diffInSeconds = now.diff(publishTime, 'second')
if (diffInSeconds < 60) {
return `${diffInSeconds}秒前`
} else if (diffInSeconds < 3600) {
const diffInMinutes = Math.floor(diffInSeconds / 60)
return `${diffInMinutes}分钟前`
} else if (diffInSeconds < 86400) {
const diffInHours = Math.floor(diffInSeconds / 3600)
return `${diffInHours}小时前`
} else if (diffInSeconds < 2592000) {
const diffInDays = Math.floor(diffInSeconds / 86400)
return `${diffInDays}天前`
} else {
const diffInMonths = Math.floor(diffInSeconds / 2592000)
return `${diffInMonths}月前`
}
}

View file

@ -1,31 +1,36 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from 'vue'
import { getTopicRangeApi } from '@/api/topic/index'
import { KUNGalgameTopic } from '@/api/topic/types/topic'
import SingleTopic from './SingleTopic.vue' import SingleTopic from './SingleTopic.vue'
//
const topics = ref<KUNGalgameTopic[]>([])
// fetchTopics
onMounted(async () => {
try {
const start = 0 //
const count = 17 //
const fetchedTopics = await getTopicRangeApi(start, count)
console.log(fetchedTopics)
topics.value = fetchedTopics
} catch (error) {
console.error('Error fetching topics:', error)
}
})
</script> </script>
<template> <template>
<div class="topic-container"> <div class="topic-container">
<SingleTopic /> <div v-for="topic in topics" :key="topic.topicId">
<SingleTopic /> <SingleTopic :data="topic" />
<SingleTopic /> </div>
<SingleTopic />
<SingleTopic />
<SingleTopic />
<SingleTopic />
<SingleTopic />
<SingleTopic />
<SingleTopic />
<SingleTopic />
<SingleTopic />
<SingleTopic />
<SingleTopic />
<SingleTopic />
<SingleTopic />
<SingleTopic />
<SingleTopic />
<SingleTopic />
<SingleTopic />
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
/* 帖子区容器 */ /* 帖子区容器 */
.topic-container { .topic-container {

View file

@ -1,15 +1,20 @@
<script setup lang="ts"> <script setup lang="ts">
import UserPart from './UserPart.vue' import UserPart from './UserPart.vue'
import TopicPart from './TopicPart.vue' import TopicPart from './TopicPart.vue'
const props = defineProps(['data'])
</script> </script>
<template> <template>
<div class="topic"> <div class="topic">
<UserPart /> <UserPart :kungalgamer="props.data.topicAuthor" />
<!-- TODO: 进入指定帖子的路由 -->
<router-link to="/topic"> <router-link to="/topic">
<TopicPart /> <TopicPart :data="props.data" />
</router-link> </router-link>
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
/* 单个帖子 */ /* 单个帖子 */
.topic { .topic {

View file

@ -1,5 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { Icon } from '@iconify/vue' import { Icon } from '@iconify/vue'
defineProps(['data'])
</script> </script>
<template> <template>
<!-- 帖子信息 --> <!-- 帖子信息 -->
@ -9,15 +11,25 @@ import { Icon } from '@iconify/vue'
<!-- 帖子的标题 --> <!-- 帖子的标题 -->
<div class="topic-title"> <div class="topic-title">
<div class="topic-title-container"> <div class="topic-title-container">
<a href="#"><span>啊这可海星</span></a> <span>{{ $props.data.topicTitle }}</span>
</div> </div>
</div> </div>
<!-- 帖子发布日期 --> <!-- 帖子发布日期 -->
<div class="topic-status"> <div class="topic-status">
<ul> <ul>
<li><Icon icon="ic:outline-remove-red-eye" />1007</li> <li>
<li><Icon icon="line-md:thumbs-up-twotone" />1007</li> <Icon icon="ic:outline-remove-red-eye" />{{
<li><Icon icon="ri:reply-line" />1007</li> $props.data.topicViews
}}
</li>
<li>
<Icon icon="line-md:thumbs-up-twotone" />{{
$props.data.topicLikes
}}
</li>
<li>
<Icon icon="ri:reply-line" />{{ $props.data.topicReplyCount }}
</li>
</ul> </ul>
</div> </div>
<!-- 帖子的状态点赞数等 --> <!-- 帖子的状态点赞数等 -->
@ -29,7 +41,7 @@ import { Icon } from '@iconify/vue'
<div class="topic-introduction"> <div class="topic-introduction">
<div class="topic-introduction-text"> <div class="topic-introduction-text">
<p> <p>
鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲鲲 {{ $props.data.topicContent }}
</p> </p>
</div> </div>
</div> </div>

View file

@ -1,22 +1,23 @@
<script setup lang="ts"></script> <script setup lang="ts">
const props = defineProps(['kungalgamer'])
console.log(props)
</script>
<template> <template>
<!-- 帖子发布者个人信息 --> <!-- 帖子发布者个人信息 -->
<div class="kungalgamer-topic-info"> <div class="kungalgamer">
<!-- 发布者头像 --> <!-- 发布者头像 -->
<div class="kungalgamer-topic-avatar"> <div class="avatar">
<a href="#"><img src="@/assets/images/topic.jpg" alt="鲲" /></a> <a href="#"><img src="@/assets/images/topic.jpg" alt="鲲" /></a>
</div> </div>
<!-- 发布者姓名 --> <!-- 发布者姓名 -->
<div class="kungalgamer-name"> <div class="name">
<a href="#"><span>鲲最可爱</span></a> <a href="#"><span>鲲最可爱</span></a>
</div> </div>
<!-- 发布者相关信息 -->
<!-- <div class="kungalgamer-ranking"></div> -->
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
/* 发帖人信息 */ /* 发帖人信息 */
.kungalgamer-topic-info { .kungalgamer {
width: 70px; width: 70px;
height: 100%; height: 100%;
/* 单个帖子左右两部分发布人信息和帖子概览均为竖向弹性盒 */ /* 单个帖子左右两部分发布人信息和帖子概览均为竖向弹性盒 */
@ -26,38 +27,38 @@
/* 发帖人信息距离帖子概览的距离 */ /* 发帖人信息距离帖子概览的距离 */
margin: 0 5px; margin: 0 5px;
} }
.kungalgamer-topic-avatar, .avatar,
.kungalgamer-name { .name {
width: 100%; width: 100%;
height: 1px; height: 1px;
} }
/* 头像图片容器设置 */ /* 头像图片容器设置 */
.kungalgamer-topic-avatar { .avatar {
/* 头像部分占发布人信息区域的比例 */ /* 头像部分占发布人信息区域的比例 */
flex-grow: 3; flex-grow: 3;
display: flex; display: flex;
justify-content: center; justify-content: center;
} }
.kungalgamer-topic-avatar a { .avatar a {
width: 100%; width: 100%;
display: flex; display: flex;
justify-content: center; justify-content: center;
flex-grow: 1; flex-grow: 1;
} }
/* 头像图片样式设置 */ /* 头像图片样式设置 */
.kungalgamer-topic-avatar img { .avatar img {
padding: 2px; padding: 2px;
border-radius: 50%; border-radius: 50%;
/* 页面缩小时头像缩小 */ /* 页面缩小时头像缩小 */
display: inline-block; display: inline-block;
} }
/* 发帖人昵称位置设置 */ /* 发帖人昵称位置设置 */
.kungalgamer-name { .name {
border-top: 1px solid var(--kungalgame-gray-2); border-top: 1px solid var(--kungalgame-gray-2);
flex-grow: 1; flex-grow: 1;
display: flex; display: flex;
} }
.kungalgamer-name a { .name a {
display: flex; display: flex;
width: 1px; width: 1px;
flex-grow: 1; flex-grow: 1;
@ -65,7 +66,7 @@
justify-content: center; justify-content: center;
} }
/* 发帖人昵称样式设置 */ /* 发帖人昵称样式设置 */
.kungalgamer-name span { .name span {
/* 页面缩小时省略不换行 */ /* 页面缩小时省略不换行 */
display: inline-block; display: inline-block;
overflow: hidden; overflow: hidden;

View file

@ -20,7 +20,7 @@ const router = useRouter()
// //
const loginMutation = useMutation(async (data: any) => { const loginMutation = useMutation(async (data: any) => {
const res = await request('http://127.0.0.1:10007/api/login', { const res: Response = await request('http://127.0.0.1:10007/api/login', {
method: 'POST', method: 'POST',
body: JSON.stringify(data), body: JSON.stringify(data),
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
@ -30,7 +30,7 @@ const loginMutation = useMutation(async (data: any) => {
// //
const registerMutation = useMutation(async (data: any) => { const registerMutation = useMutation(async (data: any) => {
const res = await request('http://127.0.0.1:10007/api/register', { const res: Response = await request('http://127.0.0.1:10007/api/register', {
method: 'POST', method: 'POST',
body: JSON.stringify(data), body: JSON.stringify(data),
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },