11<template >
22 <div class =" flex flex-col gap-[16px]" >
3- <div class =" flex justify-between items-center" >
4- <div class =" flex items-center gap-2" >
5- <div class =" text-gray-700 text-md leading-6 font-medium flex items-center gap-2" >
6- <div v-show =" !isEdit" class =" text-gray-700 text-md leading-6 font-medium flex items-center gap-2" >
7- <div >{{ title }}</div >
8- <el-tooltip content =" Edit title" placement =" top" >
9- <div v-if =" canEdit" @click =" editTitle" class =" cursor-pointer" >
10- <svg xmlns =" http://www.w3.org/2000/svg" width =" 16" height =" 16" viewBox =" 0 0 16 16" fill =" none" >
11- <path d =" M8.5 1.5H5.5C4.11929 1.5 3 2.61929 3 4V12C3 13.3807 4.11929 14.5 5.5 14.5H10.5C11.8807 14.5 13 13.3807 13 12V9" stroke =" #606266" stroke-linecap =" round" stroke-linejoin =" round" />
12- <path d =" M12.5 2.5L13.5 3.5L6.5 10.5H5.5V9.5L12.5 2.5Z" stroke =" #606266" stroke-linecap =" round" stroke-linejoin =" round" />
13- </svg >
14- </div >
15- </el-tooltip >
16- </div >
17- <div v-show =" isEdit" class =" text-gray-700 text-md leading-6 font-medium flex items-center gap-2" >
18- <input type =" text"
19- ref =" inputTitle"
20- v-model =" theTitle"
21- @change =" saveTitle"
22- @blur =" isEdit=false" >
23- </div >
24- <div class =" text-gray-500 flex gap-2 text-sm leading-5" >
25- <a :href =" `/profile/${userName}`" class =" hover:text-brand-600 hover:underline cursor-pointer" >{{userName}}</a >
26- <div >·</div >
27- <a >{{ time }}</a >
3+ <template v-if =" ! isDataLoading " >
4+ <div class =" flex justify-between items-center" >
5+ <div class =" flex items-center gap-2" >
6+ <div class =" text-gray-700 text-md leading-6 font-medium flex items-center gap-2" >
7+ <div v-show =" !isEdit" class =" text-gray-700 text-md leading-6 font-medium flex items-center gap-2" >
8+ <div >{{ title }}</div >
9+ <el-tooltip content =" Edit title" placement =" top" >
10+ <div v-if =" canEdit" @click =" editTitle" class =" cursor-pointer" >
11+ <svg xmlns =" http://www.w3.org/2000/svg" width =" 16" height =" 16" viewBox =" 0 0 16 16" fill =" none" >
12+ <path d =" M8.5 1.5H5.5C4.11929 1.5 3 2.61929 3 4V12C3 13.3807 4.11929 14.5 5.5 14.5H10.5C11.8807 14.5 13 13.3807 13 12V9" stroke =" #606266" stroke-linecap =" round" stroke-linejoin =" round" />
13+ <path d =" M12.5 2.5L13.5 3.5L6.5 10.5H5.5V9.5L12.5 2.5Z" stroke =" #606266" stroke-linecap =" round" stroke-linejoin =" round" />
14+ </svg >
15+ </div >
16+ </el-tooltip >
17+ </div >
18+ <div v-show =" isEdit" class =" text-gray-700 text-md leading-6 font-medium flex items-center gap-2" >
19+ <input type =" text"
20+ ref =" inputTitle"
21+ v-model =" theTitle"
22+ @change =" saveTitle"
23+ @blur =" isEdit=false" >
24+ </div >
25+ <div class =" text-gray-500 flex gap-2 text-sm leading-5" >
26+ <a :href =" `/profile/${userName}`" class =" hover:text-brand-600 hover:underline cursor-pointer" >{{userName}}</a >
27+ <div >·</div >
28+ <a >{{ time }}</a >
29+ </div >
2830 </div >
2931 </div >
3032 </div >
31- </div >
32-
33- <!-- 评论列表 -->
34- <div class =" border border-gray-200 border-b-0.5 rounded-lg" v-for =" comment in commentData" :key =" comment.id" >
35- <div class =" flex justify-between gap-1 border-b rounded-t-lg border-gray-200 items-center px-3 py-2 bg-gray-100" >
36- <div class =" flex items-center gap-2 text-md leading-5 text-gray-700 font-normal" >
37- <el-avatar :size =" 24" :src =" comment.user.avatar" ></el-avatar >
38- <div class =" flex items-center gap-1" >
39- <a :href =" `/profile/${comment.user.name}`" class =" hover:text-brand-600 hover:underline cursor-pointer" >{{comment.user.name}}</a >
40- <div >·</div >
41- <el-tooltip
42- :content =" formatFullTime(comment.created_at)"
43- placement =" top" >
44- <div class =" cursor-help" >{{formatTime(comment.created_at)}}</div >
45- </el-tooltip >
33+ <!-- 评论列表 -->
34+ <div class =" border border-gray-200 border-b-0.5 rounded-lg" v-for =" comment in commentData" :key =" comment.id" >
35+ <div class =" flex justify-between gap-1 border-b rounded-t-lg border-gray-200 items-center px-3 py-2 bg-gray-100" >
36+ <div class =" flex items-center gap-2 text-md leading-5 text-gray-700 font-normal" >
37+ <el-avatar :size =" 24" :src =" comment.user.avatar" ></el-avatar >
38+ <div class =" flex items-center gap-1" >
39+ <a :href =" `/profile/${comment.user.name}`" class =" hover:text-brand-600 hover:underline cursor-pointer" >{{comment.user.name}}</a >
40+ <div >·</div >
41+ <el-tooltip
42+ :content =" formatFullTime(comment.created_at)"
43+ placement =" top" >
44+ <div class =" cursor-help" >{{formatTime(comment.created_at)}}</div >
45+ </el-tooltip >
46+ </div >
4647 </div >
4748 </div >
49+ <div class =" px-3 py-3 rounded-b-lg text-gray-700 text-md font-normal markdown-body" v-html =" renderMarkdown(comment.content)" ></div >
4850 </div >
49- <div class =" px-3 py-3 rounded-b-lg text-gray-700 text-md font-normal markdown-body" v-html =" renderMarkdown(comment.content)" ></div >
50- </div >
51+ </template >
52+ <LoadingSpinner
53+ :loading =" isDataLoading"
54+ :text =" $t('repo.loadingComments')"
55+ />
56+ <CsgPagination
57+ class =" mt-4"
58+ :perPage =" perPage"
59+ :currentPage =" currentPage"
60+ :total =" totalComments"
61+ @currentChange =" handlePageChange"
62+ />
5163
5264 <!-- 评论输入框 -->
5365 <CommunityMDTextarea ref =" mdTextarea" :desc =" desc" @inputChange =" handleInputChange" ></CommunityMDTextarea >
6880</template >
6981
7082<script >
83+ import CsgPagination from ' ../shared/CsgPagination.vue'
84+ import LoadingSpinner from ' ../shared/LoadingSpinner.vue'
7185import CommunityTimeLine from ' ./CommunityTimeLine.vue'
7286import CommunityMDTextarea from ' ./CommunityMDTextarea.vue'
7387import { format } from ' timeago.js'
@@ -88,7 +102,9 @@ export default {
88102 },
89103 components: {
90104 CommunityTimeLine,
91- CommunityMDTextarea
105+ CommunityMDTextarea,
106+ CsgPagination,
107+ LoadingSpinner
92108 },
93109 data () {
94110 return {
@@ -102,7 +118,11 @@ export default {
102118 timelineData: [{ name: ' Username' , type: ' change status' , state: ' closed' , date: ' 2022-01-01' , text: ' Event 1' },
103119 { name: ' Username' , type: ' change status' , state: ' open' , date: ' 2023-03-15' , text: ' Event 2' },
104120 { name: ' Username' , type: ' change title' , title_from: ' xxx' , title_to: ' xyx' , date: ' 2023-04-10' , text: ' Event 3' }],
105- userStore: useUserStore ()
121+ userStore: useUserStore (),
122+ perPage: 10 ,
123+ currentPage: 1 ,
124+ totalComments: 0 ,
125+ isDataLoading: false ,
106126 };
107127 },
108128 computed: {
@@ -263,17 +283,36 @@ export default {
263283 this .theTitle = this .oldTitle
264284 }
265285 },
266- async getComment (discussionId ) {
286+ async getComment (discussionId , childCurrent ) {
267287 if (! discussionId) {
268288 return
269289 }
270- const commentCreateEndpoint = ` /discussions/${ discussionId} /comments`
290+ if (childCurrent) {
291+ this .currentPage = childCurrent
292+ }
293+ this .isDataLoading = true
294+ const params = new URLSearchParams ()
295+ params .append (' per' , this .perPage )
296+ params .append (' page' , this .currentPage )
297+ const commentCreateEndpoint = ` /discussions/${ discussionId} /comments?${ params .toString ()} `
271298 const {data , error } = await useFetchApi (commentCreateEndpoint).json ()
272299 if (data .value ) {
273- this .commentData = data .value .data
300+ this .commentData = data .value .data || []
301+ this .totalComments = data .value .total || 0
274302 } else {
275303 ElMessage .warning (error .value ? .msg || ' 获取评论失败' )
276304 }
305+ this .isDataLoading = false
306+ this .scrollToTop ()
307+ },
308+
309+ scrollToTop () {
310+ window .scrollTo ({ top: 0 , behavior: ' smooth' })
311+ },
312+
313+ handlePageChange (page ) {
314+ this .currentPage = page
315+ this .getComment (this .discussionId , page)
277316 },
278317 async createComment (discussionId ) {
279318 if (! discussionId) {
0 commit comments