mirror of
https://github.com/pipipi-pikachu/PPTist.git
synced 2025-04-15 02:20:00 +08:00
perf: 演讲者备注编辑优化
This commit is contained in:
parent
0c50ff12ef
commit
7a898e2bb5
@ -22,6 +22,8 @@
|
|||||||
</template>
|
</template>
|
||||||
<button><IconHighLight /></button>
|
<button><IconHighLight /></button>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
<button :class="{ 'active': attr?.bulletList }" @click="execCommand('bulletList')"><IconList /></button>
|
||||||
|
<button :class="{ 'active': attr?.orderedList }" @click="execCommand('orderedList')"><IconOrderedList /></button>
|
||||||
<button @click="execCommand('clear')"><IconFormat /></button>
|
<button @click="execCommand('clear')"><IconFormat /></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -34,6 +36,7 @@ import { useMainStore } from '@/store'
|
|||||||
import type { EditorView } from 'prosemirror-view'
|
import type { EditorView } from 'prosemirror-view'
|
||||||
import { initProsemirrorEditor, createDocument } from '@/utils/prosemirror'
|
import { initProsemirrorEditor, createDocument } from '@/utils/prosemirror'
|
||||||
import { addMark, autoSelectAll, getTextAttrs, type TextAttrs } from '@/utils/prosemirror/utils'
|
import { addMark, autoSelectAll, getTextAttrs, type TextAttrs } from '@/utils/prosemirror/utils'
|
||||||
|
import { toggleList } from '@/utils/prosemirror/commands/toggleList'
|
||||||
import tippy, { type Instance } from 'tippy.js'
|
import tippy, { type Instance } from 'tippy.js'
|
||||||
|
|
||||||
import ColorPicker from '@/components/ColorPicker/index.vue'
|
import ColorPicker from '@/components/ColorPicker/index.vue'
|
||||||
@ -99,18 +102,21 @@ const handleMouseup = () => {
|
|||||||
if (menuInstance.value) {
|
if (menuInstance.value) {
|
||||||
attr.value = getTextAttrs(editorView)
|
attr.value = getTextAttrs(editorView)
|
||||||
|
|
||||||
|
const { x, y, left, top } = range.getBoundingClientRect()
|
||||||
|
|
||||||
menuInstance.value.setProps({
|
menuInstance.value.setProps({
|
||||||
getReferenceClientRect: () => range.getBoundingClientRect(),
|
getReferenceClientRect: () => ({
|
||||||
|
x, y, left, top,
|
||||||
|
height: 0,
|
||||||
|
width: 0,
|
||||||
|
right: left,
|
||||||
|
bottom: top,
|
||||||
|
} as DOMRect),
|
||||||
})
|
})
|
||||||
menuInstance.value.show()
|
menuInstance.value.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleMousedown = () => {
|
|
||||||
hideMenuInstance()
|
|
||||||
window.getSelection()?.removeAllRanges()
|
|
||||||
}
|
|
||||||
|
|
||||||
const execCommand = (command: string, value?: string) => {
|
const execCommand = (command: string, value?: string) => {
|
||||||
if (command === 'color' && value) {
|
if (command === 'color' && value) {
|
||||||
const mark = editorView.state.schema.marks.forecolor.create({ color: value })
|
const mark = editorView.state.schema.marks.forecolor.create({ color: value })
|
||||||
@ -138,6 +144,14 @@ const execCommand = (command: string, value?: string) => {
|
|||||||
autoSelectAll(editorView)
|
autoSelectAll(editorView)
|
||||||
toggleMark(editorView.state.schema.marks.strikethrough)(editorView.state, editorView.dispatch)
|
toggleMark(editorView.state.schema.marks.strikethrough)(editorView.state, editorView.dispatch)
|
||||||
}
|
}
|
||||||
|
else if (command === 'bulletList') {
|
||||||
|
const { bullet_list: bulletList, list_item: listItem } = editorView.state.schema.nodes
|
||||||
|
toggleList(bulletList, listItem)(editorView.state, editorView.dispatch)
|
||||||
|
}
|
||||||
|
else if (command === 'orderedList') {
|
||||||
|
const { ordered_list: orderedList, list_item: listItem } = editorView.state.schema.nodes
|
||||||
|
toggleList(orderedList, listItem)(editorView.state, editorView.dispatch)
|
||||||
|
}
|
||||||
else if (command === 'clear') {
|
else if (command === 'clear') {
|
||||||
autoSelectAll(editorView)
|
autoSelectAll(editorView)
|
||||||
const { $from, $to } = editorView.state.selection
|
const { $from, $to } = editorView.state.selection
|
||||||
@ -155,7 +169,11 @@ onMounted(() => {
|
|||||||
focus: handleFocus,
|
focus: handleFocus,
|
||||||
blur: handleBlur,
|
blur: handleBlur,
|
||||||
mouseup: handleMouseup,
|
mouseup: handleMouseup,
|
||||||
mousedown: handleMousedown,
|
mousedown: () => {
|
||||||
|
window.getSelection()?.removeAllRanges()
|
||||||
|
hideMenuInstance()
|
||||||
|
},
|
||||||
|
keydown: hideMenuInstance,
|
||||||
input: handleInput,
|
input: handleInput,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
@ -167,7 +185,7 @@ onMounted(() => {
|
|||||||
content: menuRef.value!,
|
content: menuRef.value!,
|
||||||
interactive: true,
|
interactive: true,
|
||||||
trigger: 'manual',
|
trigger: 'manual',
|
||||||
placement: 'top',
|
placement: 'top-start',
|
||||||
hideOnClick: 'toggle',
|
hideOnClick: 'toggle',
|
||||||
offset: [0, 6],
|
offset: [0, 6],
|
||||||
})
|
})
|
||||||
@ -179,10 +197,16 @@ onUnmounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.editor {
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
.prosemirror-editor {
|
.prosemirror-editor {
|
||||||
|
height: 100%;
|
||||||
cursor: text;
|
cursor: text;
|
||||||
|
|
||||||
::v-deep(.ProseMirror) {
|
::v-deep(.ProseMirror) {
|
||||||
|
height: 100%;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
@ -200,7 +224,7 @@ onUnmounted(() => {
|
|||||||
.menu {
|
.menu {
|
||||||
display: flex;
|
display: flex;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
padding: 5px;
|
padding: 6px 4px;
|
||||||
border-radius: $borderRadius;
|
border-radius: $borderRadius;
|
||||||
box-shadow: 0 0 20px 0 rgba(0, 0, 0, .15);
|
box-shadow: 0 0 20px 0 rgba(0, 0, 0, .15);
|
||||||
|
|
||||||
@ -210,8 +234,11 @@ onUnmounted(() => {
|
|||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
border-radius: $borderRadius;
|
border-radius: $borderRadius;
|
||||||
font-size: 15px;
|
font-size: 16px;
|
||||||
margin: 0 3px;
|
margin: 0 3px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover, &.active {
|
&:hover, &.active {
|
||||||
|
@ -67,7 +67,7 @@
|
|||||||
<span>演讲者备注</span>
|
<span>演讲者备注</span>
|
||||||
<span>P {{slideIndex + 1}} / {{slides.length}}</span>
|
<span>P {{slideIndex + 1}} / {{slides.length}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="remark-content" :style="{ fontSize: remarkFontSize + 'px' }" v-html="currentSlideRemark"></div>
|
<div class="remark-content ProseMirror-static" :style="{ fontSize: remarkFontSize + 'px' }" v-html="currentSlideRemark"></div>
|
||||||
<div class="remark-scale">
|
<div class="remark-scale">
|
||||||
<div :class="['scale-btn', { 'disable': remarkFontSize === 12 }]" @click="setRemarkFontSize(remarkFontSize - 2)"><IconMinus /></div>
|
<div :class="['scale-btn', { 'disable': remarkFontSize === 12 }]" @click="setRemarkFontSize(remarkFontSize - 2)"><IconMinus /></div>
|
||||||
<div :class="['scale-btn', { 'disable': remarkFontSize === 40 }]" @click="setRemarkFontSize(remarkFontSize + 2)"><IconPlus /></div>
|
<div :class="['scale-btn', { 'disable': remarkFontSize === 40 }]" @click="setRemarkFontSize(remarkFontSize + 2)"><IconPlus /></div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user