mirror of
https://github.com/keven1024/015.git
synced 2026-05-26 07:08:02 +00:00
refactor(front): 优化状态管理和组件逻辑,简化GlobalDrawer和Tiptap组件的实现
This commit is contained in:
@@ -1,19 +1,19 @@
|
|||||||
<!-- app.vue -->
|
<!-- app.vue -->
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { defineRule } from 'vee-validate';
|
import { defineRule } from 'vee-validate'
|
||||||
import { all } from '@vee-validate/rules';
|
import { all } from '@vee-validate/rules'
|
||||||
Object.entries(all).forEach(([name, rule]) => {
|
Object.entries(all).forEach(([name, rule]) => {
|
||||||
defineRule(name, rule);
|
defineRule(name, rule)
|
||||||
});
|
})
|
||||||
// @ts-check
|
// @ts-check
|
||||||
const { $serwist } = useNuxtApp();
|
// const { $serwist } = useNuxtApp();
|
||||||
$serwist?.addEventListener("installed", () => {
|
// $serwist?.addEventListener("installed", () => {
|
||||||
console.log("Serwist installed!");
|
// console.log("Serwist installed!");
|
||||||
});
|
// });
|
||||||
void $serwist?.register({ immediate: true });
|
// void $serwist?.register({ immediate: true });
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<NuxtLayout>
|
<NuxtLayout>
|
||||||
<NuxtPage />
|
<NuxtPage />
|
||||||
</NuxtLayout>
|
</NuxtLayout>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -3,24 +3,25 @@ import { Drawer, DrawerContent } from '@/components/ui/drawer'
|
|||||||
import { createVNode } from 'vue'
|
import { createVNode } from 'vue'
|
||||||
import useStore from '@/composables/useStore'
|
import useStore from '@/composables/useStore'
|
||||||
|
|
||||||
const store = useStore('drawer')
|
const store = useStore()
|
||||||
const drawer = computed(() => store?._get('drawer'))
|
const currentDrawer = computed(() => store.drawer?.[store.drawer?.length - 1])
|
||||||
const currentDrawer = computed(() => drawer?.value?.[drawer?.value?.length - 1])
|
|
||||||
|
|
||||||
const render = computed<() => Component>(() => currentDrawer?.value?.render)
|
const render = computed(() => currentDrawer?.value?.render)
|
||||||
const hide = computed<() => void>(() => currentDrawer?.value?.onClose)
|
const hide = computed(() => currentDrawer?.value?.onClose)
|
||||||
const Children = () =>
|
const Children = () =>
|
||||||
createVNode(render.value, {
|
render.value
|
||||||
hide: hide?.value,
|
? createVNode(render.value, {
|
||||||
})
|
hide: hide?.value,
|
||||||
|
})
|
||||||
|
: null
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Drawer
|
<Drawer
|
||||||
:open="!!drawer?.[drawer?.length - 1]"
|
:open="!!store.drawer?.[store.drawer?.length - 1]"
|
||||||
@update:open="
|
@update:open="
|
||||||
(open) => {
|
(open) => {
|
||||||
if (!open && drawer?.length > 0) {
|
if (!open && store?.drawer?.length && hide) {
|
||||||
hide()
|
hide()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,48 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Editor, EditorContent } from '@tiptap/vue-3'
|
import { Editor, EditorContent } from '@tiptap/vue-3'
|
||||||
import StarterKit from '@tiptap/starter-kit'
|
import StarterKit from '@tiptap/starter-kit'
|
||||||
import { Markdown } from 'tiptap-markdown';
|
import { Markdown } from 'tiptap-markdown'
|
||||||
import Placeholder from '@tiptap/extension-placeholder'
|
import Placeholder from '@tiptap/extension-placeholder'
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: string
|
modelValue?: string
|
||||||
placeholder?: string
|
placeholder?: string
|
||||||
}>()
|
}>()
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:modelValue', value: string): void
|
(e: 'update:modelValue', value: string): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const editor = ref<Editor | undefined>(undefined)
|
const editor = ref<Editor | undefined>(undefined)
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
editor.value = new Editor({
|
editor.value = new Editor({
|
||||||
content: props.modelValue,
|
content: props.modelValue,
|
||||||
extensions: [StarterKit, Markdown.configure({
|
extensions: [
|
||||||
transformPastedText: true,
|
StarterKit,
|
||||||
transformCopiedText: true
|
Markdown.configure({
|
||||||
}), Placeholder.configure({
|
transformPastedText: true,
|
||||||
placeholder: props.placeholder ?? ''
|
transformCopiedText: true,
|
||||||
})],
|
}),
|
||||||
onUpdate: () => {
|
Placeholder.configure({
|
||||||
// HTML
|
placeholder: props.placeholder ?? '',
|
||||||
emit('update:modelValue', editor.value?.storage?.markdown?.getMarkdown() ?? '')
|
}),
|
||||||
|
// CommandsPlugin,
|
||||||
|
],
|
||||||
|
onUpdate: () => {
|
||||||
|
emit('update:modelValue', editor.value?.storage?.markdown?.getMarkdown() ?? '')
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
(value) => {
|
||||||
|
if (value !== editor.value?.storage?.markdown?.getMarkdown()) {
|
||||||
|
editor.value?.commands.setContent(value ?? '')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
})
|
|
||||||
watch(() => props.modelValue, (value) => {
|
|
||||||
editor.value?.commands.setContent(value)
|
|
||||||
})
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
editor.value?.destroy()
|
editor.value?.destroy()
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<editor-content :editor="editor" class="prose prose-sm bg-white/50 rounded-md p-2 [&>*]:outline-none prose-p:my-1" />
|
<editor-content :editor="editor" class="prose prose-sm bg-white/50 rounded-md p-2 [&>*]:outline-none prose-p:my-1" />
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,34 +1,17 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { cloneDeep, get, isEmpty, isUndefined, set, isString } from 'lodash-es'
|
|
||||||
|
|
||||||
type StoreType = Record<string, any>
|
type renderComponent = Component | ((props: { hide: () => null }) => VNode)
|
||||||
|
|
||||||
const initState: StoreType = {}
|
type StoreProps = {
|
||||||
// 做了一点小小的改进,可以传入key,会自动初始化,如果不初始化的话容易导致不存在值而丢失响应式
|
tiptapCommandsView?: any
|
||||||
const useStore = (key?: string) => {
|
drawer?: { render?: renderComponent; onClose: (data?: any) => void; key: string }[]
|
||||||
const store = defineStore('store', {
|
|
||||||
state: () => ({
|
|
||||||
...initState,
|
|
||||||
}),
|
|
||||||
actions: {
|
|
||||||
_get(path?: string) {
|
|
||||||
if (isEmpty(path) || isUndefined(path)) {
|
|
||||||
return this.$state
|
|
||||||
}
|
|
||||||
return get(this.$state, path)
|
|
||||||
},
|
|
||||||
_set(path: string, value: any) {
|
|
||||||
const newState = cloneDeep(this.$state)
|
|
||||||
set(newState, path, value)
|
|
||||||
this.$patch(newState)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})()
|
|
||||||
if (!isEmpty(key) && isString(key) && isUndefined(store?._get(key))) {
|
|
||||||
// console.log('reset', key, store?._get(key))
|
|
||||||
store?._set(key, null)
|
|
||||||
}
|
|
||||||
return store
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const useStore = defineStore<any, StoreProps>('store', () => {
|
||||||
|
return {
|
||||||
|
tiptapCommandsView: null,
|
||||||
|
drawer: [],
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
export default useStore
|
export default useStore
|
||||||
|
|||||||
@@ -7,14 +7,11 @@ const showDrawer = (props: DrawerProps) => {
|
|||||||
return new Promise<void>((res) => {
|
return new Promise<void>((res) => {
|
||||||
const { render } = props || {}
|
const { render } = props || {}
|
||||||
const onClose = (data?: any) => {
|
const onClose = (data?: any) => {
|
||||||
store._set(
|
store.drawer = (store.drawer ?? [])?.filter((item: any) => item.key !== key)
|
||||||
'drawer',
|
|
||||||
(store._get('drawer')?.value ?? [])?.filter((item: any) => item.key !== key)
|
|
||||||
)
|
|
||||||
res(data)
|
res(data)
|
||||||
}
|
}
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
store._set('drawer', [...(store._get('drawer')?.value || []), { render, onClose, key }])
|
store.drawer = [...(store.drawer || []), { render, onClose, key }]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user