feat: 回复评论

This commit is contained in:
rd
2025-08-08 17:57:50 +08:00
parent 7ad6fcf16f
commit f1f9338e58

View File

@ -74,23 +74,33 @@ export default {
const isCollapse = ref(false);
const comment = ref('');
const isReplay = ref(false);
const commentId = ref(undefined);
const replayTarget = ref({});
const deleteCommentModalRef = ref(null);
const closeReplay = () => {
isReplay.value = false;
replayTarget.value = {};
};
const onReplay = (item) => {
isReplay.value = true;
replayTarget.value = item;
};
const onComment = async () => {
const { code, data } = await postShareWorksComments(props.dataSource.id, route.params.shareCode, {
content: comment.value,
comment_id: commentId.value,
comment_id: replayTarget.value.id,
});
if (code === 200) {
emit('updateComment');
comment.value = '';
// comment.value = '';
}
};
const onClearComment = () => {
isReplay.value = false;
commentId.value = undefined;
replayTarget.value = {};
comment.value = '';
};
@ -123,6 +133,98 @@ export default {
deleteShareWorksComments(props.dataSource.id, comment_id, route.params.shareCode);
};
const renderTextareaBox = () => {
return (
<div class="sticky bottom-0 left-0 w-full z-22 px-24px">
<div class="relative">
{isReplay.value && (
<div class="px-12px pt-8px absolute top-0 left-0 z-2 mb-8px w-full">
<div class="rounded-4px bg-#F2F3F5 h-30px px-8px flex justify-between items-center ">
<div class="flex items-center mr-12px flex-1 overflow-hidden">
<span class="mr-4px cts !color-#737478 flex-shrink-0">回复</span>
<TextOverTips
context={`${getCommentName(replayTarget.value)}${replayTarget.value.content}`}
class="cts !color-#737478"
/>
</div>
<icon-close size={16} class="color-#737478 cursor-pointer flex-shrink-0" onClick={closeReplay} />
</div>
</div>
)}
<Textarea
auto-size
class={`max-h-220px overflow-y-auto ${isReplay.value ? 'pt-38px' : ''}`}
size="large"
placeholder="输入评论"
v-model={comment.value}
onPressEnter={onComment}
/>
</div>
{comment.value && (
<div class="flex justify-end mt-12px">
<Button type="outline" class="mr-12px rounded-8px" size="medium" onClick={onClearComment}>
取消
</Button>
<Button type="primary" class="rounded-8px" size="medium" onClick={onComment}>
发送
</Button>
</div>
)}
</div>
);
};
const renderCommentBox = () => {
return (
<div class="comment-box">
<p class="my-16px">
<span class="cts bold cm !text-16px !lh-24px mr-8px">评论</span>
{props.dataSource.comments?.length > 0 && (
<span class="cts !text-16px !lh-24px bold">{props.dataSource.comments?.length}</span>
)}
</p>
<div class="comment-list flex flex-col my-16px rounded-8px">
{props.dataSource.comments?.map((item) => (
<div class="comment-item flex px-12px py-8px group" key={item.id}>
<Image
src={item.commenter_id === 0 ? icon2 : item.commenter?.head_image}
width={40}
height={40}
preview={false}
fit="cover"
class="rounded-50% mr-13px"
v-slots={{
error: () => <img src={icon3} class="w-40 h-40 rounded-50%" />,
}}
/>
<div class="flex flex-col flex-1">
<div class="flex justify-between">
<p class="mb-4px">
<span class="cts !color-#211F24 mr-8px">{getCommentName(item)}</span>
<span class="cts !color-#939499">{formatRelativeTime(item.created_at)}</span>
</p>
<div class="items-center hidden group-hover:flex">
<SvgIcon
onClick={() => onReplay(item)}
name="svg-comment"
size={16}
class="color-#55585F cursor-pointer hover:color-#6D4CFE"
/>
{renderDeleteBtn(item)}
</div>
</div>
<p class="cts !color-#211F24">{item.content}</p>
</div>
</div>
))}
</div>
</div>
);
};
const getCommentName = (item) => {
if (item.commenter_id === 0) {
return '佚名';
@ -217,72 +319,12 @@ export default {
</div>
</div>
</div>
{/* 评论与回复 */}
<div class="comment-box">
<p class="my-16px">
<span class="cts bold cm !text-16px !lh-24px mr-8px">评论</span>
{props.dataSource.comments?.length > 0 && (
<span class="cts !text-16px !lh-24px bold">{props.dataSource.comments?.length}</span>
)}
</p>
<div class="comment-list flex flex-col my-16px rounded-8px">
{props.dataSource.comments?.map((item) => (
<div class="comment-item flex px-12px py-8px group" key={item.id}>
<Image
src={item.commenter_id === 0 ? icon2 : item.commenter?.head_image}
width={40}
height={40}
preview={false}
fit="cover"
class="rounded-50% mr-13px"
v-slots={{
error: () => <img src={icon3} class="w-40 h-40 rounded-50%" />,
}}
/>
<div class="flex flex-col flex-1">
<div class="flex justify-between">
<p class="mb-4px">
<span class="cts !color-#211F24 mr-8px">{getCommentName(item)}</span>
<span class="cts !color-#939499">{formatRelativeTime(item.created_at)}</span>
</p>
<div class="items-center hidden group-hover:flex">
<SvgIcon
name="svg-comment"
size={16}
class="color-#55585F cursor-pointer hover:color-#6D4CFE"
/>
{renderDeleteBtn(item)}
</div>
</div>
<p class="cts !color-#211F24">{item.content}</p>
</div>
</div>
))}
</div>
</div>
{renderCommentBox()}
</div>
<div class="sticky bottom-0 left-0 w-full z-22 px-24px">
<Textarea
auto-size
class="max-h-220px overflow-y-auto"
size="large"
placeholder="输入评论"
v-model={comment.value}
onPressEnter={onComment}
/>
{comment.value && (
<div class="flex justify-end mt-12px">
<Button type="outline" class="mr-12px rounded-8px" size="medium" onClick={onClearComment}>
取消
</Button>
<Button type="primary" class="rounded-8px" size="medium" onClick={onComment}>
发送
</Button>
</div>
)}
</div>
{renderTextareaBox()}
</div>
<DeleteCommentModal ref={deleteCommentModalRef} onDelete={deleteComment} />
</section>