Update API formatting and routing structure

This commit is contained in:
wangqiao
2025-08-28 11:29:20 +08:00
parent 9edc63ff4f
commit 3f1431f972
9 changed files with 263 additions and 118 deletions

View File

@ -20,7 +20,7 @@ import type {
* @return {Promise}
*/
export const page = (params: TpageReq) => {
return useDollarFetchRequest.get<IResponse<TpageRes>>('/prod-api/app-api/business/posts/page', {query: params})
return useDollarFetchRequest.get<IResponse<TpageRes>>('/prod-api/app-api/business/posts/page', { query: params })
}
/**
@ -56,7 +56,7 @@ export const postsDelete = (params: { id: number }) => {
* @return {Promise}
*/
export const getChannelDetail = (params: { id: string }) => {
return useFetchRequest.get<IResponse<TGetChannelPostsRes>>('/prod-api/app-api/business/posts/get', params)
return useFetchRequest.get<IResponse<TGetChannelPostsRes>>('/prod-api/app-api/business/posts/get', { query: params })
}
/**
@ -64,7 +64,7 @@ export const getChannelDetail = (params: { id: string }) => {
* @return {Promise}
*/
export const postscommentpage = (params: { postsId: string; pageNo: number; pageSize: number }) => {
return useFetchRequest.get<IResponse<PageResultPostsCommentRespVO>>('/prod-api/app-api/business/posts-comment/page', params)
return useFetchRequest.get<IResponse<PageResultPostsCommentRespVO>>('/prod-api/app-api/business/posts-comment/page', { query: params })
}
/**
* 创建帖子评论
@ -93,7 +93,7 @@ export const sendKefuMessage = (params: SingleMessageVo) => {
* 获得消息记录分页
*/
export const getMessagePage = (params: { pageNo: number; pageSize: number; fromId?: number; msgType?: number; topic: string }) => {
return useDollarFetchRequest.get<IResponse<PageResultMessageRespVO>>('/prod-api/app-api/mqtt/message/page', {query:params})
return useDollarFetchRequest.get<IResponse<PageResultMessageRespVO>>('/prod-api/app-api/mqtt/message/page', { query: params })
}
/**
@ -107,7 +107,7 @@ export const conversationList = () => {
* 获取聊天记录
*/
export const getChatDetail = (params: { sessionId: number; pageNo: number; pageSize: number }) => {
return useDollarFetchRequest.get<IResponse<PageResultMessageRespVO>>('/prod-api/app-api/mqtt/message/pageBySession', {query:params})
return useDollarFetchRequest.get<IResponse<PageResultMessageRespVO>>('/prod-api/app-api/mqtt/message/pageBySession', { query: params })
}
/**
@ -121,7 +121,7 @@ export const clearUnreadMessage = (params: { id: number }) => {
* 获得论坛频道
*/
export const getChannelLunTanDetail = (params: { id: string }) => {
return useDollarFetchRequest.get<IResponse<ChannelRespVO>>('/prod-api/app-api/business/channel/get', {query:params})
return useDollarFetchRequest.get<IResponse<ChannelRespVO>>('/prod-api/app-api/business/channel/get', { query: params })
}
/**

View File

@ -12,7 +12,7 @@ export default defineNuxtConfig({
ssr: true,
modules: ['@unocss/nuxt', '@pinia/nuxt', '@element-plus/nuxt', 'pinia-plugin-persistedstate/nuxt', 'nuxt-swiper'],
css: ['@unocss/reset/tailwind.css', 'element-plus/dist/index.css', '~/assets/scss/app.scss'],
css: ['element-plus/dist/index.css', '~/assets/scss/app.scss'],
vite: {
css: {
preprocessorOptions: {
@ -119,7 +119,7 @@ export default defineNuxtConfig({
},
build: {
transpile: ['vueuc', '@css-render/vue3-ssr', '@unocss', '@tinymce/tinymce-vue', 'tinymce'],
transpile: ['vueuc', '@css-render/vue3-ssr', '@tinymce/tinymce-vue', 'tinymce'],
},
plugins: [
// 在这里引入插件

View File

@ -0,0 +1,99 @@
<template>
<!-- 导航 -->
<KlNavTab active="交流频道" />
<div class="ma-auto mt-[30px] w-[1440px] flex">
<LeftContent v-model="pageReq.channelId" v-model:channelIdList="channelIdList"></LeftContent>
<RightContent v-model="pageRes" v-model:lun-tan-res="lunTanRes" v-model:page-no="pageReq.pageNo" @update-page-no="handleUpdatePageNo"></RightContent>
</div>
</template>
<script setup lang="ts">
import KlNavTab from '~/components/kl-nav-tab/index.vue'
import LeftContent from '../components/LeftContent.vue'
import RightContent from '../components/RightContent.vue'
import { page, getChannelLunTanDetail, list } from '~/api/channel/index'
import { reactive, watch, ref } from 'vue'
import type { TpageRes, ChannelRespVO } from '~/api/channel/types'
const route = useRoute()
const channelId = computed(() => (route.params.channelId as string) || '')
const pageNo = computed(() => Number(route.params.pageNo) || 1)
const pageReq = reactive({
pageNo: pageNo.value,
pageSize: 10,
channelId: channelId.value, // 频道ID
})
// const pageRes = reactive<TpageRes>({
// list: [],
// total: 0,
// })
// 获取频道列表
const { data: channelIdList } = await useAsyncData(`prod-api/app-api/business/channel/list-${Date.now()}`, async () => {
const res = await list()
return res.data as any[]
})
console.log(channelIdList)
// 获取第一个论坛详情
// if (!channelIdList.value?.length) return
const { data: lunTanRes, execute: refreshLunTanDetail } = await useAsyncData(
`prod-api/app-api/business/channel/detail-${Date.now()}`,
async () => {
if (!channelId.value) return null // 无参数时不请求
const res = await getChannelLunTanDetail({
id: channelId.value,
})
return res.data as ChannelRespVO
},
{
immediate: true,
}
)
const { data: pageRes, refresh: getPage } = await useAsyncData(`prod-api/app-api/business/posts/page-${Date.now()}`, async () => {
const res = await page(pageReq)
return res.data as TpageRes
})
// 获得频道帖子分页
// const getPage = () => {
// page(pageReq).then((res) => {
// pageRes.list = res.data.list
// pageRes.total = res.data.total
// })
// }
// getPage()
const handleUpdatePageNo = (pageNo: number) => {
pageReq.pageNo = pageNo
navigateTo(`/channel/${channelId.value}/${pageNo}`)
// getPage()
}
// 获取论坛详情
// const lunTanRes = ref({} as ChannelRespVO)
// const getLunTanDetaiil = (val: string) => {
// getChannelLunTanDetail({
// id: val,
// }).then((res) => {
// lunTanRes.value = res.data
// })
// }
// watch(
// () => channelId.value,
// (val) => {
// if (val) {
// // 更新分页请求的channelId
// pageReq.channelId = val
// // 重新请求分页数据和论坛详情
// getPage()
// refreshLunTanDetail() // 刷新论坛详情
// }
// }
// )
</script>
<style lang="scss" scoped></style>

View File

@ -4,12 +4,12 @@
<!-- Logo and Title Section -->
<div class="logo-title-section">
<div class="logo">
<img :src="lunTanRes.channelIcon" alt="JRS Logo" />
<img :src="lunTanRes?.channelIcon" alt="JRS Logo" />
</div>
<div class="title-section">
<h1 class="main-title">#{{ lunTanRes.channelTitle }}</h1>
<h1 class="main-title">#{{ lunTanRes?.channelTitle }}</h1>
<div class="action-buttons">
<el-button v-if="!lunTanRes.isFollow" type="danger" class="subscribe-btn" @click="handleFollow"
<el-button v-if="!lunTanRes?.isFollow" type="danger" class="subscribe-btn" @click="handleFollow"
><el-icon class="mr-[4px] color-[#fff!]"><Plus /></el-icon> 关注
</el-button>
<el-button v-else type="danger" class="subscribe-btn" @click="handleUnfollow"> 取消关注 </el-button>
@ -21,7 +21,7 @@
<!-- Channel Info -->
<div class="channel-info">
<span class="info-item">话题介绍</span>
<span class="info-item">{{ lunTanRes.channelProfile }}</span>
<span class="info-item">{{ lunTanRes?.channelProfile }}</span>
</div>
<!-- Stats -->
@ -32,11 +32,11 @@
</div>
<div class="stats-item">
<span class="stats-label">关注人数</span>
<span class="stats-value"><i class="el-icon-arrow-up"></i> {{ lunTanRes.followCount }}</span>
<span class="stats-value"><i class="el-icon-arrow-up"></i> {{ lunTanRes?.followCount }}</span>
</div>
<div class="stats-item">
<span class="stats-label">当前有</span>
<span class="stats-value"><i class="el-icon-arrow-up"></i> {{ lunTanRes.chatUserCount }}人聊天</span>
<span class="stats-value"><i class="el-icon-arrow-up"></i> {{ lunTanRes?.chatUserCount }}人聊天</span>
<span class="stats-value ml-[2px] cursor-pointer color-[#1a65ff!]" @click="handleChat">立即加入</span>
</div>
</div>
@ -44,8 +44,8 @@
<!-- Tags -->
<div class="channel-tags">
<span class="tag-label">标签:</span>
<span v-for="(item, index) in lunTanRes.hotTags" :key="index" class="tag-item"
>{{ item }}{{ index === lunTanRes.hotTags.length - 1 ? '' : '、' }}</span
<span v-for="(item, index) in lunTanRes?.hotTags" :key="index" class="tag-item"
>{{ item }}{{ index === lunTanRes!.hotTags.length - 1 ? '' : '、' }}</span
>
</div>
</div>
@ -55,9 +55,9 @@
<ChatPage
v-if="isChat"
v-model:is-chat="isChat"
:chat-title="lunTanRes.channelTitle"
:chat-description="lunTanRes.channelProfile"
:channel-id="lunTanRes.channelId"
:chat-title="lunTanRes!.channelTitle"
:chat-description="lunTanRes!.channelProfile"
:channel-id="lunTanRes!.channelId"
/>
</div>
</template>
@ -71,25 +71,25 @@
import useUserStore from '~/stores/user'
const userStore = useUserStore()
const lunTanRes = defineModel<ChannelRespVO>('modelValue', {
const lunTanRes = defineModel<ChannelRespVO | null>('modelValue', {
required: true,
})
const handleClick = () => {
navigateTo('/channel/create?channelId=' + lunTanRes.value.channelId)
navigateTo('/channel/create?channelId=' + lunTanRes.value?.channelId)
}
const handleFollow = () => {
createChannelFollow({ channelId: lunTanRes.value.channelId }).then((res) => {
createChannelFollow({ channelId: lunTanRes.value!.channelId }).then((res) => {
if (res.code === 0) {
lunTanRes.value.isFollow = true
lunTanRes.value!.isFollow = true
ElMessage.success('关注成功')
}
})
}
const handleUnfollow = () => {
deleteChannelFollow({ channelId: lunTanRes.value.channelId }).then((res) => {
deleteChannelFollow({ channelId: lunTanRes.value!.channelId }).then((res) => {
if (res.code === 0) {
lunTanRes.value.isFollow = false
lunTanRes.value!.isFollow = false
ElMessage.success('取消关注成功')
}
})
@ -103,7 +103,7 @@
ElMessage.warning('请先登录')
return
}
await userStore.mqttClient?.subscribe(`zbjk_message_group/${lunTanRes.value.channelId}`)
await userStore.mqttClient?.subscribe(`zbjk_message_group/${lunTanRes.value!.channelId}`)
isChat.value = true
}
</script>

View File

@ -16,27 +16,32 @@
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { list } from '~/api/channel/index'
// import { ref } from 'vue'
// import { list } from '~/api/channel/index'
const channelId = defineModel('modelValue', {
required: true,
})
/** 获取频道列表 */
const channelIdList = ref<any>([])
const getChannelIdList = () => {
list().then((res) => {
channelIdList.value = res.data
if (channelIdList.value.length > 0) {
channelId.value = channelIdList.value[0].channelId
}
const channelIdList = defineModel<any[]>('channelIdList', {
required: true,
})
}
getChannelIdList()
/** 获取频道列表 */
// const channelIdList = ref<any>([])
// const getChannelIdList = () => {
// list().then((res) => {
// channelIdList.value = res.data
// if (channelIdList.value.length > 0) {
// channelId.value = channelIdList.value[0].channelId
// }
// })
// }
// getChannelIdList()
const handleClick = (id: number) => {
console.log(id)
channelId.value = id
navigateTo(`/channel/${id}/1`)
}
</script>

View File

@ -2,7 +2,7 @@
<!-- 用户信息 -->
<div class="flex flex-col">
<UserInfo></UserInfo>
<HotLlabel v-model="channelId" class="mt-18px"></HotLlabel>
<HotLlabel v-model="channelId" class="mt-18px" v-model:channelIdList="channelIdList"></HotLlabel>
</div>
</template>
@ -13,6 +13,10 @@
const channelId = defineModel('modelValue', {
required: true,
})
const channelIdList = defineModel<any>('channelIdList', {
required: true,
})
</script>
<style scoped></style>

View File

@ -1,7 +1,9 @@
<template>
<div class="ml-[19px] w-[100%]">
<ChannelHeader v-if="Object.keys(lunTanRes).length" v-model="lunTanRes"></ChannelHeader>
<div class="mb-[13px] box-border flex flex-1 flex-col cursor-pointer gap-[12px] border border-[#EEEEEE] rounded-[8px] border-solid bg-[#FFFFFF] px-[20px] py-[16px]">
<ChannelHeader v-if="Object.keys(lunTanRes || {}).length" v-model="lunTanRes"></ChannelHeader>
<div
class="mb-[13px] box-border flex flex-1 flex-col cursor-pointer gap-[12px] border border-[#EEEEEE] rounded-[8px] border-solid bg-[#FFFFFF] px-[20px] py-[16px]"
>
<div
v-for="(item, index) in pageRes?.list"
:key="index"
@ -46,7 +48,7 @@
const pageRes = defineModel<TpageRes | null>('modelValue', {
required: true,
})
const lunTanRes = defineModel<ChannelRespVO>('lunTanRes', {
const lunTanRes = defineModel<ChannelRespVO | null>('lunTanRes', {
required: true,
})
const pageNo = defineModel<number>('pageNo', {
@ -73,7 +75,7 @@
const handleClick = (channelId: number) => {
// 新开窗口
window.open(`/chat-detail?channelId=${channelId}`, '_blank')
navigateTo(`/chat-detail/${channelId}-1`)
}
</script>

View File

@ -2,8 +2,8 @@
<!-- 导航 -->
<KlNavTab active="交流频道" />
<div class="ma-auto mt-[30px] w-[1440px] flex">
<LeftContent v-model="pageReq.channelId"></LeftContent>
<RightContent v-model="pageRes" v-model:lun-tan-res="lunTanRes" v-model:page-no="pageReq.pageNo" @update-page-no="handleUpdatePageNo"></RightContent>
<LeftContent v-model="pageReq.channelId" v-model:channelIdList="channelIdList"></LeftContent>
<!-- <RightContent v-model="pageRes" v-model:lun-tan-res="lunTanRes" v-model:page-no="pageReq.pageNo" @update-page-no="handleUpdatePageNo"></RightContent> -->
</div>
</template>
@ -11,7 +11,7 @@
import KlNavTab from '~/components/kl-nav-tab/index.vue'
import LeftContent from './components/LeftContent.vue'
import RightContent from './components/RightContent.vue'
import { page, getChannelLunTanDetail } from '~/api/channel/index'
import { page, getChannelLunTanDetail, list } from '~/api/channel/index'
import { reactive, watch, ref } from 'vue'
import type { TpageRes, ChannelRespVO } from '~/api/channel/types'
@ -25,44 +25,59 @@
total: 0,
})
// 获取频道列表
const { data: channelIdList } = await useAsyncData(`prod-api/app-api/business/channel/list-${Date.now()}`, async () => {
const res = await list()
return res.data as any[]
})
// console.log(channelIdList)
// 获取第一个论坛详情
// if (!channelIdList.value?.length) return
// const { data: lunTanRes, execute } = await useAsyncData(`prod-api/app-api/business/channel/detail-${Date.now()}`, async () => {
// const res = await getChannelLunTanDetail({
// id: channelIdList.value?.[0].channelId,
// })
// return res.data as ChannelRespVO
// })
// const {data:pageRes, refresh:getPage} = await useAsyncData(`prod-api/app-api/business/posts/page-${Date.now()}`, async () => {
// const res = await page(pageReq)
// return res.data as TpageRes
// })
// 获得频道帖子分页
const getPage = () => {
page(pageReq).then((res) => {
pageRes.list = res.data.list
pageRes.total = res.data.total
})
}
getPage()
// const getPage = () => {
// page(pageReq).then((res) => {
// pageRes.list = res.data.list
// pageRes.total = res.data.total
// })
// }
// getPage()
const handleUpdatePageNo = (pageNo: number) => {
pageReq.pageNo = pageNo
getPage()
}
// const handleUpdatePageNo = (pageNo: number) => {
// pageReq.pageNo = pageNo
// getPage()
// }
// 获取论坛详情
const lunTanRes = ref({} as ChannelRespVO)
const getLunTanDetaiil = (val: string) => {
getChannelLunTanDetail({
id: val,
}).then((res) => {
lunTanRes.value = res.data
})
}
// const lunTanRes = ref({} as ChannelRespVO)
// const getLunTanDetaiil = (val: string) => {
// getChannelLunTanDetail({
// id: val,
// }).then((res) => {
// lunTanRes.value = res.data
// })
// }
watch(
() => pageReq.channelId,
() => channelIdList.value,
(val) => {
if (val) {
console.log(val);
getPage()
getLunTanDetaiil(val)
}
navigateTo(`/channel/${val[0].channelId}/1`)
}
},
{ immediate: true }
)
</script>

View File

@ -1,6 +1,6 @@
<template>
<KlNavTab />
<div class="ml-auto mr-auto mt-20px w1440 flex">
<div class="ml-auto mr-auto mt-20px w-1440px flex">
<div class="left box-border w-1019px border border-[#EEEEEE] rounded-12px border-solid bg-[#FFFFFF] px-42px py-30px">
<div class="title text-24px text-[#333333] font-bold">{{ channelDetail?.postsTitle }}</div>
<div class="mt-20px flex items-center justify-between border-b-1px border-b-[#eee] border-b-solid pb-14px">
@ -32,9 +32,9 @@
</div>
<div class="mt-30px">
<div class="h-48px w-938px rounded-1px bg-[#F8F8F8] pl-10px text-16px text-[#333333] font-normal line-height-50px"
>共有{{ commentList.total || 0 }}条评论</div
>共有{{ commentList?.total || 0 }}条评论</div
>
<div v-for="item in commentList.list" :key="item.commentId" class="mt-10px border-b-1px border-b-[#eee] border-b-solid pb-14px">
<div v-for="item in commentList?.list" :key="item.commentId" class="mt-10px border-b-1px border-b-[#eee] border-b-solid pb-14px">
<div class="flex items-center justify-between">
<div class="flex items-center">
<img :src="item.creatorAvatar" alt="" srcset="" class="relative top-12px h-50px w-49px rounded-full" />
@ -51,7 +51,7 @@
v-model:current-page="query.pageNo"
:page-size="query.pageSize"
layout="prev, pager, next"
:total="commentList.total"
:total="commentList?.total"
class="mt-10px"
@current-change="handleCurrentChange"
/>
@ -101,50 +101,69 @@
import { getChannelDetail, postscommentpage, createPostsComment } from '~/api/channel'
import type { TGetChannelPostsRes, PageResultPostsCommentRespVO } from '~/api/channel/types'
const route = useRoute()
const channelId = route.query.channelId as string
const channelId = computed(() => route.params.channelId as string)
const pageNo = computed(() => Number(route.params.pageNo))
const channelDetail = ref<TGetChannelPostsRes>()
const commentList = reactive<PageResultPostsCommentRespVO>({
list: [],
total: 0,
console.log(channelId.value, pageNo.value)
// const channelDetail = ref<TGetChannelPostsRes>()
// const commentList = reactive<PageResultPostsCommentRespVO>({
// list: [],
// total: 0,
// })
const { data: channelDetail } = await useAsyncData(`prod-api/app-api/business/posts/detail-${Date.now()}`, async () => {
const res = await getChannelDetail({
id: channelId.value,
})
const getChannel = () => {
getChannelDetail({
id: channelId,
}).then((res) => {
if (res.code === 0) {
channelDetail.value = res.data
}
return res.data as TGetChannelPostsRes
})
}
// const getChannel = () => {
// getChannelDetail({
// id: channelId,
// }).then((res) => {
// if (res.code === 0) {
// channelDetail.value = res.data
// }
// })
// }
const query = reactive({
pageNo: 1,
pageNo: pageNo.value,
pageSize: 4,
})
const getComment = () => {
postscommentpage({
postsId: channelId,
pageNo: query.pageNo,
pageSize: query.pageSize,
}).then((res) => {
if (res.code === 0) {
commentList.list = res.data.list
commentList.total = res.data.total
}
const { data: commentList, refresh } = await useAsyncData(`prod-api/app-api/business/posts/comment/page-${Date.now()}`, async () => {
const res = await postscommentpage({
postsId: channelId.value,
pageNo: pageNo.value,
pageSize: 4,
})
}
watch(
() => channelId,
(val) => {
if (val) {
getChannel()
getComment()
}
},
{
immediate: true,
}
)
return res.data as PageResultPostsCommentRespVO
})
// const getComment = () => {
// postscommentpage({
// postsId: channelId,
// pageNo: query.pageNo,
// pageSize: query.pageSize,
// }).then((res) => {
// if (res.code === 0) {
// commentList.list = res.data.list
// commentList.total = res.data.total
// }
// })
// }
// watch(
// () => channelId,
// (val) => {
// if (val) {
// getChannel()
// getComment()
// }
// },
// {
// immediate: true,
// }
// )
const commentContent = ref('')
const handleCreateComment = () => {
@ -153,17 +172,18 @@
return
}
createPostsComment({
postsId: channelId,
postsId: channelId.value,
content: commentContent.value,
}).then((res) => {
if (res.code === 0) {
getComment()
refresh()
commentContent.value = ''
}
})
}
const handleCurrentChange = (pageNo: number) => {
query.pageNo = pageNo
getComment()
// query.pageNo = pageNo
// getComment()
navigateTo(`/chat-detail/${channelId.value}-${pageNo}`)
}
</script>