rebuild: rebuild store
This commit is contained in:
parent
7dee4ff190
commit
0525c389e8
|
@ -13,6 +13,8 @@ export interface TopicAsideOtherTagRequestData {
|
|||
}
|
||||
|
||||
export interface TopicAsideMasterRequestData {
|
||||
// User uid
|
||||
uid: number
|
||||
// The tid of the current topic, as other topics under the same tag should not include the current one
|
||||
tid: string
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<template>
|
||||
<div class="footer">
|
||||
<span>Copyright © 2023 KUNGalgame</span>
|
||||
<span>All rights reserved | Version 1.1.3</span>
|
||||
<span>All rights reserved | Version 1.2.0</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -9,13 +9,22 @@ import MilkdownEditor from './MilkdownEditor.vue'
|
|||
|
||||
// KUN Visual Novel store
|
||||
import { useKUNGalgameEditStore } from '@/store/modules/edit'
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
import { usePersistKUNGalgameReplyStore } from '@/store/modules/topic/reply'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
const { editorHeight, isSaveTopic, content, topicRewrite } = storeToRefs(
|
||||
useKUNGalgameEditStore()
|
||||
)
|
||||
const { replyDraft, replyRewrite } = storeToRefs(useKUNGalgameTopicStore())
|
||||
const {
|
||||
editorHeight: editEditorHeight,
|
||||
isSaveTopic,
|
||||
content,
|
||||
topicRewrite,
|
||||
} = storeToRefs(useKUNGalgameEditStore())
|
||||
const {
|
||||
editorHeight: replyEditorHeight,
|
||||
isSaveReply,
|
||||
isReplyRewriting,
|
||||
replyDraft,
|
||||
replyRewrite,
|
||||
} = storeToRefs(usePersistKUNGalgameReplyStore())
|
||||
|
||||
const props = defineProps<{
|
||||
isShowMenu: boolean
|
||||
|
@ -29,9 +38,7 @@ const valueMarkdown = ref('')
|
|||
|
||||
// Editor height, determined by the route name
|
||||
const editorHeightStyle = computed(() =>
|
||||
routeName.value === 'Edit'
|
||||
? editorHeight.value
|
||||
: replyDraft.value.editorHeight
|
||||
routeName.value === 'Edit' ? editEditorHeight.value : replyEditorHeight.value
|
||||
)
|
||||
|
||||
onBeforeMount(() => {
|
||||
|
@ -53,13 +60,13 @@ onBeforeMount(() => {
|
|||
* Editor is in the reply mode
|
||||
*/
|
||||
// Load reply data before mounting if not saved (and must be on the Topic page)
|
||||
if (replyDraft.value.isSaveReply && routeName.value === 'Topic') {
|
||||
if (isSaveReply.value && routeName.value === 'Topic') {
|
||||
valueMarkdown.value = replyDraft.value.content
|
||||
}
|
||||
/**
|
||||
* Editor is in the re-editing reply mode
|
||||
*/
|
||||
if (replyRewrite.value.isReplyRewriting && routeName.value === 'Topic') {
|
||||
if (isReplyRewriting.value && routeName.value === 'Topic') {
|
||||
valueMarkdown.value = replyRewrite.value.content
|
||||
}
|
||||
})
|
||||
|
@ -85,13 +92,13 @@ const saveMarkdown = (editorMarkdown: string) => {
|
|||
* Editor is in reply mode
|
||||
*/
|
||||
// Save to the reply store if not in reply re-edit mode
|
||||
if (!replyRewrite.value.isReplyRewriting && routeName.value === 'Topic') {
|
||||
if (!isReplyRewriting.value && routeName.value === 'Topic') {
|
||||
replyDraft.value.content = editorMarkdown
|
||||
}
|
||||
/**
|
||||
* Editor is in re-editing reply mode
|
||||
*/
|
||||
if (replyRewrite.value.isReplyRewriting && routeName.value === 'Topic') {
|
||||
if (isReplyRewriting.value && routeName.value === 'Topic') {
|
||||
replyRewrite.value.content = editorMarkdown
|
||||
}
|
||||
}, 1007)
|
||||
|
|
|
@ -1,40 +1,36 @@
|
|||
<script setup lang="ts">
|
||||
import { Icon } from '@iconify/vue'
|
||||
import { computed } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
// Import the icon font
|
||||
import { Icon } from '@iconify/vue'
|
||||
// Import CSS animations
|
||||
import 'animate.css'
|
||||
|
||||
// Import the topic editing store
|
||||
import { useKUNGalgameEditStore } from '@/store/modules/edit'
|
||||
// Import the reply store
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
import { usePersistKUNGalgameReplyStore } from '@/store/modules/topic/reply'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
// Import the keyword display toggle button
|
||||
import SwitchButton from './SwitchButton.vue'
|
||||
|
||||
// Topic editing page store
|
||||
const { editorHeight } = storeToRefs(useKUNGalgameEditStore())
|
||||
// Topic page store for replies
|
||||
const { replyDraft } = storeToRefs(useKUNGalgameTopicStore())
|
||||
const { editorHeight: editEditorHeight } = storeToRefs(useKUNGalgameEditStore())
|
||||
const { editorHeight: replyEditorHeight } = storeToRefs(
|
||||
usePersistKUNGalgameReplyStore()
|
||||
)
|
||||
|
||||
defineProps<{
|
||||
isShowSettingsMenu: boolean
|
||||
}>()
|
||||
|
||||
// Define emits to close the settings panel
|
||||
const emits = defineEmits<{
|
||||
close: [isShowSettingsMenu: boolean]
|
||||
}>()
|
||||
|
||||
// Current route
|
||||
const route = useRoute()
|
||||
// Name of the current page route
|
||||
const routeName = computed(() => route.name as string)
|
||||
const editorHeight = computed(() => {
|
||||
return routeName.value === 'Edit'
|
||||
? `${editEditorHeight.value}px`
|
||||
: `${replyEditorHeight.value}px`
|
||||
})
|
||||
|
||||
// Close the settings panel
|
||||
const handelCloseSettingsPanel = () => {
|
||||
emits('close', false)
|
||||
}
|
||||
|
@ -51,7 +47,7 @@ const handelCloseSettingsPanel = () => {
|
|||
<!-- Editor height settings -->
|
||||
<div class="editor-height-title">
|
||||
<span> {{ $tm('edit.editorHeight') }} </span>
|
||||
<span>{{ editorHeight }} px</span>
|
||||
<span>{{ editorHeight }} </span>
|
||||
</div>
|
||||
|
||||
<!-- Editor page -->
|
||||
|
@ -62,7 +58,7 @@ const handelCloseSettingsPanel = () => {
|
|||
min="200"
|
||||
max="500"
|
||||
step="1"
|
||||
v-model="editorHeight"
|
||||
v-model="editEditorHeight"
|
||||
/>
|
||||
<span>500 px</span>
|
||||
</div>
|
||||
|
@ -75,7 +71,7 @@ const handelCloseSettingsPanel = () => {
|
|||
min="100"
|
||||
max="500"
|
||||
step="1"
|
||||
v-model="replyDraft.editorHeight"
|
||||
v-model="replyEditorHeight"
|
||||
/>
|
||||
<span>500 px</span>
|
||||
</div>
|
||||
|
|
|
@ -11,11 +11,11 @@ const EditorSettingsMenu = defineAsyncComponent(
|
|||
// Import CSS animations
|
||||
import 'animate.css'
|
||||
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
import { usePersistKUNGalgameReplyStore } from '@/store/modules/topic/reply'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
// Topic page store for replies and adjusting reply panel width
|
||||
const { replyPanelWidth } = storeToRefs(useKUNGalgameTopicStore())
|
||||
const { replyPanelWidth } = storeToRefs(usePersistKUNGalgameReplyStore())
|
||||
|
||||
// Current route
|
||||
const route = useRoute()
|
||||
|
|
|
@ -3,10 +3,9 @@
|
|||
<script setup lang="ts">
|
||||
import { watch, computed } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
// Import the store for the editing page
|
||||
|
||||
import { useKUNGalgameEditStore } from '@/store/modules/edit'
|
||||
// Import the store for replies
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
import { usePersistKUNGalgameReplyStore } from '@/store/modules/topic/reply'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
// Current page's route
|
||||
|
@ -15,16 +14,20 @@ const route = useRoute()
|
|||
const routeName = computed(() => route.name as string)
|
||||
|
||||
// Use the store for the editing page
|
||||
const { isShowHotKeywords } = storeToRefs(useKUNGalgameEditStore())
|
||||
const { isShowHotKeywords: isShowEditHotKeywords } = storeToRefs(
|
||||
useKUNGalgameEditStore()
|
||||
)
|
||||
// Store for the topic page, used for replies
|
||||
const { replyDraft } = storeToRefs(useKUNGalgameTopicStore())
|
||||
const { isShowHotKeywords: isShowReplyHotKeywords, replyDraft } = storeToRefs(
|
||||
usePersistKUNGalgameReplyStore()
|
||||
)
|
||||
|
||||
// Watch for changes in store states to keep button states in sync with the store
|
||||
watch(
|
||||
() => [isShowHotKeywords.value, replyDraft.value.isShowHotKeywords],
|
||||
() => [isShowEditHotKeywords.value, isShowReplyHotKeywords.value],
|
||||
([newValue1, newValue2]) => {
|
||||
isShowHotKeywords.value = newValue1
|
||||
replyDraft.value.isShowHotKeywords = newValue2
|
||||
isShowEditHotKeywords.value = newValue1
|
||||
isShowReplyHotKeywords.value = newValue2
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
@ -35,13 +38,14 @@ watch(
|
|||
v-if="routeName === 'Edit'"
|
||||
type="checkbox"
|
||||
id="switch"
|
||||
v-model="isShowHotKeywords"
|
||||
v-model="isShowEditHotKeywords"
|
||||
/>
|
||||
|
||||
<input
|
||||
v-if="routeName === 'Topic'"
|
||||
type="checkbox"
|
||||
id="switch"
|
||||
v-model="replyDraft.isShowHotKeywords"
|
||||
v-model="isShowReplyHotKeywords"
|
||||
/>
|
||||
<label for="switch"></label>
|
||||
</template>
|
||||
|
|
|
@ -7,11 +7,11 @@ import Settings from '../components/Settings.vue'
|
|||
import { usePluginViewContext } from '@prosemirror-adapter/vue'
|
||||
|
||||
import { useKUNGalgameEditStore } from '@/store/modules/edit'
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
import { useTempReplyStore } from '@/store/temp/topic/reply'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
const { textCount } = storeToRefs(useKUNGalgameEditStore())
|
||||
const { replyDraft } = storeToRefs(useKUNGalgameTopicStore())
|
||||
const { textCount: textCountEdit } = storeToRefs(useKUNGalgameEditStore())
|
||||
const { textCount: textCountReply } = storeToRefs(useTempReplyStore())
|
||||
|
||||
const { view } = usePluginViewContext()
|
||||
|
||||
|
@ -26,10 +26,10 @@ watch(
|
|||
() => size.value,
|
||||
() => {
|
||||
if (routeName.value === 'Edit') {
|
||||
textCount.value = size.value
|
||||
textCountEdit.value = size.value
|
||||
}
|
||||
if (routeName.value === 'Topic') {
|
||||
replyDraft.value.textCount = size.value
|
||||
textCountReply.value = size.value
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
<script setup lang="ts">
|
||||
const count = 7
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
count?: number
|
||||
}>()
|
||||
|
||||
const count = computed(() => (props.count ? props.count : 1))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -31,7 +31,8 @@ import { useKUNGalgameRankingStore } from './modules/ranking'
|
|||
import { useKUNGalgameSettingsStore } from '@/store/modules/settings'
|
||||
|
||||
// Import store for the topic detail page
|
||||
import { useKUNGalgameTopicStore } from './modules/topic'
|
||||
import { usePersistKUNGalgameTopicStore } from '@/store/modules/topic/topic'
|
||||
import { usePersistKUNGalgameReplyStore } from '@/store/modules/topic/reply'
|
||||
|
||||
const store = createPinia()
|
||||
|
||||
|
@ -51,7 +52,8 @@ export function kungalgameStoreReset() {
|
|||
const nonMoeStore = useKUNGalgameNonMoeStore()
|
||||
const rankingStore = useKUNGalgameRankingStore()
|
||||
const settingsStore = useKUNGalgameSettingsStore()
|
||||
const topicStore = useKUNGalgameTopicStore()
|
||||
const topicStore = usePersistKUNGalgameTopicStore()
|
||||
const replyStore = usePersistKUNGalgameReplyStore()
|
||||
|
||||
balanceStore.$reset()
|
||||
editStore.$reset()
|
||||
|
@ -62,4 +64,5 @@ export function kungalgameStoreReset() {
|
|||
rankingStore.$reset()
|
||||
settingsStore.$reset()
|
||||
topicStore.$reset()
|
||||
replyStore.$reset()
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/*
|
||||
|
||||
User Information Storage
|
||||
*/
|
||||
import { defineStore } from 'pinia'
|
||||
|
|
|
@ -1,339 +0,0 @@
|
|||
// Store for topic details
|
||||
import { defineStore } from 'pinia'
|
||||
// Topics
|
||||
import {
|
||||
getTopicByTidApi,
|
||||
getRelatedTopicsByTagsApi,
|
||||
getPopularTopicsByUserUidApi,
|
||||
updateTopicUpvoteApi,
|
||||
updateTopicLikeApi,
|
||||
updateTopicDislikeApi,
|
||||
} from '@/api'
|
||||
|
||||
import type {
|
||||
TopicDetailResponseData,
|
||||
TopicAsideOtherTagRequestData,
|
||||
TopicAsideMasterRequestData,
|
||||
TopicAsideResponseData,
|
||||
TopicUpvoteTopicRequestData,
|
||||
TopicUpvoteTopicResponseData,
|
||||
TopicLikeTopicRequestData,
|
||||
TopicLikeTopicResponseData,
|
||||
TopicDislikeTopicRequestData,
|
||||
TopicDislikeTopicResponseData,
|
||||
} from '@/api'
|
||||
|
||||
// Replies
|
||||
import {
|
||||
getRepliesByPidApi,
|
||||
postReplyByPidApi,
|
||||
updateReplyUpvoteApi,
|
||||
updateReplyLikeApi,
|
||||
updateReplyDislikeApi,
|
||||
updateReplyApi,
|
||||
} from '@/api'
|
||||
|
||||
import type {
|
||||
TopicReplyRequestData,
|
||||
TopicReplyResponseData,
|
||||
TopicCreateReplyRequestData,
|
||||
TopicCreateReplyResponseData,
|
||||
TopicUpvoteReplyRequestData,
|
||||
TopicUpvoteReplyResponseData,
|
||||
TopicLikeReplyRequestData,
|
||||
TopicLikeReplyResponseData,
|
||||
TopicDislikeReplyRequestData,
|
||||
TopicDislikeReplyResponseData,
|
||||
TopicUpdateReplyRequestData,
|
||||
TopicUpdateReplyResponseData,
|
||||
} from '@/api'
|
||||
|
||||
// Comments
|
||||
import {
|
||||
getCommentsByReplyRidApi,
|
||||
updateCommentLikeApi,
|
||||
updateCommentDislikeApi,
|
||||
postCommentByPidAndRidApi,
|
||||
} from '@/api'
|
||||
|
||||
import type {
|
||||
TopicCommentResponseData,
|
||||
TopicLikeCommentRequestData,
|
||||
TopicLikeCommentResponseData,
|
||||
TopicDislikeCommentRequestData,
|
||||
TopicDislikeCommentResponseData,
|
||||
TopicCreateCommentRequestData,
|
||||
TopicCreateCommentResponseData,
|
||||
} from '@/api'
|
||||
|
||||
// Import the type of topic store
|
||||
import { TopicStore } from '../types/topic'
|
||||
|
||||
export const useKUNGalgameTopicStore = defineStore({
|
||||
id: 'KUNGalgameTopic',
|
||||
persist: true,
|
||||
state: (): TopicStore => ({
|
||||
isEdit: false,
|
||||
isShowAdvance: false,
|
||||
isActiveAside: false,
|
||||
isScrollToTop: false,
|
||||
isLoading: true,
|
||||
// Reply ID starts from 0, -1 is just for monitoring data changes
|
||||
// , used for watchEffect
|
||||
scrollToReplyId: -1,
|
||||
|
||||
replyPanelWidth: 90,
|
||||
replyDraft: {
|
||||
editorHeight: 200,
|
||||
textCount: 0,
|
||||
mode: 'minimal',
|
||||
theme: 'snow',
|
||||
isShowHotKeywords: true,
|
||||
|
||||
tid: 0,
|
||||
toUserName: '',
|
||||
to_uid: 0,
|
||||
content: '',
|
||||
tags: [],
|
||||
to_floor: 0,
|
||||
|
||||
isSaveReply: false,
|
||||
},
|
||||
replyRequest: {
|
||||
page: 1,
|
||||
limit: 3,
|
||||
sortField: 'floor',
|
||||
sortOrder: 'asc',
|
||||
},
|
||||
replyRewrite: {
|
||||
tid: 0,
|
||||
rid: 0,
|
||||
content: '',
|
||||
tags: [],
|
||||
|
||||
isReplyRewriting: false,
|
||||
},
|
||||
}),
|
||||
actions: {
|
||||
// Other topics under the same tag on the left
|
||||
async getRelatedTopicsByTags(
|
||||
request: TopicAsideOtherTagRequestData
|
||||
): Promise<TopicAsideResponseData> {
|
||||
return await getRelatedTopicsByTagsApi(request)
|
||||
},
|
||||
|
||||
// Other topics by the master
|
||||
async getPopularTopicsByUserUid(
|
||||
request: TopicAsideMasterRequestData
|
||||
): Promise<TopicAsideResponseData> {
|
||||
return await getPopularTopicsByUserUidApi(request)
|
||||
},
|
||||
|
||||
// Get a single topic
|
||||
async getTopicByTid(tid: number): Promise<TopicDetailResponseData> {
|
||||
return await getTopicByTidApi(tid)
|
||||
},
|
||||
|
||||
// Upvote a topic
|
||||
async updateTopicUpvote(
|
||||
tid: number,
|
||||
toUid: number
|
||||
): Promise<TopicUpvoteTopicResponseData> {
|
||||
const requestData: TopicUpvoteTopicRequestData = {
|
||||
tid: tid,
|
||||
to_uid: toUid,
|
||||
}
|
||||
return await updateTopicUpvoteApi(requestData)
|
||||
},
|
||||
|
||||
// Like a topic
|
||||
async updateTopicLike(
|
||||
tid: number,
|
||||
toUid: number,
|
||||
isPush: boolean
|
||||
): Promise<TopicLikeTopicResponseData> {
|
||||
const requestData: TopicLikeTopicRequestData = {
|
||||
tid: tid,
|
||||
to_uid: toUid,
|
||||
isPush: isPush,
|
||||
}
|
||||
return await updateTopicLikeApi(requestData)
|
||||
},
|
||||
|
||||
// Dislike a topic
|
||||
async updateTopicDislike(
|
||||
tid: number,
|
||||
toUid: number,
|
||||
isPush: boolean
|
||||
): Promise<TopicDislikeTopicResponseData> {
|
||||
const requestData: TopicDislikeTopicRequestData = {
|
||||
tid: tid,
|
||||
to_uid: toUid,
|
||||
isPush: isPush,
|
||||
}
|
||||
return await updateTopicDislikeApi(requestData)
|
||||
},
|
||||
|
||||
// Get replies
|
||||
async getReplies(tid: number): Promise<TopicReplyResponseData> {
|
||||
// The default values here are used for initialization
|
||||
const requestData: TopicReplyRequestData = {
|
||||
tid: tid,
|
||||
page: this.replyRequest.page,
|
||||
limit: this.replyRequest.limit,
|
||||
sortField: this.replyRequest.sortField || 'floor',
|
||||
sortOrder: this.replyRequest.sortOrder || 'desc',
|
||||
}
|
||||
return await getRepliesByPidApi(requestData)
|
||||
},
|
||||
|
||||
// Create a new reply
|
||||
async postNewReply(): Promise<TopicCreateReplyResponseData> {
|
||||
// The values here are used to initialize the reply
|
||||
const requestData: TopicCreateReplyRequestData = {
|
||||
tid: this.replyDraft.tid,
|
||||
to_uid: this.replyDraft.to_uid,
|
||||
to_floor: this.replyDraft.to_floor,
|
||||
tags: this.replyDraft.tags,
|
||||
content: this.replyDraft.content,
|
||||
}
|
||||
return await postReplyByPidApi(requestData)
|
||||
},
|
||||
|
||||
// Update a reply
|
||||
async updateReply(): Promise<TopicUpdateReplyResponseData> {
|
||||
const requestData: TopicUpdateReplyRequestData = {
|
||||
tid: this.replyRewrite.tid,
|
||||
rid: this.replyRewrite.rid,
|
||||
content: this.replyRewrite.content,
|
||||
tags: this.replyRewrite.tags,
|
||||
}
|
||||
return await updateReplyApi(requestData)
|
||||
},
|
||||
|
||||
// Upvote a reply
|
||||
async updateReplyUpvote(
|
||||
tid: number,
|
||||
toUid: number,
|
||||
rid: number
|
||||
): Promise<TopicUpvoteReplyResponseData> {
|
||||
const requestData: TopicUpvoteReplyRequestData = {
|
||||
tid: tid,
|
||||
to_uid: toUid,
|
||||
rid: rid,
|
||||
}
|
||||
return await updateReplyUpvoteApi(requestData)
|
||||
},
|
||||
|
||||
// Like a reply
|
||||
async updateReplyLike(
|
||||
tid: number,
|
||||
toUid: number,
|
||||
rid: number,
|
||||
isPush: boolean
|
||||
): Promise<TopicLikeReplyResponseData> {
|
||||
const requestData: TopicLikeReplyRequestData = {
|
||||
tid: tid,
|
||||
to_uid: toUid,
|
||||
rid: rid,
|
||||
isPush: isPush,
|
||||
}
|
||||
return await updateReplyLikeApi(requestData)
|
||||
},
|
||||
|
||||
// Dislike a reply
|
||||
async updateReplyDislike(
|
||||
tid: number,
|
||||
toUid: number,
|
||||
rid: number,
|
||||
isPush: boolean
|
||||
): Promise<TopicDislikeReplyResponseData> {
|
||||
const requestData: TopicDislikeReplyRequestData = {
|
||||
tid: tid,
|
||||
to_uid: toUid,
|
||||
rid: rid,
|
||||
isPush: isPush,
|
||||
}
|
||||
return await updateReplyDislikeApi(requestData)
|
||||
},
|
||||
|
||||
// Get comments
|
||||
async getComments(
|
||||
tid: number,
|
||||
rid: number
|
||||
): Promise<TopicCommentResponseData> {
|
||||
return await getCommentsByReplyRidApi(tid, rid)
|
||||
},
|
||||
|
||||
// Like a comment
|
||||
async updateCommentLike(
|
||||
tid: number,
|
||||
cid: number,
|
||||
toUid: number
|
||||
): Promise<TopicLikeCommentResponseData> {
|
||||
const requestData: TopicLikeCommentRequestData = {
|
||||
tid: tid,
|
||||
cid: cid,
|
||||
to_uid: toUid,
|
||||
}
|
||||
return await updateCommentLikeApi(requestData)
|
||||
},
|
||||
|
||||
// Dislike a comment
|
||||
async updateCommentDislike(
|
||||
tid: number,
|
||||
cid: number,
|
||||
toUid: number
|
||||
): Promise<TopicDislikeCommentResponseData> {
|
||||
const requestData: TopicDislikeCommentRequestData = {
|
||||
tid: tid,
|
||||
cid: cid,
|
||||
to_uid: toUid,
|
||||
}
|
||||
return await updateCommentDislikeApi(requestData)
|
||||
},
|
||||
|
||||
// Create a new comment
|
||||
async postNewComment(
|
||||
tid: number,
|
||||
rid: number,
|
||||
toUid: number,
|
||||
content: string
|
||||
): Promise<TopicCreateCommentResponseData> {
|
||||
const requestData: TopicCreateCommentRequestData = {
|
||||
tid: tid,
|
||||
rid: rid,
|
||||
to_uid: toUid,
|
||||
content: content,
|
||||
}
|
||||
return await postCommentByPidAndRidApi(requestData)
|
||||
},
|
||||
|
||||
// Reset reply draft to its original value, used for the reply publish button
|
||||
resetReplyDraft() {
|
||||
this.replyDraft.textCount = 0
|
||||
this.replyDraft.tid = 0
|
||||
this.replyDraft.toUserName = ''
|
||||
this.replyDraft.to_uid = 0
|
||||
this.replyDraft.content = ''
|
||||
this.replyDraft.tags = []
|
||||
|
||||
this.replyDraft.isSaveReply = false
|
||||
},
|
||||
// Reset page number and loading status for reply sorting to take effect
|
||||
resetPageStatus() {
|
||||
this.replyRequest.page = 1
|
||||
this.isLoading = true
|
||||
},
|
||||
// Reset data for re-editing a reply
|
||||
resetRewriteTopicData() {
|
||||
this.replyDraft.textCount = 0
|
||||
this.replyRewrite.tid = 0
|
||||
this.replyRewrite.rid = 0
|
||||
this.replyRewrite.content = ''
|
||||
this.replyRewrite.tags = []
|
||||
|
||||
this.replyRewrite.isReplyRewriting = false
|
||||
},
|
||||
},
|
||||
})
|
91
src/store/modules/topic/reply.ts
Normal file
91
src/store/modules/topic/reply.ts
Normal file
|
@ -0,0 +1,91 @@
|
|||
import { defineStore } from 'pinia'
|
||||
|
||||
// Replies
|
||||
import { postReplyByPidApi, updateReplyApi } from '@/api'
|
||||
|
||||
import type {
|
||||
TopicCreateReplyRequestData,
|
||||
TopicCreateReplyResponseData,
|
||||
TopicUpdateReplyRequestData,
|
||||
TopicUpdateReplyResponseData,
|
||||
} from '@/api'
|
||||
|
||||
import { ReplyStorePersist } from '@/store/types/topic/reply'
|
||||
|
||||
export const usePersistKUNGalgameReplyStore = defineStore({
|
||||
id: 'KUNGalgameReply',
|
||||
persist: true,
|
||||
state: (): ReplyStorePersist => ({
|
||||
replyPanelWidth: 90,
|
||||
|
||||
isSaveReply: false,
|
||||
isShowHotKeywords: true,
|
||||
editorHeight: 200,
|
||||
|
||||
// Whether the reply is being rewritten
|
||||
isReplyRewriting: false,
|
||||
|
||||
replyDraft: {
|
||||
tid: 0,
|
||||
toUserName: '',
|
||||
toUid: 0,
|
||||
content: '',
|
||||
tags: [],
|
||||
toFloor: 0,
|
||||
},
|
||||
replyRewrite: {
|
||||
tid: 0,
|
||||
rid: 0,
|
||||
content: '',
|
||||
tags: [],
|
||||
edited: 0,
|
||||
},
|
||||
}),
|
||||
actions: {
|
||||
// Create a new reply
|
||||
async postNewReply(): Promise<TopicCreateReplyResponseData> {
|
||||
// The values here are used to initialize the reply
|
||||
const requestData: TopicCreateReplyRequestData = {
|
||||
tid: this.replyDraft.tid,
|
||||
to_uid: this.replyDraft.toUid,
|
||||
to_floor: this.replyDraft.toFloor,
|
||||
tags: this.replyDraft.tags,
|
||||
content: this.replyDraft.content,
|
||||
}
|
||||
return await postReplyByPidApi(requestData)
|
||||
},
|
||||
|
||||
// Update a reply
|
||||
async updateReply(): Promise<TopicUpdateReplyResponseData> {
|
||||
const requestData: TopicUpdateReplyRequestData = {
|
||||
tid: this.replyRewrite.tid,
|
||||
rid: this.replyRewrite.rid,
|
||||
content: this.replyRewrite.content,
|
||||
tags: this.replyRewrite.tags,
|
||||
}
|
||||
return await updateReplyApi(requestData)
|
||||
},
|
||||
|
||||
// Reset reply draft to its original value, used for the reply publish button
|
||||
resetReplyDraft() {
|
||||
this.replyDraft.tid = 0
|
||||
this.replyDraft.toUserName = ''
|
||||
this.replyDraft.toUid = 0
|
||||
this.replyDraft.content = ''
|
||||
this.replyDraft.tags = []
|
||||
this.replyDraft.toFloor = 0
|
||||
|
||||
this.isSaveReply = false
|
||||
},
|
||||
|
||||
// Reset data for re-editing a reply
|
||||
resetRewriteReplyData() {
|
||||
this.replyRewrite.tid = 0
|
||||
this.replyRewrite.rid = 0
|
||||
this.replyRewrite.content = ''
|
||||
this.replyRewrite.tags = []
|
||||
|
||||
this.isReplyRewriting = false
|
||||
},
|
||||
},
|
||||
})
|
13
src/store/modules/topic/topic.ts
Normal file
13
src/store/modules/topic/topic.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { defineStore } from 'pinia'
|
||||
import { TopicStorePersist } from '@/store/types/topic/topic'
|
||||
|
||||
export const usePersistKUNGalgameTopicStore = defineStore({
|
||||
id: 'KUNGalgameTopic',
|
||||
persist: true,
|
||||
state: (): TopicStorePersist => ({
|
||||
// Whether to show advanced editing mode
|
||||
isShowAdvance: false,
|
||||
// Whether to activate the left interaction panel
|
||||
isActiveAside: false,
|
||||
}),
|
||||
})
|
|
@ -1,20 +0,0 @@
|
|||
// Temporary data for comments, used for inter-component communication
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useTempCommentStore = defineStore({
|
||||
id: 'tempComment',
|
||||
// Not persistent
|
||||
persist: false,
|
||||
state: () => ({
|
||||
tid: 0,
|
||||
rid: 0,
|
||||
toUid: 0,
|
||||
toUsername: '',
|
||||
content: '',
|
||||
|
||||
// Which reply's comment panel to display
|
||||
isShowCommentPanelRid: 0,
|
||||
}),
|
||||
getters: {},
|
||||
actions: {},
|
||||
})
|
0
src/store/temp/home.ts
Normal file
0
src/store/temp/home.ts
Normal file
|
@ -1,40 +0,0 @@
|
|||
// Temporary data for replies, used for inter-component communication
|
||||
import { defineStore } from 'pinia'
|
||||
import type { TopicReply } from '@/api'
|
||||
|
||||
export const useTempReplyStore = defineStore({
|
||||
id: 'tempReply',
|
||||
// Not persistent
|
||||
persist: false,
|
||||
state: () => ({
|
||||
tempReply: {
|
||||
rid: 0,
|
||||
tid: 0,
|
||||
// Floor where the reply is located
|
||||
floor: 0,
|
||||
// Floor where the replied reply is located
|
||||
to_floor: 0,
|
||||
r_user: {
|
||||
uid: 0,
|
||||
name: '',
|
||||
avatar: '',
|
||||
moemoepoint: 0,
|
||||
},
|
||||
to_user: {
|
||||
uid: 0,
|
||||
name: '',
|
||||
},
|
||||
edited: 0,
|
||||
content: '',
|
||||
upvotes: [],
|
||||
upvote_time: 0,
|
||||
likes: [],
|
||||
dislikes: [],
|
||||
tags: [],
|
||||
time: 0,
|
||||
comment: [],
|
||||
} as TopicReply,
|
||||
}),
|
||||
getters: {},
|
||||
actions: {},
|
||||
})
|
|
@ -1,13 +0,0 @@
|
|||
// Temporary data for reply rewriting, used for inter-component communication
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useTempReplyRewriteStore = defineStore({
|
||||
id: 'tempReplyRewrite',
|
||||
// Not persistent
|
||||
persist: false,
|
||||
// Only these three data are affected by reply rewriting
|
||||
// , updating these three data makes it reactive
|
||||
state: () => ({ rid: 0, replyContent: '', tags: [''], edited: 0 }),
|
||||
getters: {},
|
||||
actions: {},
|
||||
})
|
89
src/store/temp/topic/comment.ts
Normal file
89
src/store/temp/topic/comment.ts
Normal file
|
@ -0,0 +1,89 @@
|
|||
import { defineStore } from 'pinia'
|
||||
import type { CommentDraft } from '@/store/types/topic/comment'
|
||||
|
||||
// Comments
|
||||
import {
|
||||
getCommentsByReplyRidApi,
|
||||
updateCommentLikeApi,
|
||||
updateCommentDislikeApi,
|
||||
postCommentByPidAndRidApi,
|
||||
} from '@/api'
|
||||
|
||||
import type {
|
||||
TopicCommentResponseData,
|
||||
TopicLikeCommentRequestData,
|
||||
TopicLikeCommentResponseData,
|
||||
TopicDislikeCommentRequestData,
|
||||
TopicDislikeCommentResponseData,
|
||||
TopicCreateCommentRequestData,
|
||||
TopicCreateCommentResponseData,
|
||||
} from '@/api'
|
||||
|
||||
export const useTempCommentStore = defineStore({
|
||||
id: 'tempComment',
|
||||
// Not persistent
|
||||
persist: false,
|
||||
state: (): CommentDraft => ({
|
||||
tid: 0,
|
||||
rid: 0,
|
||||
toUid: 0,
|
||||
toUsername: '',
|
||||
content: '',
|
||||
|
||||
// Which reply's comment panel to display
|
||||
isShowCommentPanelRid: 0,
|
||||
}),
|
||||
actions: {
|
||||
// Get comments
|
||||
async getComments(
|
||||
tid: number,
|
||||
rid: number
|
||||
): Promise<TopicCommentResponseData> {
|
||||
return await getCommentsByReplyRidApi(tid, rid)
|
||||
},
|
||||
|
||||
// Like a comment
|
||||
async updateCommentLike(
|
||||
tid: number,
|
||||
cid: number,
|
||||
toUid: number
|
||||
): Promise<TopicLikeCommentResponseData> {
|
||||
const requestData: TopicLikeCommentRequestData = {
|
||||
tid: tid,
|
||||
cid: cid,
|
||||
to_uid: toUid,
|
||||
}
|
||||
return await updateCommentLikeApi(requestData)
|
||||
},
|
||||
|
||||
// Dislike a comment
|
||||
async updateCommentDislike(
|
||||
tid: number,
|
||||
cid: number,
|
||||
toUid: number
|
||||
): Promise<TopicDislikeCommentResponseData> {
|
||||
const requestData: TopicDislikeCommentRequestData = {
|
||||
tid: tid,
|
||||
cid: cid,
|
||||
to_uid: toUid,
|
||||
}
|
||||
return await updateCommentDislikeApi(requestData)
|
||||
},
|
||||
|
||||
// Create a new comment
|
||||
async postNewComment(
|
||||
tid: number,
|
||||
rid: number,
|
||||
toUid: number,
|
||||
content: string
|
||||
): Promise<TopicCreateCommentResponseData> {
|
||||
const requestData: TopicCreateCommentRequestData = {
|
||||
tid: tid,
|
||||
rid: rid,
|
||||
to_uid: toUid,
|
||||
content: content,
|
||||
}
|
||||
return await postCommentByPidAndRidApi(requestData)
|
||||
},
|
||||
},
|
||||
})
|
131
src/store/temp/topic/reply.ts
Normal file
131
src/store/temp/topic/reply.ts
Normal file
|
@ -0,0 +1,131 @@
|
|||
import { defineStore } from 'pinia'
|
||||
// Replies
|
||||
import {
|
||||
getRepliesByPidApi,
|
||||
updateReplyUpvoteApi,
|
||||
updateReplyLikeApi,
|
||||
updateReplyDislikeApi,
|
||||
} from '@/api'
|
||||
|
||||
import type {
|
||||
TopicReplyRequestData,
|
||||
TopicReplyResponseData,
|
||||
TopicUpvoteReplyRequestData,
|
||||
TopicUpvoteReplyResponseData,
|
||||
TopicLikeReplyRequestData,
|
||||
TopicLikeReplyResponseData,
|
||||
TopicDislikeReplyRequestData,
|
||||
TopicDislikeReplyResponseData,
|
||||
} from '@/api'
|
||||
|
||||
import type { ReplyStoreTemp } from '@/store/types/topic/reply'
|
||||
|
||||
export const useTempReplyStore = defineStore({
|
||||
id: 'tempReply',
|
||||
persist: false,
|
||||
state: (): ReplyStoreTemp => ({
|
||||
textCount: 0,
|
||||
isEdit: false,
|
||||
isScrollToTop: false,
|
||||
isLoading: true,
|
||||
// Reply ID starts from 0, -1 is just for monitoring data changes
|
||||
scrollToReplyId: -1,
|
||||
|
||||
replyRequest: {
|
||||
page: 1,
|
||||
limit: 3,
|
||||
sortField: 'floor',
|
||||
sortOrder: 'asc',
|
||||
},
|
||||
|
||||
tempReply: {
|
||||
rid: 0,
|
||||
tid: 0,
|
||||
// Floor where the reply is located
|
||||
floor: 0,
|
||||
// Floor where the replied reply is located
|
||||
to_floor: 0,
|
||||
r_user: {
|
||||
uid: 0,
|
||||
name: '',
|
||||
avatar: '',
|
||||
moemoepoint: 0,
|
||||
},
|
||||
to_user: {
|
||||
uid: 0,
|
||||
name: '',
|
||||
},
|
||||
edited: 0,
|
||||
content: '',
|
||||
upvotes: [],
|
||||
upvote_time: 0,
|
||||
likes: [],
|
||||
dislikes: [],
|
||||
tags: [],
|
||||
time: 0,
|
||||
comment: [],
|
||||
},
|
||||
|
||||
tempReplyRewrite: { rid: 0, content: '', tags: [''], edited: 0 },
|
||||
}),
|
||||
actions: {
|
||||
// Get replies
|
||||
async getReplies(tid: number): Promise<TopicReplyResponseData> {
|
||||
// The default values here are used for initialization
|
||||
const requestData: TopicReplyRequestData = {
|
||||
tid: tid,
|
||||
page: this.replyRequest.page,
|
||||
limit: this.replyRequest.limit,
|
||||
sortField: this.replyRequest.sortField || 'floor',
|
||||
sortOrder: this.replyRequest.sortOrder || 'desc',
|
||||
}
|
||||
return await getRepliesByPidApi(requestData)
|
||||
},
|
||||
|
||||
// Upvote a reply
|
||||
async updateReplyUpvote(
|
||||
tid: number,
|
||||
toUid: number,
|
||||
rid: number
|
||||
): Promise<TopicUpvoteReplyResponseData> {
|
||||
const requestData: TopicUpvoteReplyRequestData = {
|
||||
tid: tid,
|
||||
to_uid: toUid,
|
||||
rid: rid,
|
||||
}
|
||||
return await updateReplyUpvoteApi(requestData)
|
||||
},
|
||||
|
||||
// Like a reply
|
||||
async updateReplyLike(
|
||||
tid: number,
|
||||
toUid: number,
|
||||
rid: number,
|
||||
isPush: boolean
|
||||
): Promise<TopicLikeReplyResponseData> {
|
||||
const requestData: TopicLikeReplyRequestData = {
|
||||
tid: tid,
|
||||
to_uid: toUid,
|
||||
rid: rid,
|
||||
isPush: isPush,
|
||||
}
|
||||
return await updateReplyLikeApi(requestData)
|
||||
},
|
||||
|
||||
// Dislike a reply
|
||||
async updateReplyDislike(
|
||||
tid: number,
|
||||
toUid: number,
|
||||
rid: number,
|
||||
isPush: boolean
|
||||
): Promise<TopicDislikeReplyResponseData> {
|
||||
const requestData: TopicDislikeReplyRequestData = {
|
||||
tid: tid,
|
||||
to_uid: toUid,
|
||||
rid: rid,
|
||||
isPush: isPush,
|
||||
}
|
||||
return await updateReplyDislikeApi(requestData)
|
||||
},
|
||||
},
|
||||
})
|
89
src/store/temp/topic/topic.ts
Normal file
89
src/store/temp/topic/topic.ts
Normal file
|
@ -0,0 +1,89 @@
|
|||
import { defineStore } from 'pinia'
|
||||
|
||||
// Topics
|
||||
import {
|
||||
getTopicByTidApi,
|
||||
getRelatedTopicsByTagsApi,
|
||||
getPopularTopicsByUserUidApi,
|
||||
updateTopicUpvoteApi,
|
||||
updateTopicLikeApi,
|
||||
updateTopicDislikeApi,
|
||||
} from '@/api'
|
||||
|
||||
import type {
|
||||
TopicDetailResponseData,
|
||||
TopicAsideOtherTagRequestData,
|
||||
TopicAsideMasterRequestData,
|
||||
TopicAsideResponseData,
|
||||
TopicUpvoteTopicRequestData,
|
||||
TopicUpvoteTopicResponseData,
|
||||
TopicLikeTopicRequestData,
|
||||
TopicLikeTopicResponseData,
|
||||
TopicDislikeTopicRequestData,
|
||||
TopicDislikeTopicResponseData,
|
||||
} from '@/api'
|
||||
|
||||
export const useTempTopicStore = defineStore({
|
||||
id: 'tempTopic',
|
||||
persist: false,
|
||||
actions: {
|
||||
// Other topics under the same tag on the left
|
||||
async getRelatedTopicsByTags(
|
||||
request: TopicAsideOtherTagRequestData
|
||||
): Promise<TopicAsideResponseData> {
|
||||
return await getRelatedTopicsByTagsApi(request)
|
||||
},
|
||||
|
||||
// Other topics by the master
|
||||
async getPopularTopicsByUserUid(
|
||||
request: TopicAsideMasterRequestData
|
||||
): Promise<TopicAsideResponseData> {
|
||||
return await getPopularTopicsByUserUidApi(request)
|
||||
},
|
||||
|
||||
// Get a single topic
|
||||
async getTopicByTid(tid: number): Promise<TopicDetailResponseData> {
|
||||
return await getTopicByTidApi(tid)
|
||||
},
|
||||
|
||||
// Upvote a topic
|
||||
async updateTopicUpvote(
|
||||
tid: number,
|
||||
toUid: number
|
||||
): Promise<TopicUpvoteTopicResponseData> {
|
||||
const requestData: TopicUpvoteTopicRequestData = {
|
||||
tid: tid,
|
||||
to_uid: toUid,
|
||||
}
|
||||
return await updateTopicUpvoteApi(requestData)
|
||||
},
|
||||
|
||||
// Like a topic
|
||||
async updateTopicLike(
|
||||
tid: number,
|
||||
toUid: number,
|
||||
isPush: boolean
|
||||
): Promise<TopicLikeTopicResponseData> {
|
||||
const requestData: TopicLikeTopicRequestData = {
|
||||
tid: tid,
|
||||
to_uid: toUid,
|
||||
isPush: isPush,
|
||||
}
|
||||
return await updateTopicLikeApi(requestData)
|
||||
},
|
||||
|
||||
// Dislike a topic
|
||||
async updateTopicDislike(
|
||||
tid: number,
|
||||
toUid: number,
|
||||
isPush: boolean
|
||||
): Promise<TopicDislikeTopicResponseData> {
|
||||
const requestData: TopicDislikeTopicRequestData = {
|
||||
tid: tid,
|
||||
to_uid: toUid,
|
||||
isPush: isPush,
|
||||
}
|
||||
return await updateTopicDislikeApi(requestData)
|
||||
},
|
||||
},
|
||||
})
|
73
src/store/types/topic.d.ts
vendored
73
src/store/types/topic.d.ts
vendored
|
@ -1,73 +0,0 @@
|
|||
// Reply cache
|
||||
interface ReplyDraft {
|
||||
/**
|
||||
* Editor related
|
||||
* @param {number} editorHeight - Editor height
|
||||
* @param {'' | 'essential' | 'minimal' | 'full'} mode - Editor toolbar mode
|
||||
* @param {'snow' | 'bubble'} theme - Editor theme
|
||||
*/
|
||||
editorHeight: number
|
||||
textCount: number
|
||||
// Only three modes are supported here
|
||||
mode: '' | 'essential' | 'minimal'
|
||||
theme: 'snow' | 'bubble'
|
||||
// Whether to display hot keywords
|
||||
isShowHotKeywords: boolean
|
||||
|
||||
// Current topic ID
|
||||
tid: number
|
||||
// Who to reply to, used for reply panel display
|
||||
toUserName: string
|
||||
to_uid: number
|
||||
content: string
|
||||
tags: string[]
|
||||
// Floor number of the person being replied to, used for navigation
|
||||
to_floor: number
|
||||
|
||||
// Whether to save the reply
|
||||
isSaveReply: boolean
|
||||
}
|
||||
|
||||
// Request to get replies
|
||||
interface ReplyRequest {
|
||||
page: number
|
||||
limit: number
|
||||
sortField: string
|
||||
sortOrder: 'asc' | 'desc'
|
||||
}
|
||||
|
||||
// Update comment cache
|
||||
interface ReplyRewrite {
|
||||
tid: number
|
||||
rid: number
|
||||
content: string
|
||||
tags: string[]
|
||||
|
||||
// Whether the reply is being rewritten
|
||||
isReplyRewriting: boolean
|
||||
}
|
||||
|
||||
// Topic page store
|
||||
export interface TopicStore {
|
||||
// Whether it's being edited
|
||||
isEdit: boolean
|
||||
// Whether to show advanced editing mode
|
||||
isShowAdvance: boolean
|
||||
// Whether to activate the left interaction panel
|
||||
isActiveAside: boolean
|
||||
// Whether to scroll to the top
|
||||
isScrollToTop: boolean
|
||||
// Whether to continue loading after it's done
|
||||
isLoading: boolean
|
||||
// Reply ID to scroll to
|
||||
scrollToReplyId: number
|
||||
|
||||
// Width of the reply panel
|
||||
replyPanelWidth: number
|
||||
// Reply cache
|
||||
replyDraft: ReplyDraft
|
||||
// Request format for getting replies
|
||||
replyRequest: ReplyRequest
|
||||
// Update comment cache
|
||||
replyRewrite: ReplyRewrite
|
||||
}
|
10
src/store/types/topic/comment.d.ts
vendored
Normal file
10
src/store/types/topic/comment.d.ts
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
export interface CommentDraft {
|
||||
tid: number
|
||||
rid: number
|
||||
toUid: number
|
||||
toUsername: string
|
||||
content: string
|
||||
|
||||
// Which reply's comment panel to display
|
||||
isShowCommentPanelRid: number
|
||||
}
|
61
src/store/types/topic/reply.d.ts
vendored
Normal file
61
src/store/types/topic/reply.d.ts
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
import type { TopicReply } from '@/api'
|
||||
|
||||
interface ReplyDraft {
|
||||
tid: number
|
||||
toUserName: string
|
||||
toUid: number
|
||||
content: string
|
||||
tags: string[]
|
||||
toFloor: number
|
||||
}
|
||||
|
||||
interface ReplyRequest {
|
||||
page: number
|
||||
limit: number
|
||||
sortField: string
|
||||
sortOrder: 'asc' | 'desc'
|
||||
}
|
||||
|
||||
interface ReplyRewrite {
|
||||
tid: number
|
||||
rid: number
|
||||
content: string
|
||||
tags: string[]
|
||||
edited: number
|
||||
}
|
||||
|
||||
interface ReplyRewriteTemp {
|
||||
rid: number
|
||||
content: string
|
||||
tags: string[]
|
||||
edited: number
|
||||
}
|
||||
|
||||
export interface ReplyStoreTemp {
|
||||
textCount: number
|
||||
// Whether it's being edited
|
||||
isEdit: boolean
|
||||
// Whether to scroll to the top
|
||||
isScrollToTop: boolean
|
||||
// Whether to continue loading after it's done
|
||||
isLoading: boolean
|
||||
// Reply ID to scroll to
|
||||
scrollToReplyId: number
|
||||
|
||||
replyRequest: ReplyRequest
|
||||
tempReply: TopicReply
|
||||
tempReplyRewrite: ReplyRewriteTemp
|
||||
}
|
||||
|
||||
export interface ReplyStorePersist {
|
||||
replyPanelWidth: number
|
||||
|
||||
isSaveReply: boolean
|
||||
isShowHotKeywords: boolean
|
||||
editorHeight: number
|
||||
|
||||
isReplyRewriting: boolean
|
||||
|
||||
replyDraft: ReplyDraft
|
||||
replyRewrite: ReplyRewrite
|
||||
}
|
8
src/store/types/topic/topic.d.ts
vendored
Normal file
8
src/store/types/topic/topic.d.ts
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
import type { TopicReply } from '@/api'
|
||||
|
||||
export interface TopicStorePersist {
|
||||
// Whether to show advanced editing mode
|
||||
isShowAdvance: boolean
|
||||
// Whether to activate the left interaction panel
|
||||
isActiveAside: boolean
|
||||
}
|
|
@ -113,7 +113,7 @@ onBeforeUnmount(() => {
|
|||
</TransitionGroup>
|
||||
|
||||
<!-- Skeleton -->
|
||||
<HomeTopicSkeleton v-if="!topics.length" />
|
||||
<HomeTopicSkeleton :count="7" v-if="!topics.length" />
|
||||
|
||||
<HomeTopicSkeleton v-if="isLoading && topics.length >= 16" />
|
||||
</div>
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, computed, watch, onBeforeMount, onMounted } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
// Global message component (top)
|
||||
import Message from '@/components/alert/Message'
|
||||
// Import the store for editing topics
|
||||
|
||||
import { useKUNGalgameEditStore } from '@/store/modules/edit'
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
import { usePersistKUNGalgameReplyStore } from '@/store/modules/topic/reply'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
// Current page's route
|
||||
|
@ -14,17 +13,26 @@ const route = useRoute()
|
|||
const routeName = computed(() => route.name as string)
|
||||
|
||||
// Store for the topic edit interface
|
||||
const { isShowHotKeywords, tags, isSaveTopic, topicRewrite } = storeToRefs(
|
||||
useKUNGalgameEditStore()
|
||||
)
|
||||
const {
|
||||
isShowHotKeywords: isShowEditHotKeywords,
|
||||
tags,
|
||||
isSaveTopic,
|
||||
topicRewrite,
|
||||
} = storeToRefs(useKUNGalgameEditStore())
|
||||
// Store for the topic interface, used for replies
|
||||
const { replyDraft, replyRewrite } = storeToRefs(useKUNGalgameTopicStore())
|
||||
const {
|
||||
isShowHotKeywords: isShowReplyHotKeywords,
|
||||
isSaveReply,
|
||||
isReplyRewriting,
|
||||
replyDraft,
|
||||
replyRewrite,
|
||||
} = storeToRefs(usePersistKUNGalgameReplyStore())
|
||||
|
||||
// Compute whether to show hot tags based on route name
|
||||
const isShowKeywords = computed(() =>
|
||||
routeName.value === 'Edit'
|
||||
? isShowHotKeywords.value
|
||||
: replyDraft.value.isShowHotKeywords
|
||||
? isShowEditHotKeywords.value
|
||||
: isShowReplyHotKeywords.value
|
||||
)
|
||||
|
||||
// Backend response for hot tags
|
||||
|
@ -58,14 +66,14 @@ onBeforeMount(() => {
|
|||
* The editor is in the reply interface
|
||||
*/
|
||||
// Load reply data before mounting if it's not saved (and the current page must be in topic mode)
|
||||
if (replyDraft.value.isSaveReply && routeName.value === 'Topic') {
|
||||
if (isSaveReply.value && routeName.value === 'Topic') {
|
||||
selectedTags.value = replyDraft.value.tags
|
||||
}
|
||||
/**
|
||||
* The editor is in the reply rewriting interface
|
||||
*/
|
||||
// Load tags for rewriting a reply before mounting (if the current page is in topic mode)
|
||||
if (replyRewrite.value.isReplyRewriting && routeName.value === 'Topic') {
|
||||
if (isReplyRewriting.value && routeName.value === 'Topic') {
|
||||
selectedTags.value = replyRewrite.value.tags
|
||||
}
|
||||
})
|
||||
|
@ -161,21 +169,27 @@ const getTags = async () => {
|
|||
}
|
||||
|
||||
// Watch for changes in isShowKeywords and fetch tags when it's true, adapting to page responsiveness
|
||||
watch(isShowKeywords, async () => {
|
||||
if (isShowHotKeywords.value === true) {
|
||||
hotTags.value = await getTags()
|
||||
watch(
|
||||
() => isShowKeywords.value,
|
||||
async () => {
|
||||
if (
|
||||
(routeName.value === 'Edit' && isShowEditHotKeywords.value) ||
|
||||
(routeName.value === 'Topic' && isShowReplyHotKeywords.value)
|
||||
) {
|
||||
hotTags.value = await getTags()
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
// Fetch hot tags when the component is mounted
|
||||
onMounted(async () => {
|
||||
// Trigger the interface if hot tags need to be loaded in edit mode
|
||||
const isLoadEditHotTags =
|
||||
routeName.value === 'Edit' && isShowHotKeywords.value
|
||||
routeName.value === 'Edit' && isShowEditHotKeywords.value
|
||||
|
||||
// Trigger the interface if hot tags need to be loaded in topic mode
|
||||
const isLoadTopicHotTags =
|
||||
routeName.value === 'Topic' && replyDraft.value.isShowHotKeywords
|
||||
routeName.value === 'Topic' && isShowReplyHotKeywords.value
|
||||
|
||||
// Fetch only when needed
|
||||
if (isLoadEditHotTags || isLoadTopicHotTags) {
|
||||
|
|
|
@ -24,35 +24,33 @@ const ReplyPanel = defineAsyncComponent(
|
|||
() => import('./components/reply/ReplyPanel.vue')
|
||||
)
|
||||
|
||||
// Import the settings panel store
|
||||
import { useKUNGalgameSettingsStore } from '@/store/modules/settings'
|
||||
// Import the topic page store
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
// Temporary data for reply publication responses
|
||||
import { useTempReplyStore } from '@/store/temp/reply'
|
||||
// Temporary data for reply editing responses
|
||||
import { useTempReplyRewriteStore } from '@/store/temp/replyRewrite'
|
||||
// Use non-persistent comment store
|
||||
import { useTempCommentStore } from '@/store/temp/comment'
|
||||
import { usePersistKUNGalgameTopicStore } from '@/store/modules/topic/topic'
|
||||
import { usePersistKUNGalgameReplyStore } from '@/store/modules/topic/reply'
|
||||
|
||||
import { useTempTopicStore } from '@/store/temp/topic/topic'
|
||||
import { useTempReplyStore } from '@/store/temp/topic/reply'
|
||||
import { useTempCommentStore } from '@/store/temp/topic/comment'
|
||||
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
// Current route
|
||||
const route = useRoute()
|
||||
|
||||
const { showKUNGalgamePageWidth } = storeToRefs(useKUNGalgameSettingsStore())
|
||||
const { isShowAdvance } = storeToRefs(usePersistKUNGalgameTopicStore())
|
||||
const { isReplyRewriting } = storeToRefs(usePersistKUNGalgameReplyStore())
|
||||
|
||||
const {
|
||||
isShowAdvance,
|
||||
isEdit,
|
||||
replyRequest,
|
||||
replyRewrite,
|
||||
isScrollToTop,
|
||||
isLoading,
|
||||
scrollToReplyId,
|
||||
} = storeToRefs(useKUNGalgameTopicStore())
|
||||
const { tempReply } = storeToRefs(useTempReplyStore())
|
||||
const { rid, replyContent, tags, edited } = storeToRefs(
|
||||
useTempReplyRewriteStore()
|
||||
)
|
||||
tempReply,
|
||||
tempReplyRewrite,
|
||||
} = storeToRefs(useTempReplyStore())
|
||||
|
||||
const { isShowCommentPanelRid } = storeToRefs(useTempCommentStore())
|
||||
|
||||
const tid = computed(() => {
|
||||
|
@ -72,12 +70,12 @@ const contentScrollHeight = ref(0)
|
|||
|
||||
// Function to get topic details
|
||||
const getTopic = async (): Promise<TopicDetail> => {
|
||||
return (await useKUNGalgameTopicStore().getTopicByTid(tid.value)).data
|
||||
return (await useTempTopicStore().getTopicByTid(tid.value)).data
|
||||
}
|
||||
|
||||
// Function to get replies
|
||||
const getReplies = async (): Promise<TopicReply[]> => {
|
||||
return (await useKUNGalgameTopicStore().getReplies(tid.value)).data
|
||||
return (await useTempReplyStore().getReplies(tid.value)).data
|
||||
}
|
||||
|
||||
// Call getReplies to get reply data (watch is great!), get replies when sorting is clicked
|
||||
|
@ -109,15 +107,17 @@ watch(
|
|||
|
||||
// User edits a reply
|
||||
watch(
|
||||
() => edited.value,
|
||||
() => tempReplyRewrite.value.edited,
|
||||
() => {
|
||||
// Find the reply data in repliesData
|
||||
const reply = repliesData.value.find((reply) => reply.rid === rid.value)
|
||||
const reply = repliesData.value.find(
|
||||
(reply) => reply.rid === tempReplyRewrite.value.rid
|
||||
)
|
||||
// Update the necessary data
|
||||
if (reply) {
|
||||
reply.content = replyContent.value
|
||||
reply.tags = tags.value
|
||||
reply.edited = edited.value
|
||||
reply.content = tempReplyRewrite.value.content
|
||||
reply.tags = tempReplyRewrite.value.tags
|
||||
reply.edited = tempReplyRewrite.value.edited
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@ -209,9 +209,6 @@ const isScrollAtBottom = () => {
|
|||
|
||||
// Reset the panel status when the component is mounted
|
||||
onMounted(async () => {
|
||||
// Reset the page number, loading status, and other page states before mounting
|
||||
useKUNGalgameTopicStore().resetPageStatus()
|
||||
|
||||
// Get data for the single topic
|
||||
topicData.value = await getTopic()
|
||||
|
||||
|
@ -240,7 +237,7 @@ const resetPanelStatus = () => {
|
|||
// Close the reply panel when leaving the page, confirm leaving if there are unsaved reply edits
|
||||
onBeforeRouteLeave(async (to, from, next) => {
|
||||
// If a reply is being edited
|
||||
if (replyRewrite.value.isReplyRewriting) {
|
||||
if (isReplyRewriting.value) {
|
||||
// Get the user's choice
|
||||
const res = await useKUNGalgameMessageStore().alert(
|
||||
'AlertInfo.edit.leave',
|
||||
|
@ -275,7 +272,11 @@ onBeforeMount(() => {
|
|||
<!-- Container for visible content below -->
|
||||
<div class="content-container">
|
||||
<!-- Sidebar -->
|
||||
<Aside v-if="topicData?.tags" :tags="topicData.tags" />
|
||||
<Aside
|
||||
v-if="topicData?.tags && topicData.user"
|
||||
:tags="topicData.tags"
|
||||
:uid="topicData.user.uid"
|
||||
/>
|
||||
|
||||
<!-- Content area -->
|
||||
<div class="content" ref="content" @scroll="handelScroll">
|
||||
|
@ -325,7 +326,6 @@ onBeforeMount(() => {
|
|||
/* Add background border and rounded corners */
|
||||
border-radius: 5px;
|
||||
padding: 5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Right content area */
|
||||
|
@ -336,7 +336,6 @@ onBeforeMount(() => {
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: scroll;
|
||||
overflow-x: visible;
|
||||
}
|
||||
|
||||
.title-scroll {
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
<script setup lang="ts">
|
||||
import { Icon } from '@iconify/vue'
|
||||
import { ref, watch } from 'vue'
|
||||
import { ref, toRefs, watch } from 'vue'
|
||||
import AsideActive from './components/AsideActive.vue'
|
||||
import AsideBase from './components/AsideBase.vue'
|
||||
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
import { usePersistKUNGalgameTopicStore } from '@/store/modules/topic/topic'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
tags: string[]
|
||||
uid: number
|
||||
}>()
|
||||
|
||||
const { isActiveAside } = storeToRefs(useKUNGalgameTopicStore())
|
||||
const { tags, uid } = toRefs(props)
|
||||
const { isActiveAside } = storeToRefs(usePersistKUNGalgameTopicStore())
|
||||
const asideWidth = ref('250px')
|
||||
const handleFold = () => {
|
||||
isActiveAside.value = !isActiveAside.value
|
||||
|
@ -44,7 +46,7 @@ watch(
|
|||
</div>
|
||||
|
||||
<div class="item-active" v-if="isActiveAside">
|
||||
<AsideActive :tags="$props.tags" />
|
||||
<AsideActive :tags="tags" :uid="uid" />
|
||||
</div>
|
||||
|
||||
<div class="item" v-if="!isActiveAside">
|
||||
|
|
|
@ -3,10 +3,14 @@ import TopicAsideNav from './TopicAsideNav.vue'
|
|||
import TopicOtherTag from './TopicOtherTag.vue'
|
||||
import TopicMaster from './TopicMaster.vue'
|
||||
import KUNGalgameFooter from '@/components/KUNGalgameFooter.vue'
|
||||
import { toRefs } from 'vue'
|
||||
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
tags: string[]
|
||||
uid: number
|
||||
}>()
|
||||
|
||||
const { tags, uid } = toRefs(props)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -16,8 +20,8 @@ defineProps<{
|
|||
>
|
||||
<div class="aside">
|
||||
<TopicAsideNav />
|
||||
<TopicOtherTag style="margin-bottom: 17px" :tags="$props.tags" />
|
||||
<TopicMaster />
|
||||
<TopicOtherTag style="margin-bottom: 17px" :tags="tags" />
|
||||
<TopicMaster :uid="uid" />
|
||||
<KUNGalgameFooter />
|
||||
</div>
|
||||
</Transition>
|
||||
|
|
|
@ -2,34 +2,23 @@
|
|||
import { Icon } from '@iconify/vue'
|
||||
import { asideNavItem } from './asideNavItem'
|
||||
|
||||
// Import the topic store
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
import { useTempReplyStore } from '@/store/temp/topic/reply'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
const { isScrollToTop, replyRequest } = storeToRefs(useKUNGalgameTopicStore())
|
||||
const { isScrollToTop, replyRequest } = storeToRefs(useTempReplyStore())
|
||||
|
||||
// Sort the replies
|
||||
const handleSortReply = (sortField: string) => {
|
||||
// Reset page-related status (e.g., page number, loading status) to prevent errors
|
||||
useKUNGalgameTopicStore().resetPageStatus()
|
||||
replyRequest.value.sortField = sortField
|
||||
}
|
||||
|
||||
// Sort in ascending order
|
||||
const orderAscending = () => {
|
||||
// Reset page-related status to prevent errors
|
||||
useKUNGalgameTopicStore().resetPageStatus()
|
||||
replyRequest.value.sortOrder = 'asc'
|
||||
}
|
||||
|
||||
// Sort in descending order
|
||||
const orderDescending = () => {
|
||||
// Reset page-related status to prevent errors
|
||||
useKUNGalgameTopicStore().resetPageStatus()
|
||||
replyRequest.value.sortOrder = 'desc'
|
||||
}
|
||||
|
||||
// Scroll back to the top
|
||||
const handleBackToTop = () => {
|
||||
isScrollToTop.value = true
|
||||
}
|
||||
|
|
|
@ -5,27 +5,20 @@
|
|||
import { Icon } from '@iconify/vue'
|
||||
import { asideNavItem } from './asideNavItem'
|
||||
|
||||
// Import the topic store
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
import { useTempReplyStore } from '@/store/temp/topic/reply'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
const { isScrollToTop, replyRequest } = storeToRefs(useKUNGalgameTopicStore())
|
||||
const { isScrollToTop, replyRequest } = storeToRefs(useTempReplyStore())
|
||||
|
||||
const handleSortReply = (sortField: string) => {
|
||||
// Reset page-related status (e.g., page number, loading status) to prevent errors
|
||||
useKUNGalgameTopicStore().resetPageStatus()
|
||||
replyRequest.value.sortField = sortField
|
||||
}
|
||||
|
||||
const orderAscending = () => {
|
||||
// Reset page-related status to prevent errors
|
||||
useKUNGalgameTopicStore().resetPageStatus()
|
||||
replyRequest.value.sortOrder = 'asc'
|
||||
}
|
||||
|
||||
const orderDescending = () => {
|
||||
// Reset page-related status to prevent errors
|
||||
useKUNGalgameTopicStore().resetPageStatus()
|
||||
replyRequest.value.sortOrder = 'desc'
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,11 @@ import { RouterLink, useRoute } from 'vue-router'
|
|||
import TopicAsideSkeleton from '@/components/skeleton/topic/TopicAsideSkeleton.vue'
|
||||
|
||||
import { TopicAside } from '@/api/index'
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
import { useTempTopicStore } from '@/store/temp/topic/topic'
|
||||
|
||||
const props = defineProps<{
|
||||
uid: number
|
||||
}>()
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
|
@ -18,7 +22,8 @@ const isEmpty = ref(false)
|
|||
|
||||
const fetchTopicData = async () => {
|
||||
return (
|
||||
await useKUNGalgameTopicStore().getPopularTopicsByUserUid({
|
||||
await useTempTopicStore().getPopularTopicsByUserUid({
|
||||
uid: props.uid,
|
||||
tid: tid,
|
||||
})
|
||||
).data
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<script setup lang="ts">
|
||||
import { onMounted, ref, toRaw } from 'vue'
|
||||
import TopicAsideSkeleton from '@/components/skeleton/topic/TopicAsideSkeleton.vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { TopicAside } from '@/api/index'
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
|
||||
import TopicAsideSkeleton from '@/components/skeleton/topic/TopicAsideSkeleton.vue'
|
||||
|
||||
import { useTempTopicStore } from '@/store/temp/topic/topic'
|
||||
import type { TopicAside } from '@/api/index'
|
||||
|
||||
const props = defineProps<{
|
||||
tags: string[]
|
||||
|
@ -18,7 +20,7 @@ const isEmpty = ref(false)
|
|||
|
||||
const fetchTopicData = async () => {
|
||||
return (
|
||||
await useKUNGalgameTopicStore().getRelatedTopicsByTags({
|
||||
await useTempTopicStore().getRelatedTopicsByTags({
|
||||
tags: tags,
|
||||
tid: tid,
|
||||
})
|
||||
|
|
|
@ -3,7 +3,7 @@ import { MilkdownProvider } from '@milkdown/vue'
|
|||
import { ProsemirrorAdapterProvider } from '@prosemirror-adapter/vue'
|
||||
import ReadOnlyMilkdown from '@/components/milkdown/ReadOnlyMilkdown.vue'
|
||||
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
content: string
|
||||
}>()
|
||||
</script>
|
||||
|
@ -12,10 +12,7 @@ defineProps<{
|
|||
<div class="kungalgame-topic-content">
|
||||
<MilkdownProvider>
|
||||
<ProsemirrorAdapterProvider>
|
||||
<ReadOnlyMilkdown
|
||||
:is-readonly="true"
|
||||
:value-markdown="$props.content"
|
||||
/>
|
||||
<ReadOnlyMilkdown :is-readonly="true" :value-markdown="props.content" />
|
||||
</ProsemirrorAdapterProvider>
|
||||
</MilkdownProvider>
|
||||
</div>
|
||||
|
@ -25,8 +22,6 @@ defineProps<{
|
|||
/* Right side content area for the topic */
|
||||
.kungalgame-topic-content {
|
||||
min-height: 200px;
|
||||
/** 100 + 20 + 20 + 1 = 141px */
|
||||
width: calc(100% - 141px);
|
||||
font-size: 15px;
|
||||
padding: 17px;
|
||||
color: var(--kungalgame-font-color-3);
|
||||
|
|
|
@ -39,7 +39,7 @@ const {
|
|||
user,
|
||||
// replies,
|
||||
status,
|
||||
share,
|
||||
// share,
|
||||
category,
|
||||
// popularity,
|
||||
upvote_time,
|
||||
|
|
|
@ -6,8 +6,7 @@ import { debounce } from '@/utils/debounce'
|
|||
import { TopicComment } from '@/api/index'
|
||||
|
||||
import { useKUNGalgameUserStore } from '@/store/modules/kungalgamer'
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
import { useTempCommentStore } from '@/store/temp/comment'
|
||||
import { useTempCommentStore } from '@/store/temp/topic/comment'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
const { name } = storeToRefs(useKUNGalgameUserStore())
|
||||
|
@ -60,7 +59,7 @@ const handlePublishComment = async () => {
|
|||
if (isValidComment()) {
|
||||
// Get the new comment
|
||||
const newComment = (
|
||||
await useKUNGalgameTopicStore().postNewComment(
|
||||
await useTempCommentStore().postNewComment(
|
||||
tid.value,
|
||||
rid.value,
|
||||
toUid.value,
|
||||
|
|
|
@ -14,9 +14,8 @@ import Dislike from './Dislike.vue'
|
|||
|
||||
import { TopicComment } from '@/api/index'
|
||||
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
import { useKUNGalgameUserStore } from '@/store/modules/kungalgamer'
|
||||
import { useTempCommentStore } from '@/store/temp/comment'
|
||||
import { useTempCommentStore } from '@/store/temp/topic/comment'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
const { tid, rid, toUid, toUsername, isShowCommentPanelRid } = storeToRefs(
|
||||
|
@ -35,10 +34,8 @@ const props = defineProps<{
|
|||
const tidRef = ref(props.tid)
|
||||
const ridRef = ref(props.rid)
|
||||
const toUser = ref(props.toUser)
|
||||
// Current user uid
|
||||
const currentUserUid = useKUNGalgameUserStore().uid
|
||||
|
||||
// Reactivity
|
||||
watch(
|
||||
() => props.rid,
|
||||
async () => {
|
||||
|
@ -48,14 +45,12 @@ watch(
|
|||
}
|
||||
)
|
||||
|
||||
// Comments data
|
||||
const commentsData = ref<TopicComment[]>([])
|
||||
|
||||
const getComments = async (topicId: number, replyId: number) => {
|
||||
return (await useKUNGalgameTopicStore().getComments(topicId, replyId)).data
|
||||
return (await useTempCommentStore().getComments(topicId, replyId)).data
|
||||
}
|
||||
|
||||
// Get the newly published comment and push it to the existing data, no need to retrieve it again
|
||||
const getCommentEmits = (newComment: TopicComment) => {
|
||||
commentsData.value?.push(newComment)
|
||||
}
|
||||
|
@ -64,7 +59,6 @@ onMounted(async () => {
|
|||
commentsData.value = await getComments(tidRef.value, ridRef.value)
|
||||
})
|
||||
|
||||
// Click to reply
|
||||
const handleClickComment = (
|
||||
topicId: number,
|
||||
replyId: number,
|
||||
|
@ -75,7 +69,7 @@ const handleClickComment = (
|
|||
rid.value = replyId
|
||||
toUid.value = uid
|
||||
toUsername.value = name
|
||||
// Open the reply panel
|
||||
|
||||
isShowCommentPanelRid.value = ridRef.value
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Icon } from '@iconify/vue'
|
|||
import Message from '@/components/alert/Message'
|
||||
import { throttle } from '@/utils/throttle'
|
||||
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
import { useTempCommentStore } from '@/store/temp/topic/comment'
|
||||
|
||||
const props = defineProps<{
|
||||
tid: number
|
||||
|
@ -18,7 +18,6 @@ const props = defineProps<{
|
|||
const isDisliked = ref(props.dislikes.includes(props.uid))
|
||||
const dislikesCount = ref(props.dislikes.length)
|
||||
|
||||
// Reactivity
|
||||
watch(
|
||||
() => props.dislikes,
|
||||
(newLikes) => {
|
||||
|
@ -27,7 +26,6 @@ watch(
|
|||
}
|
||||
)
|
||||
|
||||
// Throttle callback function
|
||||
const throttleCallback = () => {
|
||||
Message(
|
||||
'You can only perform one operation within 1007 milliseconds',
|
||||
|
@ -37,24 +35,18 @@ const throttleCallback = () => {
|
|||
}
|
||||
|
||||
const dislikeComment = async () => {
|
||||
// Already disliked
|
||||
if (isDisliked.value) {
|
||||
Message(`You've already disliked it`, '您已经点过踩了', 'warn')
|
||||
return
|
||||
}
|
||||
|
||||
// The current user cannot dislike themselves
|
||||
if (props.uid === props.toUid) {
|
||||
Message('You cannot dislike yourself', '您不可以给自己点踩', 'warn')
|
||||
return
|
||||
}
|
||||
|
||||
const { tid, cid, toUid } = props
|
||||
const res = await useKUNGalgameTopicStore().updateCommentDislike(
|
||||
tid,
|
||||
cid,
|
||||
toUid
|
||||
)
|
||||
const res = await useTempCommentStore().updateCommentDislike(tid, cid, toUid)
|
||||
|
||||
if (res.code === 200) {
|
||||
dislikesCount.value++
|
||||
|
@ -65,7 +57,6 @@ const dislikeComment = async () => {
|
|||
}
|
||||
}
|
||||
|
||||
// Throttle function, can only trigger dislikes every 1007 milliseconds
|
||||
const handleClickDislikeThrottled = throttle(
|
||||
dislikeComment,
|
||||
1007,
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Icon } from '@iconify/vue'
|
|||
import Message from '@/components/alert/Message'
|
||||
import { throttle } from '@/utils/throttle'
|
||||
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
import { useTempCommentStore } from '@/store/temp/topic/comment'
|
||||
|
||||
const props = defineProps<{
|
||||
tid: number
|
||||
|
@ -18,17 +18,14 @@ const props = defineProps<{
|
|||
const isLiked = ref(props.likes.includes(props.uid))
|
||||
const likesCount = ref(props.likes.length)
|
||||
|
||||
// Reactivity
|
||||
watch(
|
||||
() => props.likes,
|
||||
(newLikes) => {
|
||||
// Update isLiked and likesCount
|
||||
isLiked.value = newLikes.includes(props.uid)
|
||||
likesCount.value = newLikes.length
|
||||
}
|
||||
)
|
||||
|
||||
// Throttle callback function
|
||||
const throttleCallback = () => {
|
||||
Message(
|
||||
'You can only perform one operation within 1007 milliseconds',
|
||||
|
@ -38,20 +35,18 @@ const throttleCallback = () => {
|
|||
}
|
||||
|
||||
const likeComment = async () => {
|
||||
/// Already liked
|
||||
if (isLiked.value) {
|
||||
Message(`You've already liked it`, '您已经点过赞了', 'warn')
|
||||
return
|
||||
}
|
||||
|
||||
// The current user cannot like themselves
|
||||
if (props.uid === props.toUid) {
|
||||
Message('You cannot like yourself', '您不可以给自己点赞', 'warn')
|
||||
return
|
||||
}
|
||||
|
||||
const { tid, cid, toUid } = props
|
||||
const res = await useKUNGalgameTopicStore().updateCommentLike(tid, cid, toUid)
|
||||
const res = await useTempCommentStore().updateCommentLike(tid, cid, toUid)
|
||||
|
||||
if (res.code === 200) {
|
||||
likesCount.value++
|
||||
|
@ -62,7 +57,6 @@ const likeComment = async () => {
|
|||
}
|
||||
}
|
||||
|
||||
// Throttle function, can only trigger likes every 1007 milliseconds
|
||||
const handleClickLikeThrottled = throttle(likeComment, 1007, throttleCallback)
|
||||
|
||||
const handleClickLike = () => {
|
||||
|
|
|
@ -5,7 +5,8 @@ import { Icon } from '@iconify/vue'
|
|||
import Message from '@/components/alert/Message'
|
||||
import { throttle } from '@/utils/throttle'
|
||||
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
import { useTempTopicStore } from '@/store/temp/topic/topic'
|
||||
import { useTempReplyStore } from '@/store/temp/topic/reply'
|
||||
|
||||
const props = defineProps<{
|
||||
uid: number
|
||||
|
@ -18,17 +19,14 @@ const props = defineProps<{
|
|||
const isDisliked = ref(props.dislikes.includes(props.uid))
|
||||
const dislikesCount = ref(props.dislikes.length)
|
||||
|
||||
// Reactive
|
||||
watch(
|
||||
() => props.dislikes,
|
||||
(newLikes) => {
|
||||
// Update isDisliked and dislikesCount
|
||||
isDisliked.value = newLikes.includes(props.uid)
|
||||
dislikesCount.value = newLikes.length
|
||||
}
|
||||
)
|
||||
|
||||
// Throttle callback
|
||||
const throttleCallback = () => {
|
||||
Message(
|
||||
'You can only perform one operation within 1007 milliseconds',
|
||||
|
@ -37,43 +35,29 @@ const throttleCallback = () => {
|
|||
)
|
||||
}
|
||||
|
||||
// Dislike operation
|
||||
const dislikeOperation = async (
|
||||
tid: number,
|
||||
rid: number,
|
||||
toUid: number,
|
||||
isPush: boolean
|
||||
) => {
|
||||
// If rid is zero, it means the dislike is for the main topic
|
||||
const isMasterTopic = rid === 0
|
||||
if (isMasterTopic) {
|
||||
return await useKUNGalgameTopicStore().updateTopicDislike(
|
||||
tid,
|
||||
toUid,
|
||||
isPush
|
||||
)
|
||||
return await useTempTopicStore().updateTopicDislike(tid, toUid, isPush)
|
||||
} else {
|
||||
return await useKUNGalgameTopicStore().updateReplyDislike(
|
||||
tid,
|
||||
toUid,
|
||||
rid,
|
||||
isPush
|
||||
)
|
||||
return await useTempReplyStore().updateReplyDislike(tid, toUid, rid, isPush)
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle dislike (dislike or cancel dislike)
|
||||
const toggleDislike = async () => {
|
||||
// Current user cannot dislike themselves
|
||||
if (props.uid === props.toUid) {
|
||||
Message('You cannot dislike yourself', '您不可以给自己点踩', 'warn')
|
||||
return
|
||||
}
|
||||
|
||||
const { tid, rid, toUid } = props
|
||||
const isPush = !isDisliked.value // Invert the value to dislike or cancel dislike
|
||||
const isPush = !isDisliked.value
|
||||
|
||||
// Perform dislike or cancel dislike operation
|
||||
const res = await dislikeOperation(tid, rid, toUid, isPush)
|
||||
|
||||
if (res.code === 200) {
|
||||
|
@ -94,21 +78,18 @@ const toggleDislike = async () => {
|
|||
}
|
||||
}
|
||||
|
||||
// Throttled function, can only trigger dislike once within 1007 milliseconds
|
||||
const handleClickDislikeThrottled = throttle(
|
||||
toggleDislike,
|
||||
1007,
|
||||
throttleCallback
|
||||
)
|
||||
|
||||
// Handle dislike
|
||||
const handleClickDislike = () => {
|
||||
handleClickDislikeThrottled()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Dislike -->
|
||||
<li>
|
||||
<span
|
||||
class="icon"
|
||||
|
|
|
@ -2,31 +2,22 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { Icon } from '@iconify/vue'
|
||||
// Upvote component
|
||||
|
||||
import Upvote from './Upvote.vue'
|
||||
// Like component
|
||||
import Like from './Like.vue'
|
||||
// Dislike component
|
||||
import Dislike from './Dislike.vue'
|
||||
// Reply component
|
||||
import Reply from './Reply.vue'
|
||||
// Rewrite component
|
||||
import Rewrite from './Rewrite.vue'
|
||||
|
||||
// Global message component (at the top)
|
||||
import Message from '@/components/alert/Message'
|
||||
|
||||
// Import the user's store
|
||||
import { useKUNGalgameUserStore } from '@/store/modules/kungalgamer'
|
||||
// Import the settings panel store
|
||||
import { useKUNGalgameSettingsStore } from '@/store/modules/settings'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
// Use the settings panel store
|
||||
const settingsStore = useKUNGalgameSettingsStore()
|
||||
const { showKUNGalgameLanguage } = storeToRefs(settingsStore)
|
||||
|
||||
// Receive props from the parent component
|
||||
const props = defineProps<{
|
||||
info: {
|
||||
tid: number
|
||||
|
@ -130,7 +121,7 @@ Link: https://www.kungal.com/topic/${props.info.tid}`
|
|||
:likes="info.likes"
|
||||
:to-uid="toUser.uid"
|
||||
v-tooltip="{
|
||||
message: { en: 'Likes', zh: '点赞数' },
|
||||
message: { en: 'Like', zh: '点赞' },
|
||||
position: 'bottom',
|
||||
}"
|
||||
/>
|
||||
|
@ -143,7 +134,7 @@ Link: https://www.kungal.com/topic/${props.info.tid}`
|
|||
:dislikes="info.dislikes"
|
||||
:to-uid="toUser.uid"
|
||||
v-tooltip="{
|
||||
message: { en: 'Dislikes', zh: '点踩数' },
|
||||
message: { en: 'Dislike', zh: '点踩' },
|
||||
position: 'bottom',
|
||||
}"
|
||||
/>
|
||||
|
@ -155,8 +146,8 @@ Link: https://www.kungal.com/topic/${props.info.tid}`
|
|||
<Reply
|
||||
:tid="info.tid"
|
||||
:to-user-name="toUser.name"
|
||||
:to_uid="toUser.uid"
|
||||
:to_floor="toFloor"
|
||||
:to-uid="toUser.uid"
|
||||
:to-floor="toFloor"
|
||||
/>
|
||||
|
||||
<!-- Share -->
|
||||
|
@ -164,7 +155,7 @@ Link: https://www.kungal.com/topic/${props.info.tid}`
|
|||
@click="handleClickShare"
|
||||
class="icon"
|
||||
v-tooltip="{
|
||||
message: { en: 'Share', zh: '分享话题' },
|
||||
message: { en: 'Share', zh: '分享' },
|
||||
position: 'bottom',
|
||||
}"
|
||||
>
|
||||
|
|
|
@ -2,15 +2,14 @@
|
|||
<script setup lang="ts">
|
||||
import { watch, ref } from 'vue'
|
||||
import { Icon } from '@iconify/vue'
|
||||
// Global message component (top)
|
||||
|
||||
import Message from '@/components/alert/Message'
|
||||
// Throttle function
|
||||
|
||||
import { throttle } from '@/utils/throttle'
|
||||
|
||||
// Import topic page store
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
import { useTempTopicStore } from '@/store/temp/topic/topic'
|
||||
import { useTempReplyStore } from '@/store/temp/topic/reply'
|
||||
|
||||
// Accept props from the parent component
|
||||
const props = defineProps<{
|
||||
uid: number
|
||||
tid: number
|
||||
|
@ -22,17 +21,14 @@ const props = defineProps<{
|
|||
const isLiked = ref(props.likes.includes(props.uid))
|
||||
const likesCount = ref(props.likes.length)
|
||||
|
||||
// Reactive
|
||||
watch(
|
||||
() => props.likes,
|
||||
(newLikes) => {
|
||||
// Update isLiked and likesCount
|
||||
isLiked.value = newLikes.includes(props.uid)
|
||||
likesCount.value = newLikes.length
|
||||
}
|
||||
)
|
||||
|
||||
// Throttle callback
|
||||
const throttleCallback = () => {
|
||||
Message(
|
||||
'You can only perform one operation within 1007 milliseconds',
|
||||
|
@ -41,39 +37,29 @@ const throttleCallback = () => {
|
|||
)
|
||||
}
|
||||
|
||||
// Like operation
|
||||
const likeOperation = async (
|
||||
tid: number,
|
||||
rid: number,
|
||||
toUid: number,
|
||||
isPush: boolean
|
||||
) => {
|
||||
// If rid is zero, it means liking the main topic
|
||||
const isMasterTopic = rid === 0
|
||||
if (isMasterTopic) {
|
||||
return await useKUNGalgameTopicStore().updateTopicLike(tid, toUid, isPush)
|
||||
return await useTempTopicStore().updateTopicLike(tid, toUid, isPush)
|
||||
} else {
|
||||
return await useKUNGalgameTopicStore().updateReplyLike(
|
||||
tid,
|
||||
toUid,
|
||||
rid,
|
||||
isPush
|
||||
)
|
||||
return await useTempReplyStore().updateReplyLike(tid, toUid, rid, isPush)
|
||||
}
|
||||
}
|
||||
|
||||
// Like / Unlike
|
||||
const toggleLike = async () => {
|
||||
// Current user cannot like themselves
|
||||
if (props.uid === props.toUid) {
|
||||
Message('You cannot like yourself', '您不可以给自己点赞', 'warn')
|
||||
return
|
||||
}
|
||||
|
||||
const { tid, rid, toUid } = props
|
||||
const isPush = !isLiked.value // Invert the value to like or unlike
|
||||
const isPush = !isLiked.value
|
||||
|
||||
// Perform like or unlike operation
|
||||
const res = await likeOperation(tid, rid, toUid, isPush)
|
||||
|
||||
if (res.code === 200) {
|
||||
|
@ -94,17 +80,14 @@ const toggleLike = async () => {
|
|||
}
|
||||
}
|
||||
|
||||
// Throttled function, can only trigger like once within 1007 milliseconds
|
||||
const handleClickLikeThrottled = throttle(toggleLike, 1007, throttleCallback)
|
||||
|
||||
// Like
|
||||
const handleClickLike = () => {
|
||||
handleClickLikeThrottled()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Like -->
|
||||
<li>
|
||||
<span
|
||||
class="icon"
|
||||
|
@ -136,7 +119,6 @@ li {
|
|||
}
|
||||
}
|
||||
|
||||
/* Icon font style */
|
||||
.icon {
|
||||
font-size: 24px;
|
||||
color: var(--kungalgame-font-color-2);
|
||||
|
|
|
@ -1,28 +1,25 @@
|
|||
<!-- Topic's bottom area, including upvote, reply, like, etc. -->
|
||||
<script setup lang="ts">
|
||||
// Import the topic page store
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
import { usePersistKUNGalgameReplyStore } from '@/store/modules/topic/reply'
|
||||
import { useTempReplyStore } from '@/store/temp/topic/reply'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
// Use the topic page store
|
||||
const { isEdit, replyDraft } = storeToRefs(useKUNGalgameTopicStore())
|
||||
const { isEdit } = storeToRefs(useTempReplyStore())
|
||||
const { replyDraft } = storeToRefs(usePersistKUNGalgameReplyStore())
|
||||
|
||||
// Accept props from the parent component
|
||||
const props = defineProps<{
|
||||
tid: number
|
||||
toUserName: string
|
||||
to_uid: number
|
||||
to_floor: number
|
||||
toUid: number
|
||||
toFloor: number
|
||||
}>()
|
||||
|
||||
// Click to open the reply panel
|
||||
const handleClickReply = () => {
|
||||
// Save necessary information for posting a reply
|
||||
replyDraft.value.tid = props.tid
|
||||
replyDraft.value.toUserName = props.toUserName
|
||||
replyDraft.value.to_uid = props.to_uid
|
||||
replyDraft.value.to_floor = props.to_floor
|
||||
// Open the reply panel
|
||||
replyDraft.value.toUid = props.toUid
|
||||
replyDraft.value.toFloor = props.toFloor
|
||||
|
||||
isEdit.value = true
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -3,20 +3,21 @@
|
|||
import { watch, ref } from 'vue'
|
||||
import { Icon } from '@iconify/vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
// Import the edit page store
|
||||
|
||||
import { useKUNGalgameEditStore } from '@/store/modules/edit'
|
||||
// Import the reply page store
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
import { usePersistKUNGalgameReplyStore } from '@/store/modules/topic/reply'
|
||||
|
||||
import { useTempReplyStore } from '@/store/temp/topic/reply'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
// Use the edit page store
|
||||
const { topicRewrite } = storeToRefs(useKUNGalgameEditStore())
|
||||
// Use the reply page store
|
||||
const { isEdit, replyRewrite } = storeToRefs(useKUNGalgameTopicStore())
|
||||
// Use the router
|
||||
const { isEdit } = storeToRefs(useTempReplyStore())
|
||||
const { isReplyRewriting, replyRewrite } = storeToRefs(
|
||||
usePersistKUNGalgameReplyStore()
|
||||
)
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
// Accept props from the parent component
|
||||
const props = defineProps<{
|
||||
tid: number
|
||||
rid: number
|
||||
|
@ -28,10 +29,8 @@ const props = defineProps<{
|
|||
toUid: number
|
||||
}>()
|
||||
|
||||
// Check if the user has permission to rewrite
|
||||
const isShowRewrite = ref(props.uid === props.toUid)
|
||||
|
||||
// Reactive
|
||||
watch(
|
||||
() => props.toUid,
|
||||
() => {
|
||||
|
@ -43,38 +42,29 @@ watch(
|
|||
}
|
||||
)
|
||||
|
||||
// Rewrite the topic
|
||||
const rewriteTopic = () => {
|
||||
// Save the data
|
||||
topicRewrite.value.tid = props.tid
|
||||
topicRewrite.value.title = props.title
|
||||
topicRewrite.value.content = props.content
|
||||
topicRewrite.value.tags = props.tags
|
||||
topicRewrite.value.category = props.category
|
||||
|
||||
// Set the "isTopicRewriting" state to true
|
||||
topicRewrite.value.isTopicRewriting = true
|
||||
|
||||
// Navigate to the edit page
|
||||
router.push({ name: 'Edit' })
|
||||
}
|
||||
|
||||
// Rewrite the reply
|
||||
const rewriteReply = () => {
|
||||
// Save the data
|
||||
replyRewrite.value.tid = props.tid
|
||||
replyRewrite.value.rid = props.rid
|
||||
replyRewrite.value.content = props.content
|
||||
replyRewrite.value.tags = props.tags
|
||||
|
||||
// Set the "isReplyRewriting" state to true
|
||||
replyRewrite.value.isReplyRewriting = true
|
||||
isReplyRewriting.value = true
|
||||
|
||||
// Open the reply panel
|
||||
isEdit.value = true
|
||||
}
|
||||
|
||||
// Edit
|
||||
const handleClickRewrite = () => {
|
||||
if (props.rid === 0) {
|
||||
rewriteTopic()
|
||||
|
|
|
@ -2,14 +2,13 @@
|
|||
<script setup lang="ts">
|
||||
import { watch, ref } from 'vue'
|
||||
import { Icon } from '@iconify/vue'
|
||||
// Global message component (bottom)
|
||||
import { useKUNGalgameMessageStore } from '@/store/modules/message'
|
||||
// Global message component (top)
|
||||
import Message from '@/components/alert/Message'
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
import { useKUNGalgameUserStore } from '@/store/modules/kungalgamer'
|
||||
|
||||
// Accept props from the parent component
|
||||
import { useKUNGalgameUserStore } from '@/store/modules/kungalgamer'
|
||||
import { useTempTopicStore } from '@/store/temp/topic/topic'
|
||||
import { useTempReplyStore } from '@/store/temp/topic/reply'
|
||||
|
||||
const props = defineProps<{
|
||||
uid: number
|
||||
tid: number
|
||||
|
@ -21,7 +20,6 @@ const props = defineProps<{
|
|||
const isUpvote = ref(props.upvotes.includes(props.uid))
|
||||
const upvoteCount = ref(props.upvotes.length)
|
||||
|
||||
// Reactive
|
||||
watch(
|
||||
() => props.upvotes,
|
||||
(newUpvote) => {
|
||||
|
@ -30,22 +28,17 @@ watch(
|
|||
}
|
||||
)
|
||||
|
||||
// Upvote topic
|
||||
const upvoteTopic = async () => {
|
||||
// Show a confirmation dialog
|
||||
const res = await useKUNGalgameMessageStore().alert(
|
||||
'AlertInfo.edit.upvoteTopic',
|
||||
true
|
||||
)
|
||||
|
||||
// Implement user's confirmation or cancellation logic here
|
||||
if (res) {
|
||||
const { tid, toUid } = props
|
||||
// Call the API to upvote the topic
|
||||
const res = await useKUNGalgameTopicStore().updateTopicUpvote(tid, toUid)
|
||||
const res = await useTempTopicStore().updateTopicUpvote(tid, toUid)
|
||||
|
||||
if (res.code === 200) {
|
||||
// Update the upvote count
|
||||
upvoteCount.value++
|
||||
isUpvote.value = true
|
||||
|
||||
|
@ -56,26 +49,17 @@ const upvoteTopic = async () => {
|
|||
}
|
||||
}
|
||||
|
||||
// Upvote reply
|
||||
const upvoteReply = async () => {
|
||||
// Show a confirmation dialog
|
||||
const res = await useKUNGalgameMessageStore().alert(
|
||||
'AlertInfo.edit.upvoteReply',
|
||||
true
|
||||
)
|
||||
|
||||
// Implement user's confirmation or cancellation logic here
|
||||
if (res) {
|
||||
const { tid, toUid, rid } = props
|
||||
// Call the API to upvote the reply
|
||||
const res = await useKUNGalgameTopicStore().updateReplyUpvote(
|
||||
tid,
|
||||
toUid,
|
||||
rid
|
||||
)
|
||||
const res = await useTempReplyStore().updateReplyUpvote(tid, toUid, rid)
|
||||
|
||||
if (res.code === 200) {
|
||||
// Update the upvote count
|
||||
upvoteCount.value++
|
||||
isUpvote.value = true
|
||||
|
||||
|
@ -86,15 +70,12 @@ const upvoteReply = async () => {
|
|||
}
|
||||
}
|
||||
|
||||
// Upvote
|
||||
const handleClickUpvote = async () => {
|
||||
// Users cannot upvote their own content
|
||||
if (props.uid === props.toUid) {
|
||||
Message('You cannot upvote your own topic', '您不可以推自己的话题', 'warn')
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the user has enough moemoepoints to use the upvote feature
|
||||
if (useKUNGalgameUserStore().moemoepoint < 1100) {
|
||||
Message(
|
||||
`Your moemoepoints are less than 1100, so you can't use the topic suggestion feature`,
|
||||
|
@ -104,7 +85,6 @@ const handleClickUpvote = async () => {
|
|||
return
|
||||
}
|
||||
|
||||
// If rid is 0, it's the topic's author
|
||||
if (props.rid === 0) {
|
||||
upvoteTopic()
|
||||
} else {
|
||||
|
|
|
@ -16,16 +16,15 @@ import Tags from '../Tags.vue'
|
|||
import Rewrite from '../Rewrite.vue'
|
||||
import KUNGalgamerInfo from '../KUNGalgamerInfo.vue'
|
||||
|
||||
// Import the function to calculate the time difference
|
||||
import { hourDiff } from '@/utils/time'
|
||||
|
||||
import { TopicReply } from '@/api/index'
|
||||
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
import { useTempCommentStore } from '@/store/temp/comment'
|
||||
import { useTempReplyStore } from '@/store/temp/topic/reply'
|
||||
import { useTempCommentStore } from '@/store/temp/topic/comment'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
const { scrollToReplyId } = storeToRefs(useKUNGalgameTopicStore())
|
||||
const { scrollToReplyId } = storeToRefs(useTempReplyStore())
|
||||
|
||||
const { tid, rid, toUid, toUsername, isShowCommentPanelRid } = storeToRefs(
|
||||
useTempCommentStore()
|
||||
|
@ -39,7 +38,6 @@ const props = defineProps<{
|
|||
const replies = computed(() => props.repliesData)
|
||||
const isCommentPanelOpen = ref(false)
|
||||
|
||||
// Function to toggle the comment panel's state
|
||||
const handleClickComment = (
|
||||
topicId: number,
|
||||
replyIid: number,
|
||||
|
@ -138,7 +136,7 @@ const handleClickComment = (
|
|||
"
|
||||
class="icon"
|
||||
v-tooltip="{
|
||||
message: { en: 'Comment Topic', zh: '评论话题' },
|
||||
message: { en: 'Comment', zh: '评论' },
|
||||
position: 'bottom',
|
||||
}"
|
||||
>
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
// Import icons
|
||||
import { Icon } from '@iconify/vue'
|
||||
// Import animations
|
||||
import 'animate.css'
|
||||
// Import Vue asynchronous functions
|
||||
import { computed, defineAsyncComponent } from 'vue'
|
||||
import { Icon } from '@iconify/vue'
|
||||
import 'animate.css'
|
||||
|
||||
const MilkdownEditor = defineAsyncComponent(
|
||||
() => import('@/components/milkdown/MilkdownEditorWrapper.vue')
|
||||
|
@ -15,28 +12,32 @@ const Tags = defineAsyncComponent(
|
|||
import ReplyPanelBtn from './ReplyPanelBtn.vue'
|
||||
|
||||
import { useKUNGalgameMessageStore } from '@/store/modules/message'
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
import { usePersistKUNGalgameTopicStore } from '@/store/modules/topic/topic'
|
||||
import { usePersistKUNGalgameReplyStore } from '@/store/modules/topic/reply'
|
||||
|
||||
import { useTempReplyStore } from '@/store/temp/topic/reply'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
const messageStore = useKUNGalgameMessageStore()
|
||||
// Use the topic page store
|
||||
const { isShowAdvance, isEdit, replyDraft, replyRewrite, replyPanelWidth } =
|
||||
storeToRefs(useKUNGalgameTopicStore())
|
||||
const { isShowAdvance } = storeToRefs(usePersistKUNGalgameTopicStore())
|
||||
const { replyDraft, isReplyRewriting, replyPanelWidth } = storeToRefs(
|
||||
usePersistKUNGalgameReplyStore()
|
||||
)
|
||||
|
||||
const { isEdit } = storeToRefs(useTempReplyStore())
|
||||
|
||||
const position = computed(() => {
|
||||
return replyDraft.value.to_floor === 0 ? 'master' : 'reply'
|
||||
return replyDraft.value.toFloor === 0 ? 'master' : 'reply'
|
||||
})
|
||||
|
||||
const panelWidth = computed(() => `${replyPanelWidth.value}%`)
|
||||
|
||||
const handleClosePanel = async () => {
|
||||
// If currently rewriting a reply
|
||||
if (replyRewrite.value.isReplyRewriting) {
|
||||
if (isReplyRewriting.value) {
|
||||
const res = await messageStore.alert('AlertInfo.edit.closePanel', true)
|
||||
// Implement user's confirmation or cancel logic here
|
||||
|
||||
if (res) {
|
||||
// Clear data because the reply has been updated at this point
|
||||
useKUNGalgameTopicStore().resetRewriteTopicData()
|
||||
usePersistKUNGalgameReplyStore().resetRewriteReplyData()
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
@ -61,7 +62,7 @@ const handleClosePanel = async () => {
|
|||
<span>{{ replyDraft.toUserName }}</span>
|
||||
<span>
|
||||
<span class="emoji">(⋈◍>◡<◍)。✧♡ </span>
|
||||
{{ `${$tm(`topic.panel.${position}`)} ${replyDraft.to_floor}` }}
|
||||
{{ `${$tm(`topic.panel.${position}`)} ${replyDraft.toFloor}` }}
|
||||
</span>
|
||||
</h3>
|
||||
<Icon
|
||||
|
|
|
@ -1,45 +1,39 @@
|
|||
<script setup lang="ts">
|
||||
// Global message component (bottom)
|
||||
import { useKUNGalgameMessageStore } from '@/store/modules/message'
|
||||
// Global message component (top)
|
||||
import Message from '@/components/alert/Message'
|
||||
// Import topic page store
|
||||
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||
// Temporary reply data
|
||||
import { useTempReplyStore } from '@/store/temp/reply'
|
||||
import { storeToRefs } from 'pinia'
|
||||
// Temporary response data for reply rewriting
|
||||
import { useTempReplyRewriteStore } from '@/store/temp/replyRewrite'
|
||||
|
||||
const { rid, replyContent, tags, edited } = storeToRefs(
|
||||
useTempReplyRewriteStore()
|
||||
)
|
||||
// Use the topic page store
|
||||
const { isShowAdvance, replyDraft, replyRewrite, isEdit } = storeToRefs(
|
||||
useKUNGalgameTopicStore()
|
||||
import { usePersistKUNGalgameTopicStore } from '@/store/modules/topic/topic'
|
||||
import { usePersistKUNGalgameReplyStore } from '@/store/modules/topic/reply'
|
||||
|
||||
import { useTempReplyStore } from '@/store/temp/topic/reply'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
const { isShowAdvance } = storeToRefs(usePersistKUNGalgameTopicStore())
|
||||
const { isSaveReply, isReplyRewriting, replyRewrite } = storeToRefs(
|
||||
usePersistKUNGalgameReplyStore()
|
||||
)
|
||||
|
||||
const { isEdit, textCount, tempReplyRewrite } = storeToRefs(useTempReplyStore())
|
||||
|
||||
const messageStore = useKUNGalgameMessageStore()
|
||||
|
||||
// Check if the reply is valid
|
||||
const isValidReply = () => {
|
||||
const count = replyDraft.value.textCount
|
||||
const count = textCount.value
|
||||
return count && count < 10007
|
||||
}
|
||||
|
||||
// Function to publish a reply
|
||||
const publishReply = async () => {
|
||||
if (isValidReply()) {
|
||||
// Reset page status, load status, and other page settings
|
||||
useKUNGalgameTopicStore().resetPageStatus()
|
||||
// Publish the reply
|
||||
const responseData = await useKUNGalgameTopicStore().postNewReply()
|
||||
const responseData = await usePersistKUNGalgameReplyStore().postNewReply()
|
||||
|
||||
if (responseData.code === 200) {
|
||||
// Save the data of the new reply
|
||||
useTempReplyStore().tempReply = responseData.data
|
||||
// Clear the data because the reply has been successfully posted
|
||||
useKUNGalgameTopicStore().resetReplyDraft()
|
||||
usePersistKUNGalgameReplyStore().resetReplyDraft()
|
||||
// Close the panel
|
||||
isEdit.value = false
|
||||
// Display a success message
|
||||
|
@ -66,10 +60,10 @@ const handlePublish = async () => {
|
|||
|
||||
// Save the data for reply rewriting
|
||||
const saveRewriteReply = () => {
|
||||
rid.value = replyRewrite.value.rid
|
||||
replyContent.value = replyRewrite.value.content
|
||||
tags.value = replyRewrite.value.tags
|
||||
edited.value = Date.now()
|
||||
tempReplyRewrite.value.rid = replyRewrite.value.rid
|
||||
tempReplyRewrite.value.content = replyRewrite.value.content
|
||||
tempReplyRewrite.value.tags = replyRewrite.value.tags
|
||||
tempReplyRewrite.value.edited = Date.now()
|
||||
}
|
||||
|
||||
// Handle reply rewriting
|
||||
|
@ -78,7 +72,7 @@ const handleRewrite = async () => {
|
|||
// Implement user's confirmation or cancel logic here
|
||||
if (res) {
|
||||
// Update the reply
|
||||
const responseData = await useKUNGalgameTopicStore().updateReply()
|
||||
const responseData = await usePersistKUNGalgameReplyStore().updateReply()
|
||||
|
||||
if (responseData.code === 200) {
|
||||
// Change the publish status, the front-end will add data for the new reply
|
||||
|
@ -88,7 +82,7 @@ const handleRewrite = async () => {
|
|||
saveRewriteReply()
|
||||
|
||||
// Clear the data because the reply has been updated at this point
|
||||
useKUNGalgameTopicStore().resetRewriteTopicData()
|
||||
usePersistKUNGalgameReplyStore().resetRewriteReplyData()
|
||||
// Close the panel
|
||||
isShowAdvance.value = false
|
||||
isEdit.value = false
|
||||
|
@ -101,7 +95,7 @@ const handleRewrite = async () => {
|
|||
// Handle saving a draft
|
||||
const handleSave = () => {
|
||||
// Set the save flag to true
|
||||
replyDraft.value.isSaveReply = true
|
||||
isSaveReply.value = true
|
||||
// Implement the logic for saving the draft here
|
||||
Message(
|
||||
'The draft has been saved successfully!',
|
||||
|
@ -117,7 +111,6 @@ const handleShowAdvance = () => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Button container -->
|
||||
<div class="btn-container">
|
||||
<!-- Advanced options button -->
|
||||
<button class="advance-btn" @click="handleShowAdvance">
|
||||
|
@ -125,20 +118,12 @@ const handleShowAdvance = () => {
|
|||
</button>
|
||||
|
||||
<!-- Confirm button -->
|
||||
<button
|
||||
v-if="!replyRewrite.isReplyRewriting"
|
||||
class="confirm-btn"
|
||||
@click="handlePublish"
|
||||
>
|
||||
<button v-if="!isReplyRewriting" class="confirm-btn" @click="handlePublish">
|
||||
{{ $tm('topic.panel.confirm') }}
|
||||
</button>
|
||||
|
||||
<!-- Rewrite button -->
|
||||
<button
|
||||
v-if="replyRewrite.isReplyRewriting"
|
||||
class="rewrite-btn"
|
||||
@click="handleRewrite"
|
||||
>
|
||||
<button v-if="isReplyRewriting" class="rewrite-btn" @click="handleRewrite">
|
||||
{{ $tm('topic.panel.rewrite') }}
|
||||
</button>
|
||||
|
||||
|
|
Loading…
Reference in a new issue