rebuild: rebuild store

This commit is contained in:
KUN1007 2023-11-11 20:52:47 +08:00
parent 7dee4ff190
commit 0525c389e8
48 changed files with 752 additions and 842 deletions

View file

@ -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
}

View file

@ -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>

View file

@ -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)

View file

@ -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>

View file

@ -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()

View file

@ -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>

View file

@ -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
}
}
)

View file

@ -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>

View file

@ -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()
}

View file

@ -1,5 +1,4 @@
/*
User Information Storage
*/
import { defineStore } from 'pinia'

View file

@ -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
},
},
})

View 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
},
},
})

View 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,
}),
})

View file

@ -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
View file

View 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: {},
})

View file

@ -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: {},
})

View 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)
},
},
})

View 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)
},
},
})

View 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)
},
},
})

View file

@ -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
View 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
View 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
View 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
}

View file

@ -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>

View file

@ -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) {

View file

@ -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 {

View file

@ -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">

View file

@ -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>

View file

@ -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
}

View file

@ -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'
}

View file

@ -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

View file

@ -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,
})

View file

@ -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);

View file

@ -39,7 +39,7 @@ const {
user,
// replies,
status,
share,
// share,
category,
// popularity,
upvote_time,

View file

@ -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,

View file

@ -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>

View file

@ -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,

View file

@ -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 = () => {

View file

@ -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"

View file

@ -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',
}"
>

View file

@ -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);

View file

@ -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>

View file

@ -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()

View file

@ -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 {

View file

@ -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',
}"
>

View file

@ -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

View file

@ -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>