Files
agt-web/apps/web-antd/src/views/license/project/comment/child-comment.vue
2025-08-12 19:04:36 +08:00

151 lines
4.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script lang="ts" setup>
import type { CommentApi } from '#/api/license/comment';
import { computed, ref } from 'vue';
import { useUserStore } from '@vben/stores';
import { message } from 'ant-design-vue';
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import { deleteComment } from '#/api/license/comment';
import { $t } from '#/locales';
import CreateComment from './create-comment.vue';
const props = withDefaults(
defineProps<{
comments?: CommentApi.Comment[];
data?: CommentApi.Comment;
projectId?: number;
}>(),
{
data: () => ({
id: 0,
author: '',
avatar: '',
updateTime: dayjs(),
depth: 1,
content: '',
children: [],
}),
projectId: 0,
comments: () => [],
},
);
const emit = defineEmits(['getCommentByProjectId']);
const userStore = useUserStore();
const isShowReply = ref<boolean>();
const parentId = ref<number>();
const reply = (id: number) => {
isShowReply.value = !isShowReply.value;
parentId.value = id;
};
const showReply = (flag: boolean) => {
isShowReply.value = flag;
};
const onDelete = async (id: number) => {
try {
await deleteComment(id);
message.success($t('ui.actionMessage.operationSuccess'));
} finally {
emit('getCommentByProjectId', props.projectId);
}
};
dayjs.extend(relativeTime);
const formatContent = computed(() => {
let dataContent = props.data.content || '';
if ((props.data?.depth ?? 0) > 2 && dataContent) {
const position = dataContent.indexOf('>') + 1;
const originalString = dataContent;
const stringToInsert = `<span style="font-size: 12px; color: #32363973">回复 ${props.data?.replyUser}</span>`;
dataContent =
originalString.slice(0, position) +
stringToInsert +
originalString.slice(position);
}
return dataContent;
});
</script>
<template>
<a-comment :author="data.author">
<template #avatar>
<a-avatar :src="data.avatar" :alt="data.author">
{{ data.author?.substring(0, 2) }}
</a-avatar>
</template>
<template #datetime>
<a-tooltip :title="dayjs(data.updateTime)">
<span>{{ dayjs(data.updateTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
</a-tooltip>
</template>
<template #content>
<div>
<!-- eslint-disable-next-line vue/no-v-html -->
<span v-html="formatContent"></span>
</div>
</template>
<template #actions>
<span key="comment-basic-reply-to">
<template v-if="!isShowReply">
<a-tooltip :title="$t('comment.reply')">
<span
class="icon-[mdi--comment-processing-outline] size-3.5"
@click="reply(data.id)"
></span>
</a-tooltip>
</template>
<template v-else>
<a-tooltip :title="$t('comment.cancelReply')">
<span
class="icon-[mdi--comment-processing] size-3.5"
@click="reply(data.id)"
></span>
</a-tooltip>
</template>
</span>
<span
v-if="userStore.userInfo?.id === data.userId"
key="comment-basic-delete"
>
<a-popconfirm
:title="$t('comment.deleteCommentTitle')"
@confirm="onDelete(data.id)"
>
<a-tooltip :title="$t('ui.actionTitle.delete')">
<span class="icon-[ri--delete-bin-line] size-3.5"></span>
</a-tooltip>
</a-popconfirm>
</span>
</template>
<div v-show="isShowReply">
<CreateComment
:project-id="projectId"
:comments="comments"
:parent-id="parentId"
@show-reply="showReply"
@get-comment-by-project-id="emit('getCommentByProjectId', projectId)"
/>
</div>
<template v-if="(data?.depth ?? 0) < 2">
<child-comment
v-for="(item, index) of data.children"
:data="item"
:key="index"
:project-id="projectId"
:comments="comments"
:parent-id="parentId"
@get-comment-by-project-id="emit('getCommentByProjectId', projectId)"
/>
</template>
</a-comment>
</template>