From 0e9a61079e88e419e8dd86f633acc60314c6d552 Mon Sep 17 00:00:00 2001 From: lijisanxiong <1518062161@qq.com> Date: Thu, 20 Nov 2025 16:24:24 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat=EF=BC=9A=E6=96=B0=E5=A2=9E=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=BC=96=E8=BE=91=E8=8E=B7=E5=8F=96=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E5=99=A8=E5=85=83=E7=B4=A0=E5=8F=8A=E4=B8=BB=E9=A2=98=E6=96=B9?= =?UTF-8?q?=E6=B3=95=EF=BC=8C=E5=B9=B6=E6=9B=B4=E6=96=B0=E8=AE=A1=E7=AE=97?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/editor/code/code-editor.controller.ts | 34 +++++++++++++++++-- .../code/monaco-editor/monaco-editor.tsx | 4 +++ src/locale/en/index.ts | 1 + src/locale/zh-CN/index.ts | 1 + 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/editor/code/code-editor.controller.ts b/src/editor/code/code-editor.controller.ts index b6b32d5e8..7af908aae 100644 --- a/src/editor/code/code-editor.controller.ts +++ b/src/editor/code/code-editor.controller.ts @@ -225,6 +225,31 @@ export class CodeEditorController this.editor?.focus(); } + /** + * 获取内联AI编辑器元素 + */ + getInLineAiEditorElement(): Element { + if (!this.editor) { + throw new RuntimeError(ibiz.i18n.t('editor.code.editorNotInit')); + } + return this.editor.getDomNode() as Element; + } + + /** + * 获取内联AI编辑器主题 + */ + getInLineAiEditorTheme(): 'light' | 'dark' { + const currentTheme = (this.editor as IParams)?._themeService?._theme + ?.themeName; + switch (currentTheme) { + case 'vs-dark': + return 'dark'; + case 'vs': + default: + return 'light'; + } + } + /** * 获取内联AI聊天参数 */ @@ -253,9 +278,14 @@ export class CodeEditorController const rect = contentArea.getBoundingClientRect(); return { + // 编辑器编辑区左侧距离 left: rect.left, - top: editorRect.top + coordinates.top + 28, // 减去 20px 的行高度及 8px 向下偏移 - width: rect.width - 160, // 减去 左侧占位 及 右侧代码预览 边距 + // 编辑器上方距离 + 选区距离编辑器上方距离 + 20px行高度 + 8px 向下偏移 + top: editorRect.top + coordinates.top + 28, + // 编辑器编辑区宽度 - 120px代码预览区宽度 - 40px边距 + width: rect.width - 160, + editorElement: this.getInLineAiEditorElement(), + editorTheme: this.getInLineAiEditorTheme(), }; } diff --git a/src/editor/code/monaco-editor/monaco-editor.tsx b/src/editor/code/monaco-editor/monaco-editor.tsx index 834418071..20bac227d 100644 --- a/src/editor/code/monaco-editor/monaco-editor.tsx +++ b/src/editor/code/monaco-editor/monaco-editor.tsx @@ -506,9 +506,11 @@ export const IBizCode = defineComponent({ textTBStyle.value = { ...textTBStyle.value, + // 编辑器左侧距离 + 选区距离编辑器左侧距离 [ns.cssVarBlockName('text-editor-toolbar-left')]: `${ editorRect.left + coordinates.left }px`, + // 编辑器上方距离 + 选区距离编辑器上方距离 + 20px行高度 + 8px 向下偏移 [ns.cssVarBlockName('text-editor-toolbar-top')]: `${ editorRect.top + coordinates.top + 28 }px`, @@ -549,7 +551,9 @@ export const IBizCode = defineComponent({ ); if (items.length === 0) return; ibiz.inLineAIUtil.showContextMenus( + // 编辑器左侧距离 + 选区距离编辑器左侧距离 editorRect.left + coordinates.left, + // 编辑器上方距离 + 选区距离编辑器上方距离 + 20px行高度 + 8px 向下偏移 + 40px工具栏高度 editorRect.top + coordinates.top + 28 + 40, items, ); diff --git a/src/locale/en/index.ts b/src/locale/en/index.ts index 1c85a4d5a..14e618269 100644 --- a/src/locale/en/index.ts +++ b/src/locale/en/index.ts @@ -670,6 +670,7 @@ export default { noSelStart: 'No start position of current selection', noEditorRect: 'No editor DOM node position info', noSelCoords: 'No scroll coordinates of selection', + editorNotInit: 'Editor not initialized', }, dateRange: { rangeSeparator: 'To', diff --git a/src/locale/zh-CN/index.ts b/src/locale/zh-CN/index.ts index e0d52c43d..a21e78629 100644 --- a/src/locale/zh-CN/index.ts +++ b/src/locale/zh-CN/index.ts @@ -626,6 +626,7 @@ export default { noSelStart: '未获取到当前选中区域的起始位置', noEditorRect: '未获取到编辑器DOM节点的位置信息', noSelCoords: '未计算出选中位置的滚动可视坐标', + editorNotInit: '编辑器未初始化', }, dateRange: { rangeSeparator: '至', -- Gitee From ebd9b8c692b3d1e5c41889c4213e7df7e6573c2e Mon Sep 17 00:00:00 2001 From: lijisanxiong <1518062161@qq.com> Date: Thu, 20 Nov 2025 16:28:21 +0800 Subject: [PATCH 2/5] =?UTF-8?q?feat=EF=BC=9A=E4=BC=98=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=BC=96=E8=BE=91=E5=99=A8=E6=8F=92=E5=85=A5=E6=96=87?= =?UTF-8?q?=E6=9C=AC=E6=96=B9=E6=B3=95=EF=BC=8C=E5=B0=86=E6=96=87=E6=9C=AC?= =?UTF-8?q?=E4=BB=A5=E6=AE=B5=E8=90=BD=E7=9A=84=E6=A0=BC=E5=BC=8F=E6=8F=92?= =?UTF-8?q?=E5=85=A5=E5=88=B0=E5=85=89=E6=A0=87=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/editor/code/code-editor.controller.ts | 50 ++++++++++++++--------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/src/editor/code/code-editor.controller.ts b/src/editor/code/code-editor.controller.ts index 7af908aae..bcc8df750 100644 --- a/src/editor/code/code-editor.controller.ts +++ b/src/editor/code/code-editor.controller.ts @@ -129,36 +129,46 @@ export class CodeEditorController * @param {string} text 文本 */ insertText(text: string): void { - const model = this.editor?.getModel(); - if (!model || !this.monaco) return; + if (!this.editor || !this.monaco) { + throw new RuntimeError(ibiz.i18n.t('editor.code.editorNotInit')); + } + + // 取选中结束位置作为插入点 + const selections = this.editor!.getSelections(); + // 无光标时不执行插入 + if (!selections || selections.length === 0) return; + + const activeSelection = selections[selections.length - 1]; + const insertLine = activeSelection.positionLineNumber; // 活跃光标的行号 + const insertColumn = activeSelection.positionColumn; // 活跃光标的列号 - const lastLineNumber = model.getLineCount(); - const lastLineContent = model.getLineContent(lastLineNumber); - const lastColumn = lastLineContent.length + 1; + // 以段落的方式插入文本 + const formattedText = `\n${text}\n`; // 执行插入操作 this.editor?.executeEdits('', [ { range: new this.monaco!.Range( - lastLineNumber, - lastColumn, - lastLineNumber, - lastColumn, + insertLine, + insertColumn, + insertLine, + insertColumn, // 光标位置纯插入,不替换任何内容 ), - text, + text: formattedText, }, ]); - // 计算插入后光标的新位置(在新增文本的末尾) - const newLastLine = lastLineNumber + (text.includes('\n') ? 1 : 0); // 若插入换行,行号+1 - const newLastColumn = text.split('\n').pop()?.length || 0; - - this.editor?.setPosition( - new this.monaco!.Position(newLastLine, newLastColumn), - ); - this.editor?.revealPositionInCenter( - new this.monaco!.Position(newLastLine, newLastColumn), - ); + // 计算插入后光标的新位置(停留在插入文本末尾,换行符之前) + const linesInText = formattedText.split('\n'); + const linesAdded = linesInText.length - 1; // 前后换行 + 文本内换行 = 总新增行数 + const lastLineOfInsert = insertLine + linesAdded - 1; // 排除末尾的换行符所在行 + const lastLineContent = linesInText[linesInText.length - 2] || ''; // 取文本最后一行(排除末尾换行) + const newColumn = lastLineContent.length; + + // 更新光标位置并聚焦 + const newPosition = new this.monaco!.Position(lastLineOfInsert, newColumn); + this.editor?.setPosition(newPosition); + this.editor?.revealPositionInCenter(newPosition); this.editor?.focus(); } -- Gitee From 1a54c3ff751159f863efcf336ed9d2eb1040252e Mon Sep 17 00:00:00 2001 From: lijisanxiong <1518062161@qq.com> Date: Thu, 20 Nov 2025 16:30:00 +0800 Subject: [PATCH 3/5] =?UTF-8?q?feat=EF=BC=9A=E4=BC=98=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=BC=96=E8=BE=91=E5=99=A8=E6=A0=B7=E5=BC=8F=EF=BC=8C?= =?UTF-8?q?=E9=80=82=E9=85=8D=E7=BC=96=E8=BE=91=E5=99=A8=E7=9A=84dark?= =?UTF-8?q?=E4=B8=BB=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../code/monaco-editor/monaco-editor.scss | 46 +++++++++++++------ .../code/monaco-editor/monaco-editor.tsx | 8 ++++ 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/src/editor/code/monaco-editor/monaco-editor.scss b/src/editor/code/monaco-editor/monaco-editor.scss index 951a8da2c..8a2bd6289 100644 --- a/src/editor/code/monaco-editor/monaco-editor.scss +++ b/src/editor/code/monaco-editor/monaco-editor.scss @@ -1,9 +1,22 @@ +/* stylelint-disable color-function-notation */ +/* stylelint-disable alpha-value-notation */ /* stylelint-disable selector-class-pattern */ $code: ( + // Color + 'color-text-editor-toolbar-bg': getCssVar(color, bg, 2), + 'color-text-editor-toolbar-text': getCssVar(color, text, 0), + 'color-text-editor-toolbar-item-bg-hover': getCssVar(color, primary, light, default), + 'color-text-editor-toolbar-item-text-hover': getCssVar(color, primary), // Height/Width 'height-text-editor-toolbar': 40px, 'footer-toolbar-height': 36px, 'footer-button-height': 36px, + // Spacing + 'spacing-code-text-editor-toolbar-padding': getCssVar('spacing', 'extra-tight'), + 'spacing-code-text-editor-toolbar-item-padding': getCssVar('spacing', 'extra-tight') getCssVar('spacing', 'tight'), + // Radius + 'spacing-code-text-editor-toolbar-circle': getCssVar('border-radius', 'extra-small'), + 'spacing-code-text-editor-toolbar-item-circle': getCssVar('border-radius', 'extra-small'), // Other 'text-editor-toolbar-z-index': 1, 'text-editor-toolbar-left': 0, @@ -11,6 +24,8 @@ $code: ( ); @include b(code) { + @include set-component-css-var('code', $code); + display: flex; flex-direction: column; width: 100%; @@ -62,8 +77,6 @@ $code: ( } @include b('code-footer') { - @include set-component-css-var('code', $code); - display: flex; align-items: center; justify-content: end; @@ -136,9 +149,6 @@ $code: ( } @include b('code-editor-enable') { - - @include set-component-css-var('code', $code); - .#{bem(code__box)} { height: 100%; } @@ -191,8 +201,6 @@ $code: ( } @include b('code-text-editor-toolbar') { - @include set-component-css-var('code', $code); - position: fixed; top: getCssVar('code', 'text-editor-toolbar-top'); left: getCssVar('code', 'text-editor-toolbar-left'); @@ -200,23 +208,33 @@ $code: ( display: flex; gap: getCssVar('spacing', 'tight'); height: getCssVar('code', 'height-text-editor-toolbar'); - padding: getCssVar('spacing', 'extra-tight'); + padding: getCssVar('code', 'spacing-code-text-editor-toolbar-padding'); font-size: getCssVar('font-size', 'regular'); - background-color: getCssVar(color, bg, 2); - border-radius: getCssVar('border-radius', 'extra-small'); + color: getCssVar('code', 'color-text-editor-toolbar-text'); + background-color: getCssVar('code', 'color-text-editor-toolbar-bg'); + border-radius: getCssVar('code', 'spacing-code-text-editor-toolbar-circle'); box-shadow: getCssVar(shadow, elevated); @include e('item') { display: flex; align-items: center; justify-content: center; - padding: getCssVar('spacing', 'extra-tight') getCssVar('spacing', 'tight'); + padding: getCssVar('code', 'spacing-code-text-editor-toolbar-item-padding'); cursor: pointer; - border-radius: getCssVar('border-radius', 'extra-small'); + border-radius: getCssVar('code', 'spacing-code-text-editor-toolbar-item-circle'); &:hover { - color: getCssVar(color, primary); - background-color: getCssVar(color, primary, light, default); + color: getCssVar('code', 'color-text-editor-toolbar-item-text-hover'); + background-color: getCssVar('code', 'color-text-editor-toolbar-item-bg-hover'); } } +} + +@include b(code) { + @include when('dark') { + #{getCssVarName('code-color-text-editor-toolbar-bg')}: rgba(53 54 60 / 100%); + #{getCssVarName('code-color-text-editor-toolbar-text')}: rgba(249, 249, 249, 1); + #{getCssVarName('code-color-text-editor-toolbar-item-bg-hover')}: rgba(255, 255, 255, 0.12); + #{getCssVarName('code-color-text-editor-toolbar-item-text-hover')}: rgba(249, 249, 249, 1); + } } \ No newline at end of file diff --git a/src/editor/code/monaco-editor/monaco-editor.tsx b/src/editor/code/monaco-editor/monaco-editor.tsx index 20bac227d..07cb58c7e 100644 --- a/src/editor/code/monaco-editor/monaco-editor.tsx +++ b/src/editor/code/monaco-editor/monaco-editor.tsx @@ -97,6 +97,9 @@ export const IBizCode = defineComponent({ // 文本编辑工具栏可见状态 const textTBVisible = ref(false); + // 当前编辑器主题 + const editorTheme = ref(''); + const editorModel = c.model; if (editorModel.editorParams) { if (editorModel.editorParams.enableEdit) { @@ -144,6 +147,8 @@ export const IBizCode = defineComponent({ // 编辑器主题 const getMonacoTheme = (name: string): string => { + editorTheme.value = + c?.editorParams?.customTheme || ibiz.config.codeEditorTheme || name; // customTheme参数已弃用,后续请使用全局参数codeEditorTheme const customTheme = c?.editorParams?.customTheme; if (customTheme) { @@ -902,6 +907,7 @@ export const IBizCode = defineComponent({ readonlyState, isLoading, textTBRef, + editorTheme, renderFooter, renderHeaderToolbar, renderTextEditorToolbar, @@ -915,6 +921,7 @@ export const IBizCode = defineComponent({
Date: Thu, 20 Nov 2025 16:30:29 +0800 Subject: [PATCH 4/5] =?UTF-8?q?feat=EF=BC=9A=E6=9B=B4=E6=96=B0CHANGELOG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82fd2fdcd..13d435c81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,15 @@ ## [Unreleased] +### Added + +- 新增代码编辑器获取编辑器元素及主题方法,并更新位置计算逻辑的注释 + +### Changed + +- 优化代码编辑器插入文本方法,将文本以段落的格式插入到光标位置 +- 优化代码编辑器样式,适配编辑器的dark主题 + ## [0.7.41-alpha.38] - 2025-11-19 ### Added -- Gitee From 3ab7dafa3ae01f8ed1e1f138174c7025d4dd823a Mon Sep 17 00:00:00 2001 From: lijisanxiong <1518062161@qq.com> Date: Thu, 20 Nov 2025 17:55:22 +0800 Subject: [PATCH 5/5] =?UTF-8?q?feat=EF=BC=9A=E8=B0=83=E6=95=B4=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=BC=96=E8=BE=91=E5=99=A8=E5=AE=9A=E4=BD=8D=E5=80=BC?= =?UTF-8?q?=E4=B8=BA=E5=8A=A8=E6=80=81=E8=8E=B7=E5=8F=96=E5=8F=8A=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E5=85=B6=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/editor/code/code-editor.controller.ts | 16 ++++++++++++---- src/editor/code/monaco-editor/monaco-editor.tsx | 11 ++++++----- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/editor/code/code-editor.controller.ts b/src/editor/code/code-editor.controller.ts index bcc8df750..1a1ccb549 100644 --- a/src/editor/code/code-editor.controller.ts +++ b/src/editor/code/code-editor.controller.ts @@ -264,6 +264,9 @@ export class CodeEditorController * 获取内联AI聊天参数 */ getInLineAiChatOptions(): IInLineAiChatOptions { + if (!this.editor || !this.monaco) { + throw new RuntimeError(ibiz.i18n.t('editor.code.editorNotInit')); + } const contentArea = this.editor ?.getDomNode() ?.querySelector('.editor-scrollable') as HTMLElement; @@ -286,14 +289,19 @@ export class CodeEditorController } const rect = contentArea.getBoundingClientRect(); + // 编辑器布局信息 + const layoutInfo = this.editor.getLayoutInfo(); return { // 编辑器编辑区左侧距离 left: rect.left, - // 编辑器上方距离 + 选区距离编辑器上方距离 + 20px行高度 + 8px 向下偏移 - top: editorRect.top + coordinates.top + 28, - // 编辑器编辑区宽度 - 120px代码预览区宽度 - 40px边距 - width: rect.width - 160, + // 编辑器上方距离 + 选区距离编辑器上方距离 + 行高度 + top: editorRect.top + coordinates.top + coordinates.height, + // 编辑器编辑区宽度 - 代码预览区宽度 - 代码预览区标尺宽度 + width: + rect.width - + layoutInfo.minimap.minimapWidth - + layoutInfo.overviewRuler.width, editorElement: this.getInLineAiEditorElement(), editorTheme: this.getInLineAiEditorTheme(), }; diff --git a/src/editor/code/monaco-editor/monaco-editor.tsx b/src/editor/code/monaco-editor/monaco-editor.tsx index 07cb58c7e..95da10101 100644 --- a/src/editor/code/monaco-editor/monaco-editor.tsx +++ b/src/editor/code/monaco-editor/monaco-editor.tsx @@ -515,9 +515,9 @@ export const IBizCode = defineComponent({ [ns.cssVarBlockName('text-editor-toolbar-left')]: `${ editorRect.left + coordinates.left }px`, - // 编辑器上方距离 + 选区距离编辑器上方距离 + 20px行高度 + 8px 向下偏移 + // 编辑器上方距离 + 选区距离编辑器上方距离 + 行高度 [ns.cssVarBlockName('text-editor-toolbar-top')]: `${ - editorRect.top + coordinates.top + 28 + editorRect.top + coordinates.top + coordinates.height }px`, }; } @@ -547,7 +547,8 @@ export const IBizCode = defineComponent({ if (!position) return; const coordinates = editor?.getScrolledVisiblePosition(position); const editorRect = editor?.getDomNode()?.getBoundingClientRect(); - if (!coordinates || !editorRect) return; + const textTBHeight = textTBRef.value.offsetHeight; + if (!coordinates || !editorRect || !textTBHeight) return; const items: MenuItem[] = ibiz.inLineAIUtil.calcContextMenus( c.deACMode, (tag: string) => { @@ -558,8 +559,8 @@ export const IBizCode = defineComponent({ ibiz.inLineAIUtil.showContextMenus( // 编辑器左侧距离 + 选区距离编辑器左侧距离 editorRect.left + coordinates.left, - // 编辑器上方距离 + 选区距离编辑器上方距离 + 20px行高度 + 8px 向下偏移 + 40px工具栏高度 - editorRect.top + coordinates.top + 28 + 40, + // 编辑器上方距离 + 选区距离编辑器上方距离 + 行高度 + 工具栏高度 + editorRect.top + coordinates.top + coordinates.height + textTBHeight, items, ); }; -- Gitee