Add clickable icons to timeline

This commit is contained in:
Tim
2025-07-09 18:03:50 +08:00
parent 5554594123
commit 8feb488c0e
4 changed files with 23 additions and 5 deletions

View File

@@ -1,7 +1,11 @@
<template> <template>
<div class="timeline"> <div class="timeline">
<div class="timeline-item" v-for="(item, idx) in items" :key="idx"> <div class="timeline-item" v-for="(item, idx) in items" :key="idx">
<div class="timeline-icon"> <div
class="timeline-icon"
:class="{ clickable: !!item.iconClick }"
@click="item.iconClick && item.iconClick()"
>
<img v-if="item.src" :src="item.src" class="timeline-img" /> <img v-if="item.src" :src="item.src" class="timeline-img" />
<i v-else-if="item.icon" :class="item.icon"></i> <i v-else-if="item.icon" :class="item.icon"></i>
</div> </div>
@@ -48,6 +52,10 @@ export default {
flex-shrink: 0; flex-shrink: 0;
} }
.timeline-icon.clickable {
cursor: pointer;
}
.timeline-img { .timeline-img {
width: 100%; width: 100%;
height: 100%; height: 100%;

View File

@@ -76,6 +76,7 @@
<script> <script>
import { ref, watch } from 'vue' import { ref, watch } from 'vue'
import { useRouter } from 'vue-router'
import CommentEditor from './CommentEditor.vue' import CommentEditor from './CommentEditor.vue'
import { renderMarkdown } from '../utils/markdown' import { renderMarkdown } from '../utils/markdown'
import BaseTimeline from './BaseTimeline.vue' import BaseTimeline from './BaseTimeline.vue'
@@ -98,6 +99,7 @@ const CommentItem = {
} }
}, },
setup(props) { setup(props) {
const router = useRouter()
const showReplies = ref(props.defaultShowReplies) const showReplies = ref(props.defaultShowReplies)
watch( watch(
() => props.defaultShowReplies, () => props.defaultShowReplies,
@@ -135,18 +137,22 @@ const CommentItem = {
id: data.id, id: data.id,
userName: data.author.username, userName: data.author.username,
time: new Date(data.createdAt).toLocaleDateString('zh-CN', { month: 'numeric', day: 'numeric' }), time: new Date(data.createdAt).toLocaleDateString('zh-CN', { month: 'numeric', day: 'numeric' }),
avatar: data.avatar.username, avatar: data.author.avatar,
text: data.content, text: data.content,
reply: (data.replies || []).map(r => ({ reply: (data.replies || []).map(r => ({
id: r.id, id: r.id,
userName: r.author.username, userName: r.author.username,
time: new Date(r.createdAt).toLocaleDateString('zh-CN', { month: 'numeric', day: 'numeric' }), time: new Date(r.createdAt).toLocaleDateString('zh-CN', { month: 'numeric', day: 'numeric' }),
avatar: r.avatar, avatar: r.author.avatar,
text: r.content, text: r.content,
reply: [], reply: [],
openReplies: false openReplies: false,
src: r.author.avatar,
iconClick: () => router.push(`/users/${r.author.id}`)
})), })),
openReplies: false openReplies: false,
src: data.author.avatar,
iconClick: () => router.push(`/users/${data.author.id}`)
}) })
showEditor.value = false showEditor.value = false
toast.success('回复成功') toast.success('回复成功')

View File

@@ -59,6 +59,7 @@
<script> <script>
import { ref, onMounted } from 'vue' import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { API_BASE_URL } from '../main' import { API_BASE_URL } from '../main'
import BaseTimeline from '../components/BaseTimeline.vue' import BaseTimeline from '../components/BaseTimeline.vue'
import { getToken } from '../utils/auth' import { getToken } from '../utils/auth'
@@ -71,6 +72,7 @@ export default {
name: 'MessagePageView', name: 'MessagePageView',
components: { BaseTimeline }, components: { BaseTimeline },
setup() { setup() {
const router = useRouter()
const notifications = ref([]) const notifications = ref([])
const isLoadingMessage = ref(false) const isLoadingMessage = ref(false)
@@ -112,6 +114,7 @@ export default {
notifications.value.push({ notifications.value.push({
...n, ...n,
src: n.comment.author.avatar, src: n.comment.author.avatar,
iconClick: () => router.push(`/users/${n.comment.author.id}`)
}) })
} else { } else {
notifications.value.push({ notifications.value.push({

View File

@@ -153,6 +153,7 @@ export default {
reply: (c.replies || []).map(mapComment), reply: (c.replies || []).map(mapComment),
openReplies: false, openReplies: false,
src: c.author.avatar, src: c.author.avatar,
iconClick: () => router.push(`/users/${c.author.id}`)
}) })
const getTopRelativeTo = (el, container) => { const getTopRelativeTo = (el, container) => {