Initial project
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
import { CommentReplyView, CommentView } from "timi-web";
|
||||
|
||||
/**
|
||||
* emits
|
||||
*/
|
||||
export interface Emits {
|
||||
(event: "reply", comment: CommentView, replyTo?: CommentReplyView): Promise<void>;
|
||||
}
|
||||
|
||||
export const useHandler = (emit: Emits) => {
|
||||
|
||||
const onReply = async (comment: CommentView, replyTo?: CommentReplyView) => await emit("reply", comment, replyTo);
|
||||
|
||||
return {
|
||||
onReply,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
import view from "./index.vue";
|
||||
import { Toolkit } from "timi-web";
|
||||
|
||||
export const CommentReplyList = Toolkit.withInstall(view);
|
||||
export default CommentReplyList;
|
||||
@@ -0,0 +1,179 @@
|
||||
<template>
|
||||
<div class="tui-comment-reply-list">
|
||||
<div v-if="comment && comment.replies" class="reply" v-for="reply in comment.replies" :key="reply.id">
|
||||
<div class="header">
|
||||
<!-- 发送者头像 -->
|
||||
<div class="sender-avatar">
|
||||
<a
|
||||
v-if="reply.sender"
|
||||
:href="`/user/space/${reply.senderId}`"
|
||||
v-popup:config="popupUserStore.config"
|
||||
@mouseenter="popupUserStore.user.value = reply.sender"
|
||||
>
|
||||
<img
|
||||
:class="(<any>ImageType)[reply.sender.profile.avatarType]"
|
||||
:src="UserAPI.getAvatarURL(reply.sender.profile)"
|
||||
alt="回复发送者头像"
|
||||
/>
|
||||
</a>
|
||||
<img v-else class="ir-pixelated" :src="defAvatarURL" alt="回复发送者头像" />
|
||||
</div>
|
||||
<!-- 被回复用户 -->
|
||||
<a
|
||||
v-if="reply.sender"
|
||||
class="pink bold selectable"
|
||||
:href="`/user/space/${reply.senderId}`"
|
||||
target="_blank"
|
||||
v-text="reply.sender.name"
|
||||
v-popup:config="popupUserStore.config"
|
||||
@mouseenter="popupUserStore.user.value = reply.sender"
|
||||
></a>
|
||||
<span
|
||||
v-else
|
||||
class="gray selectable"
|
||||
v-text="reply.senderNick"
|
||||
></span>
|
||||
<!-- 非回复层主时才显示被回复用户 -->
|
||||
<template v-if="!!reply.replyId">
|
||||
<span> 回复 </span>
|
||||
<!-- 被回复用户 -->
|
||||
<a
|
||||
v-if="reply.receiver"
|
||||
class="pink bold selectable"
|
||||
:href="`/user/space/${reply.receiverId}`"
|
||||
target="_blank"
|
||||
v-text="reply.receiver.name"
|
||||
v-popup:config="popupUserStore.config"
|
||||
@mouseenter="popupUserStore.user.value = reply.receiver"
|
||||
></a>
|
||||
<span
|
||||
v-else
|
||||
class="gray selectable"
|
||||
v-text="reply.receiverNick"
|
||||
></span>
|
||||
</template>
|
||||
</div>
|
||||
<!-- 回复内容 -->
|
||||
<markdown-view class="content" :content="reply.content" />
|
||||
<!-- 其他回复信息 -->
|
||||
<div class="reply-to">
|
||||
<a href="javascript:" @click="onReply(comment, reply)">回复</a>
|
||||
<span
|
||||
class="light-gray"
|
||||
v-text="Time.toPassedDate(reply.createdAt)"
|
||||
v-popup:text="Time.toDateTime(reply.createdAt)"
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
CommentView,
|
||||
CommonAPI,
|
||||
ImageType,
|
||||
MarkdownView,
|
||||
PublicResources,
|
||||
SettingKey,
|
||||
SettingMapper,
|
||||
Time,
|
||||
UserAPI
|
||||
} from "timi-web";
|
||||
import { Emits, useHandler } from "~/components/comment/list/reply/emits";
|
||||
import { popupUserStore } from "~/store/popupUser";
|
||||
|
||||
defineOptions({
|
||||
name: "CommentReplyList"
|
||||
});
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
comment: CommentView,
|
||||
}>(), {});
|
||||
const { comment } = toRefs(props);
|
||||
|
||||
const emits = defineEmits<Emits>();
|
||||
const { onReply } = useHandler(emits);
|
||||
|
||||
// 默认头像
|
||||
const defAvatarURL = ref();
|
||||
onMounted(async () => {
|
||||
const res = JSON.parse(SettingMapper.getValue(SettingKey.PUBLIC_RESOURCES) as string) as PublicResources;
|
||||
defAvatarURL.value = CommonAPI.getAttachmentReadAPI(res.user.avatar);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.tui-comment-reply-list {
|
||||
|
||||
.reply {
|
||||
padding: 6px;
|
||||
|
||||
&:nth-child(n + 2) {
|
||||
border-top: 1px #d7d7d7 dotted;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
border-top: 2px solid #E4EFFA;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.sender-avatar {
|
||||
border: 1px solid #FBC7D4;
|
||||
padding: 1px;
|
||||
margin-right: .5rem;
|
||||
|
||||
img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
transition: .5s var(--tui-bezier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
margin-top: .5rem;
|
||||
}
|
||||
|
||||
.reply-to {
|
||||
display: flex;
|
||||
padding-right: 0;
|
||||
justify-content: end;
|
||||
|
||||
> a {
|
||||
margin-right: .5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@media screen and (max-width: 650px) {
|
||||
.tui-comment-reply-list {
|
||||
|
||||
.reply {
|
||||
padding: 3px;
|
||||
transition: .5s var(--tui-bezier);
|
||||
|
||||
.header {
|
||||
|
||||
.sender-avatar {
|
||||
|
||||
img {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
transition: .5s var(--tui-bezier);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user