Commit 1f06fdd6 by lijiabin

【需求 17679】 feat: 加入问吧详情页面 优化评论组件等

parent 5f8e0353
......@@ -149,6 +149,36 @@ export interface ArticleItemDto {
rewardNum: number
isExpand: boolean
hasAddQuestion: boolean
cultureCommentListVo: {
articleId: number
avatar: string
children: string
childrenNum: number
content: string
createTime: number
createUserId: number
description: string
faceUrl: string
hasPraise: BooleanFlag
hiddenAvatar: string
hiddenName: string
id: number
isFeatured: BooleanFlag
isRecommend: BooleanFlag
isTop: BooleanFlag
pid: number
postPriseCount: number
praiseCount: number
region: string
regionHide: BooleanFlag
replyId: number
replyName: string
replyUser: string
title: string
type: ArticleTypeEnum
userId: string
viewCount: number
}
}
/**
......
......@@ -308,10 +308,12 @@ const {
id,
defaultSize = 10,
isReal,
immediate = true,
} = defineProps<{
id: number | string
defaultSize?: number
isReal: BooleanFlag
immediate?: boolean
}>()
const emit = defineEmits<{
......@@ -366,6 +368,7 @@ const { list, searchParams, goToPage, loading, changePageSize, refresh, search }
return obj
})
},
immediate,
},
)
const handleCurrentChange = async (e: number) => {
......@@ -496,6 +499,7 @@ const handleUserInfo = (item: CommentItemDto) => {
defineExpose({
scrollToCommentBox: () => handleBackTop(),
search: () => search(),
})
</script>
<style scoped lang="scss">
......
......@@ -161,6 +161,11 @@ export const constantsRoute = [
name: 'CultureVideoSearchList',
component: () => import('@/views/videoSearchList/index.vue'),
},
{
path: 'questionDetail/:id',
name: 'CultureQuestionDetail',
component: () => import('@/views/questionDetail/index.vue'),
},
// 发布文章
// {
// {
......
......@@ -22,14 +22,15 @@
:key="item.id"
class="question-card !rounded-lg mb-4 transition-all duration-300"
shadow="hover"
@click="router.push(`/questionDetail/${item.id}`)"
>
<!-- 问题标题 -->
<h3
class="text-lg font-semibold text-gray-900 mb-3 leading-relaxed cursor-pointer hover:text-blue-600 transition-colors"
<h2
class="text-xl line-clamp-1 font-semibold text-gray-900 mb-2 leading-relaxed cursor-pointer hover:text-blue-600 transition-colors"
>
{{ item.title }}
</h3>
<div class="flex gap-4 mb-4">
</h2>
<div class="flex gap-4 mb-2">
<el-image
v-if="item.faceUrl"
:src="item.faceUrl"
......@@ -43,7 +44,9 @@
class="text-gray-600 text-base leading-relaxed transition-all duration-300"
:class="{ 'line-clamp-3': !item.isExpand }"
>
{{ item.content }}
{{ item.cultureCommentListVo?.hiddenAvatar }}{{
item.cultureCommentListVo?.content
}}
</p>
<!-- 展开/收起按钮 靠右边布局 -->
<div class="flex justify-end">
......@@ -68,7 +71,7 @@
<!-- 左侧:发布人信息 -->
<div class="flex items-center gap-4">
<div class="flex items-center gap-2">
<!-- <span class="text-orange-500 text-sm font-medium">发布人</span> -->
<span class="text-orange-500 text-sm font-medium">发布人</span>
<div class="flex items-center gap-2">
<el-avatar :size="20" :src="item.showAvatar"> </el-avatar>
<span class="text-sm text-gray-700 font-medium">{{ item.showName }}</span>
......@@ -106,7 +109,7 @@
</el-button>
<!-- 回答按钮保持不变 -->
<el-button size="small" plain @click="handleComment(item)">
<el-button size="small" plain @click="handleComment(item, index)">
<el-icon><Edit /></el-icon>
回答
</el-button>
......@@ -139,7 +142,7 @@
<el-button
text
class="flex items-center gap-2 text-gray-500 transition-colors"
@click="handleComment(item)"
@click="handleComment(item, index)"
>
<el-icon><ChatDotRound /></el-icon>
<span class="text-sm">{{ item.replyCount || 0 }}</span>
......@@ -149,10 +152,12 @@
<Transition name="fade">
<Comment
v-show="item.showComment"
:ref="(e) => (commentRefList[index] = e as InstanceType<typeof Comment>)"
:id="item.id"
:total="item.replyCount"
:defaultSize="5"
:isReal="0"
:immediate="false"
@commentSuccess="() => handleCommentSuccess(item)"
/>
</Transition>
......@@ -215,6 +220,7 @@ import { getArticleList, addOrCanceArticlelCollect, addOrCancelToAnswerList } fr
import type { ArticleItemDto } from '@/api/article/types'
import { useQuestionStore } from '@/stores/question'
import ActionMore from '@/components/common/ActionMore/index.vue'
import router from '@/router'
const { fetchUserQestionNum } = useQuestionStore()
......@@ -253,7 +259,8 @@ const handleCollect = async (item: ArticleItemDto) => {
ElMessage.success(item.hasCollect ? '收藏成功' : '取消收藏')
}
const handleComment = (item: ArticleItemDto) => {
const handleComment = (item: ArticleItemDto, index: number) => {
commentRefList.value[index]?.search()
item.showComment = !item.showComment
}
......@@ -283,6 +290,7 @@ const handleTabChange = () => {
}
const contentRefList = ref<HTMLElement[]>([])
const commentRefList = ref<InstanceType<typeof Comment>[]>([])
// 检测当前是否超过三行 要用到具体的dom
const isOverThreeLine = (index: number) => {
......
<script setup lang="ts">
import { ref } from 'vue'
import { CaretTop, CaretBottom, ChatDotRound, Share, Star, Plus } from '@element-plus/icons-vue'
// --- 模拟数据 ---
const tags = ref([
{ id: 1, name: 'React' },
{ id: 2, name: 'Vue.js' },
])
const question = ref({
title: 'vue转react是什么感受?',
description:
'最近在面试,有一家公司各方面都很满意,但是因为他们是做阿里巴巴网店模板,只能用react写,所以要考虑学习react,来知乎问问各位大佬意见...',
viewCount: '12,304',
followCount: 52,
})
const answers = ref([
{
id: 1,
user: {
name: '我们',
avatar: 'https://picsum.photos/id/64/100/100',
bio: '各位都脑测了就回复了,你们的一切脑测都是对的',
},
votes: 2,
content: '什么时候这群人才能明白框架没那么重要,重要的是逻辑能力和代码水平',
publishDate: '2025-10-13 11:42',
commentCount: 0,
},
{
id: 2,
user: {
name: '老富甲',
avatar: 'https://picsum.photos/id/1025/100/100',
bio: '程序员',
},
votes: 12,
content: `初入前端的时候,写的是 vue 2,非常简单的就入门了,然后就是自己研究html和css,对调样式很感兴趣,乐在其中。<br><br>换公司学 react,由于连 ts 都不会,同时学 react 官网和 ts 官网,两个官网都撸了4-5遍,差不多3天吧,就差不多能写基础的页面了,后续就是熟练度问题了,然后就是要学习各种组件库,其实还好,不会很难的,并且会了之后感觉很爽,比写vue爽了非常非常多。<br><br>写 react 我感觉就是比写 vue 更有激情,可能因为 vscode 对 ts、react 的插件体验更好点...`,
publishDate: '2025-10-12 18:20',
commentCount: 2,
},
])
const isFollowing = ref(false)
</script>
<template>
<div class="min-h-screen p-6 font-sans text-gray-800 flex justify-center">
<!--
背景调整:bg-[#f9fafb]
这是一种极接近白色的淡灰,视觉上非常干净,
但能保证卡片的白色阴影依然可见。
-->
<div class="w-full max-w-4xl space-y-4">
<!-- 1. 问题卡片 -->
<!-- 圆角调整:rounded-xl (12px),这是最标准的圆角大小 -->
<div class="bg-white rounded-xl p-8 shadow-sm border border-gray-100">
<!-- 标签 -->
<div class="flex gap-2 mb-4">
<el-tag
v-for="tag in tags"
:key="tag.id"
class="!border-none !bg-blue-50 !text-blue-600 !px-3 !h-7 !text-xs font-bold rounded-md"
>
{{ tag.name }}
</el-tag>
</div>
<!-- 标题 -->
<h1 class="text-2xl font-bold text-gray-900 mb-3 leading-snug">
{{ question.title }}
</h1>
<!-- 描述 -->
<p class="text-gray-600 leading-relaxed mb-6 text-sm md:text-base">
{{ question.description }}
<span class="text-blue-600 cursor-pointer hover:underline text-sm font-medium ml-1"
>显示全部</span
>
</p>
<!-- 操作栏 -->
<div class="flex flex-wrap items-center justify-between gap-4 pt-2">
<div class="flex gap-3">
<el-button
type="primary"
class="!rounded-lg !px-5 !h-9 !text-sm !font-medium !bg-blue-600 !border-blue-600 hover:!bg-blue-700 hover:!shadow-md transition-all"
@click="isFollowing = !isFollowing"
>
{{ isFollowing ? '已关注' : '关注问题' }}
</el-button>
<el-button
class="!rounded-lg !px-5 !h-9 !text-sm !font-medium !text-blue-600 !border-blue-200 !bg-blue-50 hover:!bg-blue-100 transition-colors"
>
<el-icon class="mr-1"><Plus /></el-icon>
写回答
</el-button>
<el-button
class="!rounded-lg !h-9 !px-4 !text-gray-500 hover:!text-gray-700 !bg-transparent !border-gray-200"
>
邀请回答
</el-button>
</div>
<div class="flex gap-5 text-gray-400 text-sm">
<div
class="flex items-center gap-1 cursor-pointer hover:text-gray-600 transition-colors"
>
<el-icon class="text-base"><ChatDotRound /></el-icon>
<span>2 条评论</span>
</div>
<div
class="flex items-center gap-1 cursor-pointer hover:text-gray-600 transition-colors"
>
<el-icon class="text-base"><Share /></el-icon>
<span>分享</span>
</div>
</div>
</div>
</div>
<!-- 2. 分隔栏 -->
<div class="flex items-center justify-between px-1 py-1">
<span class="font-bold text-gray-900 text-base">105 个回答</span>
<div
class="flex items-center text-xs text-gray-500 cursor-pointer hover:text-blue-600 font-medium bg-white px-3 py-1 rounded-md shadow-sm border border-gray-100"
>
按时间排序
<el-icon class="ml-1"><CaretBottom /></el-icon>
</div>
</div>
<!-- 3. 回答列表 -->
<div class="space-y-3">
<div
v-for="answer in answers"
:key="answer.id"
class="bg-white rounded-xl p-8 shadow-sm border border-gray-100 hover:shadow-md transition-shadow duration-200"
>
<!-- 用户 -->
<div class="flex items-center mb-3">
<img :src="answer.user.avatar" class="w-9 h-9 rounded-full object-cover bg-gray-100" />
<div class="ml-3">
<div class="font-bold text-gray-900 text-sm">{{ answer.user.name }}</div>
<div class="text-xs text-gray-400 mt-0.5">{{ answer.user.bio }}</div>
</div>
</div>
<!-- 赞同信息 -->
<div class="mb-3 text-xs text-gray-400 flex items-center">
<span class="bg-gray-50 px-2 py-0.5 rounded text-gray-500">
{{ answer.votes }} 人赞同了该回答
</span>
</div>
<!-- 正文 -->
<div
class="text-gray-800 leading-7 text-sm md:text-base mb-6"
v-html="answer.content"
></div>
<!-- 底部操作 -->
<div class="flex items-center text-sm text-gray-400 gap-5 select-none">
<!-- 赞同按钮组:稍微方正一点的圆角 -->
<div class="flex bg-blue-50/50 rounded-lg p-0.5 border border-blue-100/50">
<button
class="flex items-center px-3 py-1 rounded-md bg-white text-blue-600 shadow-sm text-xs font-bold hover:text-blue-700 transition-colors"
>
<el-icon class="mr-1"><CaretTop /></el-icon>
赞同 {{ answer.votes }}
</button>
<button
class="flex items-center px-2 py-1 text-blue-400 hover:text-blue-600 transition-colors ml-0.5"
>
<el-icon><CaretBottom /></el-icon>
</button>
</div>
<div
class="flex items-center gap-1 cursor-pointer hover:text-gray-600 transition-colors"
>
<el-icon class="text-base"><ChatDotRound /></el-icon>
<span v-if="answer.commentCount" class="text-xs"
>{{ answer.commentCount }} 条评论</span
>
<span v-else class="text-xs">添加评论</span>
</div>
<div
class="flex items-center gap-1 cursor-pointer hover:text-gray-600 transition-colors"
>
<el-icon class="text-base"><Share /></el-icon>
<span class="text-xs">分享</span>
</div>
<div
class="flex items-center gap-1 cursor-pointer hover:text-gray-600 transition-colors"
>
<el-icon class="text-base"><Star /></el-icon>
<span class="text-xs">收藏</span>
</div>
<span class="ml-auto text-xs text-gray-300 hidden sm:block">
{{ answer.publishDate }}
</span>
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped>
/*
样式微调:
1. 卡片边框改为 border-gray-100,这是一种极淡的边框,配合阴影,质感更细腻。
2. 字体大小微调:正文使用 text-sm md:text-base,让信息密度稍微高一点,更像知乎PC端的阅读体验。
*/
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment