feat: separate editor store

This commit is contained in:
KUN1007 2023-09-18 15:11:55 +08:00
parent e3e67f9156
commit 051a031831
9 changed files with 165 additions and 71 deletions

View file

@ -16,13 +16,8 @@ const EditorSettingsMenu = defineAsyncComponent(
import 'animate.css'
//
/**
* @param {number} - 编辑器文字计数
* @param {boolean} - 是否显示编辑器设置
*/
defineProps<{
textCount: number
isShowSettings: boolean
}>()
const router = useRouter()
@ -60,7 +55,6 @@ const handelClickSettings = () => {
@click="handelClickSettings"
class="settings-icon"
:class="settingsPanelActive"
v-if="isShowSettings"
>
<Icon icon="uiw:setting-o" />
</span>

View file

@ -1,33 +1,48 @@
<script setup lang="ts">
import { ref, watch } from 'vue'
import { ref, watch, computed } from 'vue'
import { useRoute } from 'vue-router'
// css
import 'animate.css'
// store
import { useKUNGalgameEditStore } from '@/store/modules/edit'
// store
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
import { storeToRefs } from 'pinia'
//
import SwitchButton from './SwitchButton.vue'
// 使 store
const settingsStore = useKUNGalgameEditStore()
const { mode } = storeToRefs(settingsStore)
const { editorHeight } = storeToRefs(useKUNGalgameEditStore())
// store
const { editorHeight, mode } = storeToRefs(useKUNGalgameEditStore())
// store
const { replyDraft } = storeToRefs(useKUNGalgameTopicStore())
defineProps<{
isShowSettingsMenu: boolean
}>()
//
const route = useRoute()
//
const routeName = computed(() => route.name as string)
//
const editorMode = computed(() =>
routeName.value === 'Edit' ? mode.value : replyDraft.value.mode
)
//
const isRefreshPage = ref(false)
//
watch(mode, () => {
isRefreshPage.value = true
})
watch(
() => [replyDraft.value.mode, mode.value],
() => {
isRefreshPage.value = true
}
)
const handleRefreshPage = () => location.reload()
</script>
@ -44,7 +59,9 @@ const handleRefreshPage = () => location.reload()
<span> {{ $tm('edit.editorHeight') }} </span>
<span>{{ editorHeight }} px</span>
</div>
<div class="editor-height">
<!-- 编辑界面 -->
<div v-if="routeName === 'Edit'" class="editor-height">
<span>300 px</span>
<input
type="range"
@ -56,6 +73,19 @@ const handleRefreshPage = () => location.reload()
<span>500 px</span>
</div>
<!-- 回复面板 -->
<div v-if="routeName === 'Topic'" class="editor-height">
<span>100 px</span>
<input
type="range"
min="100"
max="500"
step="1"
v-model="replyDraft.editorHeight"
/>
<span>500 px</span>
</div>
<!-- 是否显示编辑器高级选项 -->
<div class="editor-advance">
<div class="editor-advance-title">
@ -72,7 +102,7 @@ const handleRefreshPage = () => location.reload()
</div>
<!-- 切换按钮 -->
<select class="select" v-model="mode">
<select class="select" v-model="editorMode">
<option value="minimal">{{ $tm('edit.minimal') }}</option>
<option value="">{{ $tm('edit.default') }}</option>
<option value="essential">{{ $tm('edit.essential') }}</option>

View file

@ -30,9 +30,8 @@ import DOMPurify from 'dompurify'
import { debounce } from '@/utils/debounce'
// store
const { editorHeight, mode, theme, isSaveTopic, content } = storeToRefs(
useKUNGalgameEditStore()
)
const { editorHeight, mode, theme, textCount, isSaveTopic, content } =
storeToRefs(useKUNGalgameEditStore())
// store
const { replyDraft } = storeToRefs(useKUNGalgameTopicStore())
@ -43,7 +42,6 @@ const routeName = computed(() => route.name as string)
//
/**
* @param {number} height - 编辑器的高度
* @param {boolean} isShowToolbar - 是否显示工具栏
* @param {boolean} isShowAdvance - 是否显示高级编辑模式
* @param {boolean} isShowTitle - 是否显示标题
@ -51,7 +49,6 @@ const routeName = computed(() => route.name as string)
*/
const props = defineProps<{
height?: number
isShowToolbar: boolean
isShowAdvance: boolean
isShowTitle: boolean
@ -60,28 +57,37 @@ const props = defineProps<{
//
const editorRef = ref<typeof QuillEditor>()
//
const editorHeightStyle = computed(
() => `height: ${props.height ? props.height : editorHeight.value}px`
)
//
const isShowEditorToolbar = computed(() =>
props.isShowToolbar ? 'block' : 'none'
)
//
const valueHtml = ref('')
//
const textCount = ref(0)
//
const editorOptions = {
placeholder: 'Moe Moe Moe!',
}
//
const onEditorReady = () => {}
//
const editorHeightStyle = computed(
() =>
`height: ${
routeName.value === 'Edit'
? editorHeight.value
: replyDraft.value.editorHeight
}px`
)
//
const editorMode = computed(() =>
routeName.value === 'Edit' ? mode.value : replyDraft.value.mode
)
//
const textCountNumber = computed(() =>
routeName.value === 'Edit' ? textCount.value : replyDraft.value.textCount
)
//
const isShowEditorToolbar = computed(() =>
props.isShowToolbar ? 'block' : 'none'
)
onBeforeMount(() => {
// Edit
@ -115,7 +121,14 @@ const handleTextChange = async () => {
//
const length = computed(() => editorRef.value?.getText().trim().length)
textCount.value = length.value
//
if (routeName.value === 'Edit') {
textCount.value = length.value
}
if (routeName.value === 'Topic') {
replyDraft.value.textCount = length.value
}
}
</script>
@ -132,19 +145,14 @@ const handleTextChange = async () => {
:style="editorHeightStyle"
:theme="theme"
:modules="modules"
:toolbar="mode"
:toolbar="editorMode"
:options="editorOptions"
@textChange="handleTextChange"
@ready="onEditorReady"
@click.prevent
/>
<!-- 编辑器 footer -->
<EditorFooter
:textCount="textCount"
:editorHeight="editorHeight"
:isShowSettings="isShowSettings"
/>
<EditorFooter :textCount="textCountNumber" />
</div>
</template>

View file

@ -1,26 +1,49 @@
<!-- KUNGalgame 通用切换按钮 -->
<script setup lang="ts">
import { watch } from 'vue'
import { watch, computed } from 'vue'
import { useRoute } from 'vue-router'
// store
import { useKUNGalgameEditStore } from '@/store/modules/edit'
// store
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
import { storeToRefs } from 'pinia'
//
const route = useRoute()
//
const routeName = computed(() => route.name as string)
// 使 store
const settingsStore = useKUNGalgameEditStore()
const { isShowHotKeywords } = storeToRefs(settingsStore)
const { isShowHotKeywords } = storeToRefs(useKUNGalgameEditStore())
// store
const { replyDraft } = storeToRefs(useKUNGalgameTopicStore())
// store store
watch(isShowHotKeywords, (newValue) => {
isShowHotKeywords.value = newValue
})
watch(
() => [isShowHotKeywords.value, replyDraft.value.isShowHotKeywords],
([newValue1, newValue2]) => {
isShowHotKeywords.value = newValue1
replyDraft.value.isShowHotKeywords = newValue2
}
)
</script>
<template>
<input type="checkbox" id="switch" v-model="isShowHotKeywords" /><label
for="switch"
>Toggle</label
>
<!-- 根据路由名绑定不同的 model -->
<input
v-if="routeName === 'Edit'"
type="checkbox"
id="switch"
v-model="isShowHotKeywords"
/>
<input
v-if="routeName === 'Topic'"
type="checkbox"
id="switch"
v-model="replyDraft.isShowHotKeywords"
/>
<label for="switch"></label>
</template>
<style lang="scss" scoped>

View file

@ -98,7 +98,7 @@ export default {
panel: {
to: 'Reply To',
master: 'ご主人',
reply: 'zako♡',
reply: 'zako~♡',
},
},
update: {

View file

@ -14,6 +14,7 @@ interface Topic {
* @param {'snow' | 'bubble'} theme -
*/
editorHeight: number
textCount: number
mode: '' | 'essential' | 'minimal' | 'full'
theme: 'snow' | 'bubble'
@ -44,6 +45,7 @@ export const useKUNGalgameEditStore = defineStore({
persist: true,
state: (): Topic => ({
editorHeight: 300,
textCount: 0,
mode: '',
theme: 'snow',

View file

@ -21,6 +21,19 @@ import {
// 回复的缓存
interface ReplyDraft {
/**
*
* @param {number} editorHeight -
* @param {'' | 'essential' | 'minimal' | 'full'} mode - toolbar
* @param {'snow' | 'bubble'} theme -
*/
editorHeight: number
textCount: number
mode: '' | 'essential' | 'minimal' | 'full'
theme: 'snow' | 'bubble'
// 是否显示热门关键词
isShowHotKeywords: boolean
// 当前话题的 id
tid: number
r_uid: number
@ -90,6 +103,12 @@ export const useKUNGalgameTopicStore = defineStore({
scrollToReplyId: -1,
replyDraft: {
editorHeight: 200,
textCount: 0,
mode: '',
theme: 'snow',
isShowHotKeywords: true,
tid: 0,
r_uid: 0,
replyUserName: '',

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, computed, watch, onBeforeMount, onUpdated } from 'vue'
import { ref, computed, watch, onBeforeMount } from 'vue'
import { useRoute } from 'vue-router'
// store
import { useKUNGalgameEditStore } from '@/store/modules/edit'
@ -18,6 +18,13 @@ const { isShowHotKeywords, tags, isSaveTopic } = storeToRefs(
// store
const { replyDraft } = storeToRefs(useKUNGalgameTopicStore())
// tags
const isShowKeywords = computed(() =>
routeName.value === 'Edit'
? isShowHotKeywords.value
: replyDraft.value.isShowHotKeywords
)
// 7 tag
const hotTags = [
'啊这可海星',
@ -143,7 +150,7 @@ watch(selectedTags.value, () => {
<div class="hint">{{ $tm('edit.hint') }}</div>
<!-- 热门 tags -->
<div class="hot-tags" v-if="isShowHotKeywords">
<div class="hot-tags" v-if="isShowKeywords">
<!-- 标签的提示词 -->
<div class="tags-info">{{ $tm('edit.hot') }}</div>
<!-- 标签容器 -->

View file

@ -15,21 +15,34 @@ const { isShowAdvance, replyDraft, isEdit } = storeToRefs(
const info = useKUNGalgameMessageStore()
//
const isValidReply = () => {}
const isValidReply = () => {
return replyDraft.value.content.trim().length > 7 &&
replyDraft.value.content.trim() !== `<p><br></p>`
? true
: false
}
//
const publishReply = async () => {
//
useKUNGalgameTopicStore().resetPageStatus()
//
await useKUNGalgameTopicStore().postNewReply()
if (isValidReply()) {
console.log(replyDraft.value.content)
//
replyDraft.value.publishStatus = !replyDraft.value.publishStatus
//
useKUNGalgameTopicStore().resetReplyDraft()
//
isEdit.value = false
//
useKUNGalgameTopicStore().resetPageStatus()
//
await useKUNGalgameTopicStore().postNewReply()
//
replyDraft.value.publishStatus = !replyDraft.value.publishStatus
//
useKUNGalgameTopicStore().resetReplyDraft()
//
isEdit.value = false
//
message('Publish reply successfully!', '发布回复成功!', 'success')
} else {
message('Reply content cannot be empty!', '回复内容不能为空!', 'warn')
}
}
//
@ -38,8 +51,6 @@ const handlePublish = async () => {
//
if (res) {
publishReply()
//
message('Publish reply successfully!', '发布回复成功!', 'success')
} else {
//
message('Cancel publish reply', '取消发布回复', 'info')