提交 d1aa468a 编写于 作者: zhujiamin's avatar zhujiamin

update:支持代码编辑器

上级 61e5b9fc
<IbizCode
name="{{item.codeName}}"
{{#if item.psEditor.isReadOnly}}
:readonly="{{item.psEditor.isReadOnly}}"
{{/if}}
{{#if (or (eq ctrlType 'form') (eq ctrlType 'panel'))}}
:value="state.data.{{item.psEditor.name}}"
@editorEvent="handleEditorEvent"
{{/if}}
{{#eq ctrlType 'grid'}}
:value="record.{{item.psEditor.name}}"
@editorEvent="($event) => handleEditorEvent(index,$event)"
{{/eq}}
:context="state.context"
:viewParams="state.viewParams"/>
\ No newline at end of file
......@@ -48,4 +48,5 @@
{{#*inline "PICTURE_ONE"}}{{>@macro/front-end/editors/upload.hbs}}{{/inline}}
{{#*inline "PICKUPVIEW"}}{{>@macro/front-end/editors/data-picker-view.hbs}}{{/inline}}
{{#*inline "PICKEREX_DROPDOWNVIEW"}}{{>@macro/front-end/editors/data-picker-view.hbs}}{{/inline}}
{{#*inline "PICKEREX_DROPDOWNVIEW_LINK"}}{{>@macro/front-end/editors/data-picker-view.hbs}}{{/inline}}
\ No newline at end of file
{{#*inline "PICKEREX_DROPDOWNVIEW_LINK"}}{{>@macro/front-end/editors/data-picker-view.hbs}}{{/inline}}
{{#*inline "CODE"}}{{>@macro/front-end/editors/code.hbs}}{{/inline}}
\ No newline at end of file
......@@ -8,7 +8,9 @@
},
"dependencies": {
"@ant-design/icons-vue": "^6.0.1",
"@popperjs/core": "^2.9.2",
"@popperjs/core": "^2.9.2",
"monaco-editor": "^0.24.0",
"vite-plugin-monaco-editor":"^1.0.10",
"ant-design-vue": "^3.0.0-alpha.14",
"axios": "^0.24.0",
"element-plus": "^1.2.0-beta.6",
......
<script setup lang="ts">
import * as monaco from 'monaco-editor';
import 'monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution';
import 'monaco-editor/esm/vs/editor/contrib/find/findController.js';
import { IParam, EditorBase, IContext, IActionParam } from '@core';
import { getCurrentInstance, onBeforeMount, onMounted, ref, Ref, watch } from 'vue';
import { FullscreenOutlined, FullscreenExitOutlined } from '@ant-design/icons-vue';
interface IToolbarItem {
key: string; //标识
text: string; //文本值
component: any; //组件
visible: boolean; //显示状态
}
interface CodeProps {
/**
* @description 编辑器名称
*/
name: string;
/**
* 当前值
*
* @type {*}
* @memberof AppCodeEditor
*/
value: string;
/**
* 主题
*
* @type {string}
* @memberof AppCodeEditor
*/
theme: 'vs-light' | 'vs-dark';
/**
* 语言
*
* @type {string}
* @memberof AppCodeEditor
*/
language: 'json' | 'javascript' | 'typescript' | 'css' | 'less' | 'sass' | 'java';
/**
* 只读模式
*
* @type {boolean}
* @memberof AppCodeEditor
*/
readonly: boolean;
/**
* 是否显示小地图
*
* @type {boolean}
* @memberof AppCodeEditor
*/
isMinimap: boolean;
/**
* 是否能够更换语言
*
* @type {boolean}
* @memberof AppCodeEditor
*/
isChangeLanguage: boolean;
}
const props = withDefaults(defineProps<CodeProps>(), {
value: '',
theme: 'vs-light',
language: 'typescript',
readonly: false,
isMinimap: true,
isChangeLanguage: true,
});
interface EditorEmit {
(name: 'editorEvent', value: IActionParam): void;
}
const emit = defineEmits<EditorEmit>();
/**
* 代码编辑器对象
*
* @type {*}
* @memberof AppCodeEditor
*/
let codeEditor: any;
// 当前使用语言
let presentLanguage: Ref<string> = ref('');
// 语言列表
let languages: string[] = ['json', 'javascript', 'typescript', 'css', 'less', 'sass', 'java', 'sql'];
// 右侧工具栏项
let rightToolbarItems: Ref<IToolbarItem[]> = ref([
{
key: 'fullScreen',
text: '全屏',
component: 'full-screen',
visible: true,
},
{
key: 'quitFullScreen',
text: '退出全屏',
component: 'exit-full-screen',
visible: false,
},
]);
/**
* 绘制图标
*
* @param {string} type
* @return {*}
* @memberof AppCodeEditor
*/
const renderIcon = (type: string) => {
return `<a-icon type="step-backward" />`;
};
onBeforeMount(() => {
presentLanguage.value = props.language;
});
onMounted(() => {
initCodeEditor();
watch(
() => props.value,
(newVal: any, oldVal: any) => {
codeEditor.setValue(newVal);
},
);
});
onBeforeMount(() => {
window.removeEventListener('resize', resize);
});
// 通过ref属性获取编辑器元素
const codeEditorRef = ref(null);
/**
* 初始化编辑器
*
* @memberof AppCodeEditor
*/
const initCodeEditor = () => {
if (codeEditorRef.value) {
codeEditor = monaco.editor.create(codeEditorRef.value, {
value: props.value,
theme: props.theme,
language: presentLanguage.value,
readOnly: props.readonly,
minimap: { enabled: props.isMinimap },
});
registerEvent();
window.addEventListener('resize', resize);
window.addEventListener('fullscreenchange', fullscreenchange);
}
};
/**
* 初始化编辑器大小
*
* @memberof AppCodeEditor
*/
const resize = () => {
codeEditor.layout();
};
/**
* 全屏变化
*
* @memberof AppCodeEditor
*/
const fullscreenchange = () => {
if (document.fullscreenElement) {
const toolbarItem: any = rightToolbarItems.value.find(toolbarItem => toolbarItem.key === 'fullScreen');
toolbarItem.visible = false;
const item: any = rightToolbarItems.value.find(toolbarItem => toolbarItem.key === 'quitFullScreen');
item.visible = true;
} else {
const toolbarItem: any = rightToolbarItems.value.find(toolbarItem => toolbarItem.key === 'quitFullScreen');
toolbarItem.visible = false;
const item: any = rightToolbarItems.value.find(toolbarItem => toolbarItem.key === 'fullScreen');
item.visible = true;
}
};
/**
*注册事件
*
* @memberof AppCodeEditor
*/
const registerEvent = () => {
if (!props.readonly) {
codeEditor.onDidBlurEditorText(
//数据发生改变
(event: any) => {
emit('editorEvent', { tag: props.name, action: 'valueChange', data: codeEditor.getValue() });
},
);
}
};
/**
* 工具栏点击项
*
* @param {IToolbarItem} toolbarItem
* @memberof AppCodeEditor
*/
const toolBarClick = (toolbarItem: IToolbarItem) => {
if (toolbarItem.key === 'fullScreen') {
const editorContainer = document.getElementsByClassName('app-code-editor')[0];
editorContainer.requestFullscreen();
}
if (toolbarItem.key === 'quitFullScreen') {
document.exitFullscreen();
}
};
/**
* 切换语言
*
* @param {string} item
* @memberof AppCodeEditor
*/
const onLanguageChange = (item: string) => {
codeEditor.dispose();
initCodeEditor();
codeEditor.trigger('anyString', 'editor.action.formatDocument');
};
</script>
<template>
<div class='app-code-editor'>
<div :class="{toolbar: true, [theme]: true}">
<div class="left-toolbar">
<a-select
ref="select"
v-model:value="presentLanguage"
style="width: 110px"
:disabled="!isChangeLanguage"
:bordered="false"
@change="onLanguageChange"
>
<a-select-option
:value="language"
v-for="(language,index) in languages"
:key="index"
>{{language}}</a-select-option>
</a-select>
</div>
<div class="right-toolbar">
<template
v-for="(toolbarItem) in rightToolbarItems"
:key="toolbarItem.key"
>
<div
class='toolbar-item'
v-if="toolbarItem.visible"
:title="toolbarItem.text"
@click="toolBarClick(toolbarItem)"
>
<fullscreen-outlined v-if="toolbarItem.key == 'fullScreen'"/>
<fullscreen-exit-outlined v-if="toolbarItem.key == 'quitFullScreen'"/>
</div>
</template>
</div>
</div>
<div
class='code-editor-wrapper'
ref='codeEditorRef'
></div>
</div>
</template>
<style lang='scss'>
.app-code-editor {
width: 100%;
height: 100%;
min-width: 300px;
min-height: 300px;
position: relative;
overflow: hidden;
box-shadow: rgba(0, 0, 0, 0.1) 0px 2px 12px 0px;
border-radius: 4px;
> .toolbar {
padding: 5px 15px;
display: flex;
align-items: center;
z-index: 1;
font-size: 12px;
font-weight: 800;
justify-content: space-between;
> .left-toolbar,
.right-toolbar {
> .toolbar-item {
cursor: pointer;
padding: 3px;
color: rgb(157, 165, 180);
display: flex;
align-items: center;
justify-content: center;
border-radius: 2px;
}
> .toolbar-item:hover {
background-color: rgba(106, 108, 109, 0.31);
}
}
> .toolbar.vs-dark {
background-color: rgb(33, 37, 43);
}
.code-editor-wrapper {
min-height: 278px;
height: calc(100% - 22px);
width: 100%;
.monaco-editor .view-line {
text-align: left;
}
}
}
</style>
\ No newline at end of file
......@@ -7,6 +7,9 @@ import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
// 代码编辑器 代码提示插件
import monacoEditorPlugin from "vite-plugin-monaco-editor";
// https://vitejs.dev/config/
export default defineConfig({
resolve: {
......@@ -32,5 +35,6 @@ export default defineConfig({
dts: true,
resolvers: [ElementPlusResolver()],
}),
monacoEditorPlugin(),
],
});
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册