@@ -15,6 +15,7 @@ import {
15
15
import {
16
16
requestDeleteComment ,
17
17
requestRateComment ,
18
+ requestTopComment ,
18
19
useComments ,
19
20
} from '../../../apis/comment'
20
21
import {
@@ -142,7 +143,12 @@ const MainComment = ({
142
143
children ?: ReactNode
143
144
} ) => {
144
145
return (
145
- < Card className = { clsx ( className ) } >
146
+ < Card
147
+ className = { clsx (
148
+ className ,
149
+ comment . topping && 'shadow-[0_0_0_1px_#2d72d2]' ,
150
+ ) }
151
+ >
146
152
< div >
147
153
< CommentHeader comment = { comment } />
148
154
< CommentContent comment = { comment } />
@@ -189,21 +195,34 @@ const SubComment = ({
189
195
190
196
const CommentHeader = ( {
191
197
className,
192
- comment : { uploader , uploaderId , uploadTime } ,
198
+ comment,
193
199
} : {
194
200
className ?: string
195
201
comment : CommentInfo
196
202
} ) => {
203
+ const { uploader, uploaderId, uploadTime } = comment
204
+ const topping = isMainComment ( comment ) ? comment . topping : false
197
205
const [ { userId } ] = useAtom ( authAtom )
198
206
199
207
return (
200
- < div className = { clsx ( className , 'mb-2 flex items-center text-xs' ) } >
208
+ < div
209
+ className = { clsx (
210
+ className ,
211
+ 'mb-2 flex items-center text-xs' ,
212
+ 'leading-[20px]' , // 在无 <Tag> 时保持高度一致
213
+ ) }
214
+ >
201
215
< div className = { clsx ( 'mr-2' , userId === uploaderId && 'font-bold' ) } >
202
216
{ uploader }
203
217
</ div >
204
218
< div className = "text-slate-500" title = { formatDateTime ( uploadTime ) } >
205
219
{ formatRelativeTime ( uploadTime ) }
206
220
</ div >
221
+ { topping && (
222
+ < Tag minimal className = "ml-2" intent = "primary" icon = "pin" >
223
+ 置顶
224
+ </ Tag >
225
+ ) }
207
226
</ div >
208
227
)
209
228
}
@@ -268,6 +287,9 @@ const CommentActions = ({
268
287
>
269
288
回复
270
289
</ Button >
290
+ { userId === comment . uploaderId && isMainComment ( comment ) && (
291
+ < CommentTopButton comment = { comment } />
292
+ ) }
271
293
{ userId === comment . uploaderId && (
272
294
< Button
273
295
minimal
@@ -347,3 +369,35 @@ const CommentRatingButtons = ({ comment }: { comment: CommentInfo }) => {
347
369
</ >
348
370
)
349
371
}
372
+
373
+ const CommentTopButton = ( { comment } : { comment : MainCommentInfo } ) => {
374
+ const { commentId, topping } = comment
375
+ const { reload } = useContext ( CommentAreaContext )
376
+
377
+ const [ pending , setPending ] = useState ( false )
378
+
379
+ const top = async ( ) => {
380
+ if ( pending ) {
381
+ return
382
+ }
383
+
384
+ setPending ( true )
385
+
386
+ try {
387
+ await wrapErrorMessage (
388
+ ( e ) => '置顶失败:' + formatError ( e ) ,
389
+ requestTopComment ( commentId , ! topping ) ,
390
+ )
391
+
392
+ reload ( )
393
+ } finally {
394
+ setPending ( false )
395
+ }
396
+ }
397
+
398
+ return (
399
+ < Button minimal small className = "!font-normal !text-[13px]" onClick = { top } >
400
+ { topping ? '取消置顶' : '置顶' }
401
+ </ Button >
402
+ )
403
+ }
0 commit comments