mirror of
https://github.com/nagisa77/OpenIsle.git
synced 2026-06-09 03:27:32 +08:00
Add post change log tracking
This commit is contained in:
@@ -122,9 +122,10 @@
|
||||
<l-hatch size="28" stroke="4" speed="3.5" color="var(--primary-color)"></l-hatch>
|
||||
</div>
|
||||
<div v-else class="comments-container">
|
||||
<BaseTimeline :items="comments">
|
||||
<BaseTimeline :items="timelineItems">
|
||||
<template #item="{ item }">
|
||||
<CommentItem
|
||||
v-if="item.kind === 'comment'"
|
||||
:key="item.id"
|
||||
:comment="item"
|
||||
:level="0"
|
||||
@@ -133,6 +134,7 @@
|
||||
:post-closed="closed"
|
||||
@deleted="onCommentDeleted"
|
||||
/>
|
||||
<PostChangeLogItem v-else :key="item.id" :log="item" />
|
||||
</template>
|
||||
</BaseTimeline>
|
||||
</div>
|
||||
@@ -182,6 +184,7 @@ import { useRoute } from 'vue-router'
|
||||
import CommentItem from '~/components/CommentItem.vue'
|
||||
import CommentEditor from '~/components/CommentEditor.vue'
|
||||
import BaseTimeline from '~/components/BaseTimeline.vue'
|
||||
import PostChangeLogItem from '~/components/PostChangeLogItem.vue'
|
||||
import ArticleTags from '~/components/ArticleTags.vue'
|
||||
import ArticleCategory from '~/components/ArticleCategory.vue'
|
||||
import ReactionsGroup from '~/components/ReactionsGroup.vue'
|
||||
@@ -212,6 +215,7 @@ const category = ref('')
|
||||
const tags = ref([])
|
||||
const postReactions = ref([])
|
||||
const comments = ref([])
|
||||
const changeLogs = ref([])
|
||||
const status = ref('PUBLISHED')
|
||||
const closed = ref(false)
|
||||
const pinnedAt = ref(null)
|
||||
@@ -225,6 +229,11 @@ const subscribed = ref(false)
|
||||
const commentSort = ref('NEWEST')
|
||||
const isFetchingComments = ref(false)
|
||||
const isMobile = useIsMobile()
|
||||
const timelineItems = computed(() => {
|
||||
const cs = comments.value.map((c) => ({ ...c, kind: 'comment' }))
|
||||
const ls = changeLogs.value.map((l) => ({ ...l, kind: 'log' }))
|
||||
return [...cs, ...ls].sort((a, b) => new Date(a.time) - new Date(b.time))
|
||||
})
|
||||
|
||||
const headerHeight = import.meta.client
|
||||
? parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--header-height')) || 0
|
||||
@@ -290,8 +299,13 @@ const gatherPostItems = () => {
|
||||
const main = mainContainer.value.querySelector('.info-content-container')
|
||||
if (main) items.push({ el: main, top: getTop(main) })
|
||||
|
||||
for (const c of comments.value) {
|
||||
const el = document.getElementById('comment-' + c.id)
|
||||
for (const c of timelineItems.value) {
|
||||
let el
|
||||
if (c.kind === 'comment') {
|
||||
el = document.getElementById('comment-' + c.id)
|
||||
} else {
|
||||
el = document.getElementById('change-log-' + c.id)
|
||||
}
|
||||
if (el) {
|
||||
items.push({ el, top: getTop(el) })
|
||||
}
|
||||
@@ -329,6 +343,16 @@ const mapComment = (
|
||||
parentUserClick: parentUserId ? () => navigateTo(`/users/${parentUserId}`) : null,
|
||||
})
|
||||
|
||||
const mapChangeLog = (l) => ({
|
||||
id: l.id,
|
||||
username: l.username,
|
||||
type: l.type,
|
||||
time: TimeManager.format(l.time),
|
||||
newClosed: l.newClosed,
|
||||
newPinnedAt: l.newPinnedAt,
|
||||
newFeatured: l.newFeatured,
|
||||
})
|
||||
|
||||
const getTop = (el) => {
|
||||
return el.getBoundingClientRect().top + window.scrollY
|
||||
}
|
||||
@@ -422,19 +446,21 @@ watchEffect(() => {
|
||||
// router.replace('/404')
|
||||
// }
|
||||
|
||||
const totalPosts = computed(() => comments.value.length + 1)
|
||||
const totalPosts = computed(() => timelineItems.value.length + 1)
|
||||
const lastReplyTime = computed(() =>
|
||||
comments.value.length ? comments.value[comments.value.length - 1].time : postTime.value,
|
||||
timelineItems.value.length
|
||||
? timelineItems.value[timelineItems.value.length - 1].time
|
||||
: postTime.value,
|
||||
)
|
||||
const firstReplyTime = computed(() =>
|
||||
comments.value.length ? comments.value[0].time : postTime.value,
|
||||
timelineItems.value.length ? timelineItems.value[0].time : postTime.value,
|
||||
)
|
||||
const scrollerTopTime = computed(() =>
|
||||
commentSort.value === 'OLDEST' ? postTime.value : firstReplyTime.value,
|
||||
)
|
||||
|
||||
watch(
|
||||
() => comments.value.length,
|
||||
() => timelineItems.value.length,
|
||||
async () => {
|
||||
await nextTick()
|
||||
gatherPostItems()
|
||||
@@ -546,6 +572,7 @@ const approvePost = async () => {
|
||||
status.value = 'PUBLISHED'
|
||||
toast.success('已通过审核')
|
||||
await refreshPost()
|
||||
await fetchChangeLogs()
|
||||
} else {
|
||||
toast.error('操作失败')
|
||||
}
|
||||
@@ -561,6 +588,7 @@ const pinPost = async () => {
|
||||
if (res.ok) {
|
||||
toast.success('已置顶')
|
||||
await refreshPost()
|
||||
await fetchChangeLogs()
|
||||
} else {
|
||||
toast.error('操作失败')
|
||||
}
|
||||
@@ -576,6 +604,7 @@ const unpinPost = async () => {
|
||||
if (res.ok) {
|
||||
toast.success('已取消置顶')
|
||||
await refreshPost()
|
||||
await fetchChangeLogs()
|
||||
} else {
|
||||
toast.error('操作失败')
|
||||
}
|
||||
@@ -591,6 +620,7 @@ const excludeRss = async () => {
|
||||
if (res.ok) {
|
||||
rssExcluded.value = true
|
||||
toast.success('已标记为rss不推荐')
|
||||
await fetchChangeLogs()
|
||||
} else {
|
||||
toast.error('操作失败')
|
||||
}
|
||||
@@ -606,6 +636,7 @@ const includeRss = async () => {
|
||||
if (res.ok) {
|
||||
rssExcluded.value = false
|
||||
toast.success('已标记为rss推荐')
|
||||
await fetchChangeLogs()
|
||||
} else {
|
||||
toast.error('操作失败')
|
||||
}
|
||||
@@ -622,6 +653,7 @@ const closePost = async () => {
|
||||
closed.value = true
|
||||
toast.success('已关闭')
|
||||
await refreshPost()
|
||||
await fetchChangeLogs()
|
||||
} else {
|
||||
toast.error('操作失败')
|
||||
}
|
||||
@@ -638,6 +670,7 @@ const reopenPost = async () => {
|
||||
closed.value = false
|
||||
toast.success('已重新打开')
|
||||
await refreshPost()
|
||||
await fetchChangeLogs()
|
||||
} else {
|
||||
toast.error('操作失败')
|
||||
}
|
||||
@@ -682,6 +715,7 @@ const rejectPost = async () => {
|
||||
status.value = 'REJECTED'
|
||||
toast.success('已驳回')
|
||||
await refreshPost()
|
||||
await fetchChangeLogs()
|
||||
} else {
|
||||
toast.error('操作失败')
|
||||
}
|
||||
@@ -740,6 +774,20 @@ const fetchComments = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
const fetchChangeLogs = async () => {
|
||||
try {
|
||||
const res = await fetch(`${API_BASE_URL}/api/posts/${postId}/change-logs`)
|
||||
if (res.ok) {
|
||||
const data = await res.json()
|
||||
changeLogs.value = data.map(mapChangeLog)
|
||||
await nextTick()
|
||||
gatherPostItems()
|
||||
}
|
||||
} catch (e) {
|
||||
console.debug('Fetch change logs error', e)
|
||||
}
|
||||
}
|
||||
|
||||
watch(commentSort, fetchComments)
|
||||
|
||||
const jumpToHashComment = async () => {
|
||||
@@ -763,7 +811,7 @@ const gotoProfile = () => {
|
||||
|
||||
const initPage = async () => {
|
||||
scrollTo(0, 0)
|
||||
await fetchComments()
|
||||
await Promise.all([fetchComments(), fetchChangeLogs()])
|
||||
const hash = location.hash
|
||||
const id = hash.startsWith('#comment-') ? hash.substring('#comment-'.length) : null
|
||||
if (id) expandCommentPath(id)
|
||||
|
||||
Reference in New Issue
Block a user