From 5e86172cdd44e07a56e1406c45c7d8851eb5682d Mon Sep 17 00:00:00 2001 From: "jlj05024111@163.com" Date: Tue, 18 Nov 2025 20:28:00 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0markdown=E7=BC=96?= =?UTF-8?q?=E8=BE=91=E5=99=A8=E6=96=B0=E5=A2=9E=E6=94=AF=E6=8C=81=E6=89=8B?= =?UTF-8?q?=E5=8A=A8=E7=BC=96=E8=BE=91=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ibiz-markdown-editor.scss | 111 +++++++++++++++++- .../ibiz-markdown-editor.tsx | 111 +++++++++++++++++- src/locale/en/index.ts | 1 + src/locale/zh-CN/index.ts | 1 + 4 files changed, 220 insertions(+), 4 deletions(-) diff --git a/src/editor/markdown/ibiz-markdown-editor/ibiz-markdown-editor.scss b/src/editor/markdown/ibiz-markdown-editor/ibiz-markdown-editor.scss index ae9d69b47..9859cd848 100644 --- a/src/editor/markdown/ibiz-markdown-editor/ibiz-markdown-editor.scss +++ b/src/editor/markdown/ibiz-markdown-editor/ibiz-markdown-editor.scss @@ -1,12 +1,102 @@ $markdown: ( 'width': 100%, + color-manual-toolbar-bg-save: getCssVar(color,primary), + color-manual-toolbar-text-save: getCssVar(color, primary-active-text), + color-manual-toolbar-text-cancel: getCssVar(color,text,1), + color-manual-toolbar-text-cancel-hover: getCssVar(color,primary), + spacing-manual-toolbar-height: 32px, + spacing-manual-toolbar-gap: getCssVar('spacing',base), + spacing-manual-toolbar-item-padding: 0 getCssVar('spacing',base), + spacing-manual-toolbar-margin: getCssVar('spacing',base-tight) getCssVar('spacing',tight) 0 0, + spacing-manual-toolbar-fullscreen-height: getCssVar(height,control-default), + spacing-manual-toolbar-fullscreen-padding: 0 getCssVar('spacing',extra-loose), + spacing-manual-toolbar-fullscreen-height-header: getCssVar(spacing, super-loose), + height-manual-toolbar-height: getCssVar(height,control-default), + border-radius-manual-toolbar-item: getCssVar('border-radius', small), + border-manual-toolbar-fullscreen-footer: 1px solid getCssVar(color, border), + ); @include b(markdown) { - @include b(markdown-cherry) { - @include set-component-css-var('markdown', $markdown); + @include set-component-css-var('markdown', $markdown); + @include e('header'){ + display: flex; + flex-shrink: 0; + gap: getCssVar('markdown', 'spacing-manual-toolbar-gap'); + align-items: center; + justify-content: end; + height: getCssVar('markdown', 'spacing-manual-toolbar-height'); + @include m('edit'){ + cursor: pointer; + } + @include m('full'){ + cursor: pointer; + } + @include when('fullscreen'){ + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 999; + width: 100%; + height: calc(getCssVar('markdown', 'spacing-manual-toolbar-fullscreen-height-header')); + padding: getCssVar('markdown', 'spacing-manual-toolbar-fullscreen-padding'); + margin-top: 0; + background-color: var(--ibiz-view-bg-color); + + & + .ibiz-markdown-cherry .cherry.fullscreen{ + top: calc(getCssVar('markdown', 'spacing-manual-toolbar-fullscreen-height-header')); + height: calc(100% - #{getCssVar('markdown', 'spacing-manual-toolbar-fullscreen-height-header')}); + } + } + + } + + @include e('footer'){ + display: flex; + gap: getCssVar('markdown', 'spacing-manual-toolbar-gap'); + align-items: center; + justify-content: end; + height: getCssVar('markdown', 'spacing-manual-toolbar-height'); + margin: getCssVar('markdown', 'spacing-manual-toolbar-margin'); + @include m('save'){ + height: getCssVar('markdown', 'height-manual-toolbar-height'); + padding: getCssVar('markdown', 'spacing-manual-toolbar-item-padding'); + line-height: getCssVar('markdown', 'height-manual-toolbar-height'); + color: getCssVar('markdown', 'color-manual-toolbar-text-save'); + text-align: center; + cursor: pointer; + background-color:getCssVar('markdown', 'color-manual-toolbar-bg-save'); + border-radius: getCssVar('markdown', 'border-radius-manual-toolbar-item'); + } + @include m('cancel'){ + color: getCssVar('markdown', 'color-manual-toolbar-text-cancel'); + cursor: pointer; + + &:hover{ + color: getCssVar('markdown', 'color-manual-toolbar-text-cancel-hover'); + } + } + @include when('fullscreen'){ + position: fixed; + right: 0; + bottom: 0; + left: 0; + z-index: 999; + width: 100%; + height: calc(getCssVar('markdown', 'spacing-manual-toolbar-fullscreen-height') * 2); + padding: getCssVar('markdown', 'spacing-manual-toolbar-fullscreen-padding'); + margin-top: 0; + background-color: var(--ibiz-view-bg-color); + border-top: getCssVar('markdown', 'border-manual-toolbar-fullscreen-footer'); + & + .ibiz-markdown-cherry .cherry.fullscreen{ + height: calc(100% - #{getCssVar('markdown', 'spacing-manual-toolbar-fullscreen-height')} * 2); + } + } + } + @include b(markdown-cherry) { width: getCssVar('markdown', 'width'); .cherry { @@ -57,6 +147,19 @@ $markdown: ( } } + @include when(manual){ + display: flex; + flex-direction: column; + .#{bem(markdown-cherry)}{ + flex-grow: 1; + height: calc(100% - #{getCssVar('markdown', 'spacing-manual-toolbar-height')})!important; + } + + @include when(editing){ + flex-direction: column-reverse; + } + } + .cherry-preview--full { border-left: none; } @@ -76,4 +179,8 @@ $markdown: ( display: none; } } + + .cherry.fullscreen{ + z-index: 999; + } } \ No newline at end of file diff --git a/src/editor/markdown/ibiz-markdown-editor/ibiz-markdown-editor.tsx b/src/editor/markdown/ibiz-markdown-editor/ibiz-markdown-editor.tsx index 1784ef4eb..4185f9204 100644 --- a/src/editor/markdown/ibiz-markdown-editor/ibiz-markdown-editor.tsx +++ b/src/editor/markdown/ibiz-markdown-editor/ibiz-markdown-editor.tsx @@ -66,6 +66,17 @@ const IBizMarkDown: any = defineComponent({ const { UIStore } = useUIStore(); const theme = ref(customTheme || UIStore.theme); + // 是否正在编辑中 + const isEditing = ref(false); + + // 显示模式 + let enableedit: 'default' | 'manual' = 'default'; + if (c.editorParams?.enableedit) { + enableedit = c.editorParams.enableedit; + } + // 是否进入全屏 + const isFullScreen = ref(false); + // 编辑器模式 const defaultModel = ref('editOnly'); @@ -172,6 +183,7 @@ const IBizMarkDown: any = defineComponent({ // 设置markdown内容 const setCherryContent = (val: string) => { isIgnoreChange = true; + // 第二个参数传true时,能保持当前的光标位置,默认他是false editor?.setMarkdown(val, true); }; @@ -198,6 +210,9 @@ const IBizMarkDown: any = defineComponent({ // 变更事件回调 const afterChange = (_e: string) => { + if (enableedit === 'manual') { + return; + } emit('change', getCherryContent(), c?.model.id, isIgnoreChange); isIgnoreChange = false; }; @@ -286,8 +301,10 @@ const IBizMarkDown: any = defineComponent({ if (editor && markDownBox.value) { if (isFullscreen()) { closeFullscreen(); + isFullScreen.value = false; } else { openFullscreen(); + isFullScreen.value = true; } } }; @@ -304,7 +321,7 @@ const IBizMarkDown: any = defineComponent({ }; const editorInit = () => { - if (props.disabled || props.readonly) { + if (props.disabled || props.readonly || enableedit === 'manual') { defaultModel.value = 'previewOnly'; } nextTick(() => { @@ -483,6 +500,85 @@ const IBizMarkDown: any = defineComponent({ } }; + // 切换编辑 + const onEnableEdit = () => { + isEditing.value = true; + defaultModel.value = 'editOnly'; + editor?.switchModel(defaultModel.value); + }; + + // 重置编辑状态 + const onResetEditState = () => { + isEditing.value = false; + defaultModel.value = 'previewOnly'; + editor?.switchModel(defaultModel.value); + }; + + // 取消编辑 + const onEditCancel = () => { + // 直接重置值 + setCherryContent(currentVal.value); + onResetEditState(); + }; + + // 确认编辑 + const onEditConfirm = () => { + emit('change', getCherryContent(), c?.model.id, isIgnoreChange); + isIgnoreChange = false; + onResetEditState(); + }; + + // 绘制头部额外工具栏 + const renderHeader = () => { + if (enableedit === 'manual' && !isEditing.value) { + return ( +
+ {!props.disabled && !props.readonly && ( +
+ +
+ )} +
+ +
+
+ ); + } + }; + + // 绘制编辑态的确认取消按钮 + const renderFooter = () => { + if ( + enableedit === 'manual' && + isEditing.value && + !props.disabled && + !props.readonly + ) { + return ( +
+
+ {ibiz.i18n.t('editor.common.cancel')} +
+
+ {ibiz.i18n.t('editor.common.confirm')} +
+
+ ); + } + }; + onMounted(() => { editorInit(); calcMarkDownStyle(); @@ -513,17 +609,28 @@ const IBizMarkDown: any = defineComponent({ theme, defaultModel, cssVars, + isEditing, + enableedit, getCherryHtml, getCherryContent, setCherryContent, + renderHeader, + renderFooter, }; }, render() { return (
+ {this.renderHeader()} + {this.renderFooter()}