Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
corporateCulture-qd
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
王立鹏
corporateCulture-qd
Commits
5ce1af42
Commit
5ce1af42
authored
Mar 05, 2026
by
lijiabin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
【需求 20331】 perf: 优化组件
parent
6902c1be
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
232 additions
and
223 deletions
+232
-223
index.vue
src/components/common/Comment/index.vue
+232
-223
No files found.
src/components/common/Comment/index.vue
View file @
5ce1af42
...
@@ -90,256 +90,265 @@
...
@@ -90,256 +90,265 @@
<!-- 分割线 -->
<!-- 分割线 -->
<!-- 评论列表 -->
<!-- 评论列表 -->
<div
v-loading=
"loading"
class=
"divide-y divide-gray-100"
v-if=
"list.length"
>
<div
v-loading=
"loading"
class=
"divide-y divide-gray-100"
>
<div
<div
v-show=
"list.length"
>
v-for=
"(item, index) in list"
<div
:key=
"item.id"
v-for=
"(item, index) in list"
:ref=
"(el) => (commentItemRefList[index] = el as HTMLElement)"
:key=
"item.id"
>
:ref=
"(el) => (commentItemRefList[index] = el as HTMLElement)"
<div
class=
"p-4 transition-colors"
>
>
<div
class=
"flex gap-3"
>
<div
class=
"p-4 transition-colors"
>
<img
<div
class=
"flex gap-3"
>
@
click=
"jumpToUserHomePage({ userId: item.userId, type })"
<img
:src=
"item.avatar"
@
click=
"jumpToUserHomePage({ userId: item.userId, type })"
alt=
""
:src=
"item.avatar"
class=
"w-10 h-10 rounded-full object-cover cursor-pointer"
alt=
""
/>
class=
"w-10 h-10 rounded-full object-cover cursor-pointer"
<div
class=
"flex-1"
>
/>
<div
class=
"flex items-center gap-2 mb-2"
>
<div
class=
"flex-1"
>
<span
class=
"font-semibold text-gray-800"
>
{{ item.replyUser }}
</span>
<div
class=
"flex items-center gap-2 mb-2"
>
<!-- <span
<span
class=
"font-semibold text-gray-800"
>
{{ item.replyUser }}
</span>
<!-- <span
class="px-2 py-0.5 text-xs bg-gradient-to-r from-purple-100 to-blue-100 text-purple-600 rounded-full"
class="px-2 py-0.5 text-xs bg-gradient-to-r from-purple-100 to-blue-100 text-purple-600 rounded-full"
>
>
技术专家
技术专家
</span> -->
</span> -->
<!-- <span class="px-2 py-0.5 text-xs bg-red-100 text-red-600 rounded-full">置顶</span> -->
<!-- <span class="px-2 py-0.5 text-xs bg-red-100 text-red-600 rounded-full">置顶</span> -->
</div>
<!-- 换行 -->
<p
class=
"text-gray-800 my-2 break-all whitespace-pre-wrap"
v-html=
"parseEmoji(item.content)"
></p>
<!-- 评论图片列表 -->
<div
class=
"flex flex-wrap gap-2"
>
<div
v-for=
"(img, imgIndex) in item.imgUrl.split(',').filter(Boolean)"
:key=
"imgIndex"
class=
"w-20 h-20 rounded-lg overflow-hidden mb-2 cursor-pointer"
>
<el-image
:src=
"img"
:preview-teleported=
"true"
class=
"w-full h-full object-cover"
:preview-src-list=
"item.imgUrl.split(',').filter(Boolean)"
:initial-index=
"imgIndex"
fit=
"cover"
/>
</div>
</div>
<div
class=
"flex items-center justify-between"
>
<div
class=
"flex items-center gap-6 text-gray-500"
>
<span
class=
"flex items-center gap-2 text-[14px]"
>
<span
>
{{ dayjs(item.createTime * 1000).format('YYYY-MM-DD HH:mm:ss') }}
</span>
<span>
·
</span>
<span
class=
"text-gray-500"
>
{{ item.region }}
</span>
</span>
<div
class=
"flex gap-2 items-center hover:text-blue-500"
>
<div
class=
"flex items-center gap-1 cursor-pointer"
@
click=
"handleLickComment(item)"
>
<el-icon
:size=
"16"
>
<svg-icon
:name=
"item.hasPraise ? 'praise_fill' : 'praise'"
></svg-icon>
</el-icon>
<span>
{{ item.postPriseCount }}
</span>
</div>
</div>
<button
class=
"cursor-pointer hover:text-blue-500 transition-colors text-[14px]"
@
click=
"handleReply(item, index)"
>
回复
</button>
</div>
</div>
</div>
<!-- 换行 -->
<!-- 回复列表 -->
<p
<!-- 问吧 和 其他 做区分 -->
class=
"text-gray-800 my-2 break-all whitespace-pre-wrap"
<
template
v-if=
"!isQuestion"
>
v-html=
"parseEmoji(item.content)"
<div
v-if=
"item.children?.length"
class=
"mt-3 ml-4 space-y-3"
>
></p>
<!-- 回复评论的内容 里面可能是 展示全部的 也有可能是展示5条之内容 -->
<!-- 评论图片列表 -->
<div
class=
"flex flex-wrap gap-2"
>
<div
<div
v-for=
"child in getCurrentChildrenList(item)"
v-for=
"(img, imgIndex) in item.imgUrl.split(',').filter(Boolean)"
v-loading=
"item.loadingChildren"
:key=
"imgIndex"
:key=
"child.id"
class=
"w-20 h-20 rounded-lg overflow-hidden mb-2 cursor-pointer"
class=
"flex gap-2 p-3 rounded-lg"
>
>
<img
<el-image
@
click=
"jumpToUserHomePage(
{ userId: child.userId, type })"
:src=
"img"
:src="child.avatar"
:preview-teleported=
"true"
alt=""
class=
"w-full h-full object-cover"
class="w-8 h-8 rounded-full object-cover cursor-pointer"
:preview-src-list=
"item.imgUrl.split(',').filter(Boolean)"
:initial-index=
"imgIndex"
fit=
"cover"
/>
/>
<div
class=
"flex-1"
>
</div>
<div
class=
"flex items-center gap-1"
>
</div>
<span
class=
"font-semibold text-gray-600 text-base"
>
{{
<div
class=
"flex items-center justify-between"
>
child
.
replyUser
<div
class=
"flex items-center gap-6 text-gray-500"
>
}}
</span>
<span
class=
"flex items-center gap-2 text-[14px]"
>
<!-- v-if="item.replyName && item.replyName !== parentComment?.replyUser" -->
<span
<span
class=
"text-gray-500 text-sm flex items-center gap-1"
>
>
{{ dayjs(item.createTime * 1000).format('YYYY-MM-DD HH:mm:ss') }}
<el-icon
class=
"mx-1"
><IEpCaretRight
/></el-icon>
</span>
{{
child
.
replyName
}}
<span>
·
</span>
</span>
<span
class=
"text-gray-500"
>
{{ item.region }}
</span>
</span>
<div
class=
"flex gap-2 items-center hover:text-blue-500"
>
<div
class=
"flex items-center gap-1 cursor-pointer"
@
click=
"handleLickComment(item)"
>
<el-icon
:size=
"16"
>
<svg-icon
:name=
"item.hasPraise ? 'praise_fill' : 'praise'"
></svg-icon>
</el-icon>
<span>
{{ item.postPriseCount }}
</span>
</div>
</div>
<p
</div>
class=
"text-gray-800 my-2 break-all whitespace-pre-wrap text-[16px]"
<button
v-html=
"parseEmoji(child.content)"
class=
"cursor-pointer hover:text-blue-500 transition-colors text-[14px]"
></p>
@
click=
"handleReply(item, index)"
<!-- 评论图片列表 -->
>
<div
class=
"flex flex-wrap gap-2"
>
回复
<div
</button>
v-for=
"(img, imgIndex) in child.imgUrl.split(',').filter(Boolean)"
</div>
:key=
"imgIndex"
</div>
class=
"w-20 h-20 rounded-lg overflow-hidden mb-2"
<!-- 回复列表 -->
>
<!-- 问吧 和 其他 做区分 -->
<el-image
<
template
v-if=
"!isQuestion"
>
:src=
"img"
<div
v-if=
"item.children?.length"
class=
"mt-3 ml-4 space-y-3"
>
:preview-teleported=
"true"
<!-- 回复评论的内容 里面可能是 展示全部的 也有可能是展示5条之内容 -->
class=
"w-full h-full object-cover"
<div
:preview-src-list=
"child.imgUrl.split(',').filter(Boolean)"
v-for=
"child in getCurrentChildrenList(item)"
:initial-index=
"imgIndex"
v-loading=
"item.loadingChildren"
fit=
"cover"
:key=
"child.id"
/>
class=
"flex gap-2 p-3 rounded-lg"
>
<img
@
click=
"jumpToUserHomePage(
{ userId: child.userId, type })"
:src="child.avatar"
alt=""
class="w-8 h-8 rounded-full object-cover cursor-pointer"
/>
<div
class=
"flex-1"
>
<div
class=
"flex items-center gap-1"
>
<span
class=
"font-semibold text-gray-600 text-base"
>
{{
child
.
replyUser
}}
</span>
<!-- v-if="item.replyName && item.replyName !== parentComment?.replyUser" -->
<span
class=
"text-gray-500 text-sm flex items-center gap-1"
>
<el-icon
class=
"mx-1"
><IEpCaretRight
/></el-icon>
{{
child
.
replyName
}}
</span>
</div>
</div>
</div>
<p
<div
class=
"flex items-center justify-between"
>
class=
"text-gray-800 my-2 break-all whitespace-pre-wrap text-[16px]"
<div
class=
"flex items-center gap-6 text-gray-500 text-[14px]"
>
v-html=
"parseEmoji(child.content)"
<span
class=
"flex items-center gap-2"
>
></p>
<span
<!-- 评论图片列表 -->
>
{{
dayjs
(
child
.
createTime
*
1000
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
}}
<div
class=
"flex flex-wrap gap-2"
>
<div
v-for=
"(img, imgIndex) in child.imgUrl.split(',').filter(Boolean)"
:key=
"imgIndex"
class=
"w-20 h-20 rounded-lg overflow-hidden mb-2"
>
<el-image
:src=
"img"
:preview-teleported=
"true"
class=
"w-full h-full object-cover"
:preview-src-list=
"child.imgUrl.split(',').filter(Boolean)"
:initial-index=
"imgIndex"
fit=
"cover"
/>
</div>
</div>
<div
class=
"flex items-center justify-between"
>
<div
class=
"flex items-center gap-6 text-gray-500 text-[14px]"
>
<span
class=
"flex items-center gap-2"
>
<span
>
{{
dayjs
(
child
.
createTime
*
1000
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
}}
</span>
<span>
·
</span>
<span
class=
"text-gray-500"
>
{{
child
.
region
}}
</span>
</span>
</span>
<span>
·
</span>
<div
class=
"flex gap-2 items-center hover:text-blue-500"
>
<span
class=
"text-gray-500"
>
{{
child
.
region
}}
</span>
<div
</span>
class=
"flex items-center gap-1 cursor-pointer"
<div
class=
"flex gap-2 items-center hover:text-blue-500"
>
@
click=
"handleLickComment(child)"
<div
>
class=
"flex items-center gap-1 cursor-pointer"
<el-icon
:size=
"16"
>
@
click=
"handleLickComment(child)"
<svg-icon
>
:name=
"child.hasPraise ? 'praise_fill' : 'praise'"
<el-icon
:size=
"16"
>
></svg-icon>
<svg-icon
</el-icon>
:name=
"child.hasPraise ? 'praise_fill' : 'praise'"
<span>
{{
child
.
postPriseCount
}}
</span>
></svg-icon>
</div>
</el-icon>
<span>
{{
child
.
postPriseCount
}}
</span>
</div>
</div>
<button
@
click=
"handleReply(child, index)"
class=
"cursor-pointer hover:text-blue-500 transition-colors"
>
回复
</button>
</div>
</div>
<button
@
click=
"handleReply(child, index)"
class=
"cursor-pointer hover:text-blue-500 transition-colors"
>
回复
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</
template
>
</
template
>
<!-- 问吧 如果有 子评论 直接变成 查看更多 -->
<!-- 问吧 如果有 子评论 直接变成 查看更多 -->
<
template
v-else
>
<
template
v-else
>
<div
v-if=
"item.childNum"
>
<div
v-if=
"item.childNum"
>
<button
<button
class=
"cursor-pointer text-sm text-gray-500 mt-2"
class=
"cursor-pointer text-sm text-gray-500 mt-2"
@
click=
"handleOpenCommentDialog(item)"
@
click=
"handleOpenCommentDialog(item)"
>
>
查看全部
{{
item
.
childNum
}}
条回复>
查看全部
{{
item
.
childNum
}}
条回复>
</button>
</button>
</div>
</div>
</
template
>
</
template
>
<!-- 只有大于5 才会显示这个 -->
<!-- 只有大于5 才会显示这个 -->
<div
class=
"ml-4"
v-show=
"item.childrenNum > 5 && !isQuestion"
>
<div
class=
"ml-4"
v-show=
"item.childrenNum > 5 && !isQuestion"
>
<!-- 展示 展开回复 -->
<!-- 展示 展开回复 -->
<button
v-show=
"!item.showChildrenPage"
class=
"cursor-pointer text-sm text-gray-500"
@
click=
"handleExpandReply(item)"
>
还有{{ item.childrenNum - 5 }}条回复,
<span
class=
"hover:text-blue-500 transition-colors"
>
点击查看
</span
>
</button>
<!-- 展示 收起回复 以及分页 -->
<div
class=
"flex items-center gap-2"
v-show=
"item.showChildrenPage"
>
<span
class=
"text-sm text-gray-500"
>
共{{ Math.ceil(item.childrenNum / 10) }}页
</span
>
<el-pagination
:pager-count=
"5"
layout=
"pager"
v-show=
"item.showChildrenPage"
:current-page=
"item.childrenPageCurrent"
:total=
"item.childrenNum"
@
current-change=
"handleChildrenCurrentChange($event, item, index)"
/>
<button
<button
class=
"cursor-pointer hover:text-blue-500 transition-colors text-sm text-gray-500"
v-show=
"!item.showChildrenPage"
@
click=
"handleCollapseReply(item, index)"
class=
"cursor-pointer text-sm text-gray-500"
@
click=
"handleExpandReply(item)"
>
>
收起回复
还有{{ item.childrenNum - 5 }}条回复,
<span
class=
"hover:text-blue-500 transition-colors"
>
点击查看
</span
>
</button>
</button>
<!-- 展示 收起回复 以及分页 -->
<div
class=
"flex items-center gap-2"
v-show=
"item.showChildrenPage"
>
<span
class=
"text-sm text-gray-500"
>
共{{ Math.ceil(item.childrenNum / 10) }}页
</span
>
<el-pagination
:pager-count=
"5"
layout=
"pager"
v-show=
"item.showChildrenPage"
:current-page=
"item.childrenPageCurrent"
:total=
"item.childrenNum"
@
current-change=
"handleChildrenCurrentChange($event, item, index)"
/>
<button
class=
"cursor-pointer hover:text-blue-500 transition-colors text-sm text-gray-500"
@
click=
"handleCollapseReply(item, index)"
>
收起回复
</button>
</div>
</div>
</div>
<!-- 展示 回复评论的输入框 -->
<transition
name=
"fadeToComment"
>
<div
v-show=
"showCommentBox(item)"
class=
"flex gap-3 mt-4"
>
<img
:src=
"userAvatar"
alt=
""
class=
"w-10 h-10 rounded-full object-cover cursor-pointer"
@
click=
"jumpToUserHomePage({ userId: userInfo.userId, type })"
/>
<CommentBox
v-model:inputText=
"commentToOther"
v-model:inputImg=
"commentToOtherImgStr"
class=
"flex-1"
:ref=
"(el) => (replyToOtherBoxRefList[index] = el as HTMLElement)"
>
<
template
#
submit
>
<button
class=
"cursor-pointer disabled:opacity-50 px-6 py-2 bg-gradient-to-r from-blue-500 to-purple-500 text-white rounded-full text-sm hover:shadow-lg transition-all"
:disabled=
"!commentToOther.trim() || commentToOtherLoading"
@
click=
"handleComment(index)"
>
发表
</button>
</
template
>
</CommentBox>
</div>
</transition>
</div>
</div>
<!-- 展示 回复评论的输入框 -->
<transition
name=
"fadeToComment"
>
<div
v-show=
"showCommentBox(item)"
class=
"flex gap-3 mt-4"
>
<img
:src=
"userAvatar"
alt=
""
class=
"w-10 h-10 rounded-full object-cover cursor-pointer"
@
click=
"jumpToUserHomePage({ userId: userInfo.userId, type })"
/>
<CommentBox
v-model:inputText=
"commentToOther"
v-model:inputImg=
"commentToOtherImgStr"
class=
"flex-1"
:ref=
"(el) => (replyToOtherBoxRefList[index] = el as HTMLElement)"
>
<
template
#
submit
>
<button
class=
"cursor-pointer disabled:opacity-50 px-6 py-2 bg-gradient-to-r from-blue-500 to-purple-500 text-white rounded-full text-sm hover:shadow-lg transition-all"
:disabled=
"!commentToOther.trim() || commentToOtherLoading"
@
click=
"handleComment(index)"
>
发表
</button>
</
template
>
</CommentBox>
</div>
</transition>
</div>
</div>
</div>
</div>
<div
class=
"px-4"
>
<el-divider
class=
"my-2!"
/>
</div>
</div>
</div>
<div
class=
"px-4"
>
<!-- 底部分页 -->
<el-divider
class=
"my-2!"
/>
<!-- 靠右侧 -->
<div
class=
"flex justify-end"
>
<div
class=
"w-fit p-4"
>
<el-pagination
v-model:current-page=
"searchParams.current"
v-model:page-size=
"searchParams.size"
:total=
"firstComentTotal"
@
current-change=
"handleCurrentChange"
@
size-change=
"changePageSize"
layout=
"prev, pager, next, slot"
>
<div>
共 {{ total }} 条
</div>
</el-pagination>
</div>
</div>
</div>
</div>
</div>
<!-- 底部分页 -->
<div
v-show=
"!list.length"
>
<!-- 靠右侧 -->
<div
class=
"flex items-center justify-center"
>
<div
class=
"flex justify-end"
>
<el-empty
:image-size=
"100"
description=
"暂无评论"
/>
<div
class=
"w-fit p-4"
>
<el-pagination
v-model:current-page=
"searchParams.current"
v-model:page-size=
"searchParams.size"
:total=
"firstComentTotal"
@
current-change=
"handleCurrentChange"
@
size-change=
"changePageSize"
layout=
"prev, pager, next, slot"
>
<div>
共 {{ total }} 条
</div>
</el-pagination>
</div>
</div>
</div>
</div>
</div>
</div>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment