Commit 11c97d0b authored by 罗超's avatar 罗超

Merge branch 'router'

parents 2fecfbb4 3fb3b203
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
"@types/ali-oss": "^6.16.11", "@types/ali-oss": "^6.16.11",
"@types/opentype.js": "^1.3.8", "@types/opentype.js": "^1.3.8",
"@types/psd": "^3.4.3", "@types/psd": "^3.4.3",
"@vue/reactivity": "^3.4.29",
"@vueuse/integrations": "^10.7.2", "@vueuse/integrations": "^10.7.2",
"ali-oss": "^6.18.1", "ali-oss": "^6.18.1",
"animate.css": "^4.1.1", "animate.css": "^4.1.1",
......
...@@ -76,5 +76,6 @@ const handleClickMenuItem = (item: ContextmenuItem) => { ...@@ -76,5 +76,6 @@ const handleClickMenuItem = (item: ContextmenuItem) => {
position: fixed; position: fixed;
z-index: 9999; z-index: 9999;
user-select: none; user-select: none;
font-family: Arial, Helvetica, sans-serif;
} }
</style> </style>
\ No newline at end of file
import type { Node, NodeType, ResolvedPos, Mark, MarkType } from 'prosemirror-model' import type { Node, NodeType, ResolvedPos, Mark, MarkType } from 'prosemirror-model'
import type { EditorState, Selection } from 'prosemirror-state' import { TextSelection, type EditorState, type Selection } from 'prosemirror-state'
import type { EditorView } from 'prosemirror-view' import type { EditorView } from 'prosemirror-view'
import { selectAll } from 'prosemirror-commands' import { selectAll} from 'prosemirror-commands'
export const autoSelectAll = (view: EditorView) => { export const autoSelectAll = (view: EditorView) => {
const { empty } = view.state.selection const { empty } = view.state.selection
if (empty) selectAll(view.state, view.dispatch) if (empty) selectAll(view.state, view.dispatch)
} }
export const clearSelection = (view: EditorView) => {
const { state, dispatch } = view
const { selection } = state
if (!selection.empty) {
const selectionWithoutRange = TextSelection.create(state.doc, selection.anchor)
const transaction = state.tr.setSelection(selectionWithoutRange)
dispatch(transaction)
}
}
export const addMark = (editorView: EditorView, mark: Mark, selection?: { from: number; to: number; }) => { export const addMark = (editorView: EditorView, mark: Mark, selection?: { from: number; to: number; }) => {
if (selection) { if (selection) {
editorView.dispatch(editorView.state.tr.addMark(selection.from, selection.to, mark)) editorView.dispatch(editorView.state.tr.addMark(selection.from, selection.to, mark))
......
...@@ -20,19 +20,19 @@ withDefaults(defineProps<{ ...@@ -20,19 +20,19 @@ withDefaults(defineProps<{
height: 0; height: 0;
left: 0; left: 0;
top: 0; top: 0;
border: 0 dashed $themeColor; border: 0 solid $themeColor;
&.top { &.top {
border-top-width: 1px; border-top-width: 2px;
} }
&.bottom { &.bottom {
border-bottom-width: 1px; border-bottom-width: 2px;
} }
&.left { &.left {
border-left-width: 1px; border-left-width: 2px;
} }
&.right { &.right {
border-right-width: 1px; border-right-width: 2px;
} }
&.wide { &.wide {
......
...@@ -31,15 +31,29 @@ const rotateClassName = computed(() => { ...@@ -31,15 +31,29 @@ const rotateClassName = computed(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
.resize-handler { .resize-handler {
position: absolute; position: absolute;
width: 10px;
height: 10px; width:26px;
height: 26px;
left: 0; left: 0;
top: 0; top: 0;
margin: -5px 0 0 -5px; margin: -12px 0 0 -12px;
border: 1px solid $themeColor; // border: 1px solid $themeColor;
background-color: #fff;
border-radius: 1px;
cursor: pointer; &::after{
width: 10px;
height: 10px;
border-radius: 10px;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2);
background-color: #fff;
cursor: inherit;
display: block;
content: ' ';
left: 8px;
top:8px;
position: absolute;
}
&.left-top.rotate-0, &.left-top.rotate-0,
&.right-bottom.rotate-0, &.right-bottom.rotate-0,
...@@ -49,7 +63,7 @@ const rotateClassName = computed(() => { ...@@ -49,7 +63,7 @@ const rotateClassName = computed(() => {
&.right-top.rotate-90, &.right-top.rotate-90,
&.top.rotate-135, &.top.rotate-135,
&.bottom.rotate-135 { &.bottom.rotate-135 {
cursor: nwse-resize; cursor: url('https://im.oytour.com/trip/cusor/8f76b0abb0a62213ab3795d3ebaf3c3e.svg') 16 16, nwse-resize;
} }
&.top.rotate-0, &.top.rotate-0,
&.bottom.rotate-0, &.bottom.rotate-0,
...@@ -59,7 +73,7 @@ const rotateClassName = computed(() => { ...@@ -59,7 +73,7 @@ const rotateClassName = computed(() => {
&.right.rotate-90, &.right.rotate-90,
&.left-bottom.rotate-135, &.left-bottom.rotate-135,
&.right-top.rotate-135 { &.right-top.rotate-135 {
cursor: ns-resize; cursor: url('https://im.oytour.com/trip/cusor/4f7515dd177541d307de562bd6ee8f07.svg') 16 16, ns-resize;
} }
&.left-bottom.rotate-0, &.left-bottom.rotate-0,
&.right-top.rotate-0, &.right-top.rotate-0,
...@@ -69,7 +83,7 @@ const rotateClassName = computed(() => { ...@@ -69,7 +83,7 @@ const rotateClassName = computed(() => {
&.right-bottom.rotate-90, &.right-bottom.rotate-90,
&.left.rotate-135, &.left.rotate-135,
&.right.rotate-135 { &.right.rotate-135 {
cursor: nesw-resize; cursor: url('https://im.oytour.com/trip/cusor/13cfd89732053891fab7d23547a6d4f0.svg') 16 16, nesw-resize;
} }
&.left.rotate-0, &.left.rotate-0,
&.right.rotate-0, &.right.rotate-0,
...@@ -79,7 +93,17 @@ const rotateClassName = computed(() => { ...@@ -79,7 +93,17 @@ const rotateClassName = computed(() => {
&.bottom.rotate-90, &.bottom.rotate-90,
&.left-top.rotate-135, &.left-top.rotate-135,
&.right-bottom.rotate-135 { &.right-bottom.rotate-135 {
cursor: ew-resize; cursor: url('https://im.oytour.com/trip/cusor/7e6be5a8633602679325c01e745e53ef.svg') 16 16, ew-resize !important;
}
&.left.rotate-0::after,
&.right.rotate-0::after{
width:6px;
height: 14px;
border-radius: 6px;
left: 10px;
top: 6px;
cursor: url('https://im.oytour.com/trip/cusor/7e6be5a8633602679325c01e745e53ef.svg') 16 16, ew-resize !important;
// b7f2dba7d2a5c7631de984f35d15f2ee
} }
} }
</style> </style>
\ No newline at end of file
...@@ -11,12 +11,13 @@ ...@@ -11,12 +11,13 @@
position: absolute; position: absolute;
width: 10px; width: 10px;
height: 10px; height: 10px;
border-radius: 10px;
top: -25px; top: -25px;
margin-left: -5px; margin-left: -4px;
border: 1px solid $themeColor; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2);
// border: 1px solid $themeColor;
background-color: #fff; background-color: #fff;
border-radius: 1px; cursor: url('https://im.oytour.com/trip/cusor/b7f2dba7d2a5c7631de984f35d15f2ee.svg') 16 16, grab;
cursor: grab;
&:active { &:active {
cursor: grabbing; cursor: grabbing;
......
...@@ -173,8 +173,8 @@ const handleClip = (data: ImageClipedEmitData | null) => { ...@@ -173,8 +173,8 @@ const handleClip = (data: ImageClipedEmitData | null) => {
.editable-element-image { .editable-element-image {
position: absolute; position: absolute;
&.lock .element-content { &.lock .element-content{
cursor: default; cursor: url('https://im.oytour.com/trip/cusor/c7ca2e93ad449598be9ead2d132dd05b.svg'), default;
} }
} }
.rotate-wrapper { .rotate-wrapper {
......
...@@ -15,7 +15,7 @@ import { useMainStore } from '@/store' ...@@ -15,7 +15,7 @@ import { useMainStore } from '@/store'
import type { EditorView } from 'prosemirror-view' import type { EditorView } from 'prosemirror-view'
import { toggleMark, wrapIn, lift } from 'prosemirror-commands' import { toggleMark, wrapIn, lift } from 'prosemirror-commands'
import { initProsemirrorEditor, createDocument } from '@/utils/prosemirror' import { initProsemirrorEditor, createDocument } from '@/utils/prosemirror'
import { isActiveOfParentNodeType, findNodesWithSameMark, getTextAttrs, autoSelectAll, addMark, markActive, getFontsize } from '@/utils/prosemirror/utils' import { isActiveOfParentNodeType, findNodesWithSameMark, getTextAttrs, autoSelectAll, addMark, markActive, getFontsize, clearSelection } from '@/utils/prosemirror/utils'
import emitter, { EmitterEvents, type RichTextAction, type RichTextCommand } from '@/utils/emitter' import emitter, { EmitterEvents, type RichTextAction, type RichTextCommand } from '@/utils/emitter'
import { alignmentCommand } from '@/utils/prosemirror/commands/setTextAlign' import { alignmentCommand } from '@/utils/prosemirror/commands/setTextAlign'
import { indentCommand, textIndentCommand } from '@/utils/prosemirror/commands/setTextIndent' import { indentCommand, textIndentCommand } from '@/utils/prosemirror/commands/setTextIndent'
...@@ -96,7 +96,8 @@ watch(() => props.editable, () => { ...@@ -96,7 +96,8 @@ watch(() => props.editable, () => {
// 暴露 focus 方法 // 暴露 focus 方法
const focus = () => editorView.focus() const focus = () => editorView.focus()
const selectAll = () => autoSelectAll(editorView) const selectAll = () => autoSelectAll(editorView)
defineExpose({ focus,selectAll }) const clearSelect = () => clearSelection(editorView)
defineExpose({ focus,selectAll,clearSelect })
// 执行富文本命令(可以是一个或多个) // 执行富文本命令(可以是一个或多个)
// 部分命令在执行前先判断当前选区是否为空,如果选区为空先进行全选操作 // 部分命令在执行前先判断当前选区是否为空,如果选区为空先进行全选操作
......
...@@ -44,9 +44,10 @@ ...@@ -44,9 +44,10 @@
}" }"
/> />
<!-- 当字号过大且行高较小时,会出现文字高度溢出的情况,导致拖拽区域无法被选中,因此添加了以下节点避免该情况 --> <!-- 当字号过大且行高较小时,会出现文字高度溢出的情况,导致拖拽区域无法被选中,因此添加了以下节点避免该情况222 -->
<div class="drag-handler top"></div> <div class="drag-handler top"></div>
<div class="drag-handler bottom"></div> <div class="drag-handler bottom"></div>
<!-- <div class="drag-handler full"></div> -->
</div> </div>
</div> </div>
</div> </div>
...@@ -74,6 +75,8 @@ const { shadowStyle } = useElementShadow(shadow) ...@@ -74,6 +75,8 @@ const { shadowStyle } = useElementShadow(shadow)
&.lock .element-content { &.lock .element-content {
cursor: default; cursor: default;
} }
} }
.rotate-wrapper { .rotate-wrapper {
width: 100%; width: 100%;
...@@ -102,12 +105,18 @@ const { shadowStyle } = useElementShadow(shadow) ...@@ -102,12 +105,18 @@ const { shadowStyle } = useElementShadow(shadow)
position: absolute; position: absolute;
left: 0; left: 0;
right: 0; right: 0;
z-index: 100;
&.top { &.top {
top: 0; top: 0;
} }
&.bottom { &.bottom {
bottom: 0; bottom: 0;
} }
&.full{
top: 0;
bottom: 0;
height: unset;
}
} }
.clip-box{ .clip-box{
-webkit-background-clip: text !important; -webkit-background-clip: text !important;
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
@mousedown="$event => handleSelectElement($event)" @mousedown="$event => handleSelectElement($event)"
@touchstart="$event => handleSelectElement($event)" @touchstart="$event => handleSelectElement($event)"
> >
<div class="full-lock" v-if="fullLockVisible<2" @click="hideLockHandler"></div>
<ElementOutline <ElementOutline
:width="elementInfo.width" :width="elementInfo.width"
:height="elementInfo.height" :height="elementInfo.height"
...@@ -55,7 +56,7 @@ ...@@ -55,7 +56,7 @@
ref="editorRef" ref="editorRef"
/> />
<!-- 当字号过大且行高较小时,会出现文字高度溢出的情况,导致拖拽区域无法被选中,因此添加了以下节点避免该情况 --> <!-- 当字号过大且行高较小时,会出现文字高度溢出的情况,导致拖拽区域无法被选中,因此添加了以下节点避免该情况111 -->
<template v-show="!activeGroupElementId"> <template v-show="!activeGroupElementId">
<div class="drag-handler top" @dblclick="setEditorHandler"></div> <div class="drag-handler top" @dblclick="setEditorHandler"></div>
<div class="drag-handler bottom" @dblclick="setEditorHandler"></div> <div class="drag-handler bottom" @dblclick="setEditorHandler"></div>
...@@ -95,6 +96,7 @@ const editorRef = ref() ...@@ -95,6 +96,7 @@ const editorRef = ref()
const shadow = computed(() => props.elementInfo.shadow) const shadow = computed(() => props.elementInfo.shadow)
const { shadowStyle } = useElementShadow(shadow) const { shadowStyle } = useElementShadow(shadow)
const fullLockVisible = ref(0)
const handleSelectElement = (e: MouseEvent | TouchEvent, canMove = true) => { const handleSelectElement = (e: MouseEvent | TouchEvent, canMove = true) => {
if(e.button && e.button== 1) return if(e.button && e.button== 1) return
...@@ -130,6 +132,10 @@ watch(isScaling, () => { ...@@ -130,6 +132,10 @@ watch(isScaling, () => {
} }
}) })
const hideLockHandler = ()=>{
fullLockVisible.value++
}
const updateTextElementHeight = (entries: ResizeObserverEntry[]) => { const updateTextElementHeight = (entries: ResizeObserverEntry[]) => {
const contentRect = entries[0].contentRect const contentRect = entries[0].contentRect
if (!elementRef.value) return if (!elementRef.value) return
...@@ -187,7 +193,11 @@ const checkEmptyText = debounce(function() { ...@@ -187,7 +193,11 @@ const checkEmptyText = debounce(function() {
const isHandleElement = computed(() => handleElementId.value === props.elementInfo.id) const isHandleElement = computed(() => handleElementId.value === props.elementInfo.id)
watch(isHandleElement, () => { watch(isHandleElement, () => {
if (!isHandleElement.value) checkEmptyText() if (!isHandleElement.value) {
checkEmptyText()
editorRef.value?.clearSelect()
fullLockVisible.value=0
}
}) })
</script> </script>
...@@ -220,6 +230,16 @@ watch(isHandleElement, () => { ...@@ -220,6 +230,16 @@ watch(isHandleElement, () => {
::v-deep(a) { ::v-deep(a) {
cursor: text; cursor: text;
} }
.full-lock{
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
cursor: url('https://im.oytour.com/trip/cusor/c7ca2e93ad449598be9ead2d132dd05b.svg'), default;
z-index: 99;
}
} }
.drag-handler { .drag-handler {
height: 20px; height: 20px;
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment