feat(editor): 新增,编辑代码块完成

This commit is contained in:
parisma 2022-09-07 14:45:38 +08:00 committed by jia000
parent f1242ee3f4
commit 2a8cfe58c4
5 changed files with 141 additions and 80 deletions

View File

@ -1,6 +1,6 @@
<template>
<el-dialog v-model="state.isShowCodeBlockEditor" title="代码块编辑面板" :fullscreen="true">
<div ref="codeBlockEditor" class="m-editor-code-block-editor-panel">
<div class="m-editor-code-block-editor-panel">
<el-row class="code-name-wrapper" justify="start">
<el-col :span="2">
<span>代码块名称</span>
@ -31,63 +31,56 @@
</template>
<script lang="ts" setup>
import { inject, ref, watchEffect } from 'vue';
import { defineEmits, defineProps, inject, ref } from 'vue';
import { ElMessage } from 'element-plus';
import type { Services } from '../../../type';
import type { Services, State } from '../../../type';
import useCodeBlock from './useCodeBlock';
const { state, closePanel } = useCodeBlock();
const codeBlockEditor = ref<HTMLElement | null>(null);
const codeEditor = ref<any | null>(null);
const services = inject<Services>('services');
const props = defineProps<{
state: State;
}>();
watchEffect(() => {
if (state.isShowCodeBlockEditor) {
if (!codeBlockEditor.value) {
return;
}
}
});
const emit = defineEmits(['close']);
//
const saveAndClose = () => {
saveCode();
closePanel();
emit('close');
};
//
const saveCode = () => {
if (!codeEditor.value || !state.codeConfig) return;
if (!codeEditor.value || !props.state.codeConfig) return;
try {
const codeContent = codeEditor.value.getEditor().getValue();
/* eslint no-eval: "off" */
state.codeConfig.content = eval(codeContent);
const { id, ...codeConfig } = state.codeConfig;
const { editorService } = services || {};
if (!editorService) return;
const root = editorService.get('root');
// idkey
let codeBlockList = root?.method || {};
codeBlockList = {
...codeBlockList,
...{
[state.codeConfig.id]: codeConfig,
},
};
// dsl
editorService.set('root', {
...root,
method: codeBlockList,
});
ElMessage.success('代码保存成功');
props.state.codeConfig.content = eval(codeContent);
} catch (e: any) {
ElMessage.error(e.stack);
}
const { id, ...codeConfig } = props.state.codeConfig;
const { editorService } = services || {};
if (!editorService) return;
const root = editorService.get('root');
// idkey
let codeBlockMap = root?.method || {};
codeBlockMap = {
...codeBlockMap,
...{
[props.state.codeConfig.id]: codeConfig,
},
};
// dsl
editorService.set('root', {
...root,
method: codeBlockMap,
});
ElMessage.success('代码保存成功');
};
</script>

View File

@ -7,15 +7,78 @@
<el-divider class="divider" />
<!-- 代码块列表 -->
<div class="list-container"></div>
<div class="list-container" v-if="state.codeBlockMap">
<div v-for="(value, key) in state.codeBlockMap" :key="key">
<div class="list-item">
<div class="code-name">{{ value.name }}{{ key }}</div>
<el-tooltip class="box-item" effect="dark" content="编辑代码" placement="top">
<el-icon class="edit-icon" @click="editCode(key)"><EditPen /></el-icon>
</el-tooltip>
</div>
</div>
</div>
<!-- 代码块编辑区 -->
<code-block-editor />
<code-block-editor :state="state" @close="closePanel"></code-block-editor>
</div>
</template>
<script lang="ts" setup>
import { inject, reactive, watchEffect } from 'vue';
import { EditPen } from '@element-plus/icons-vue';
import type { CodeBlockConfig, Services, State } from '../../../type';
import codeBlockEditor from './CodeBlockEditor.vue';
import useCodeBlock from './useCodeBlock';
const { createCodeBlock } = useCodeBlock();
const state = reactive<State>({
isShowCodeBlockEditor: false,
codeConfig: null,
codeBlockMap: null,
});
const services = inject<Services>('services');
//
const createCodeBlock = () => {
const config: CodeBlockConfig = {
id: getUniqueId(),
name: '代码块',
content: `(app) => {\n // place your code here\n}`,
};
showCodeEditor(config);
};
//
const showCodeEditor = (config: CodeBlockConfig) => {
state.codeConfig = config;
showPanel();
};
//
const showPanel = () => (state.isShowCodeBlockEditor = true);
//
const closePanel = () => (state.isShowCodeBlockEditor = false);
// id
const getUniqueId = () => (Date.now().toString(36) + Math.random().toString(36).substring(2)).padEnd(19, '0');
//
const editCode = (key: string) => {
if (!state.codeBlockMap) return;
// Id
const currentCode = state.codeBlockMap[key];
const config: CodeBlockConfig = {
id: key,
...currentCode,
};
showCodeEditor(config);
};
watchEffect(() => {
const { editorService } = services || {};
if (!editorService) return;
const root = editorService.get('root');
state.codeBlockMap = root?.method || null;
});
</script>

View File

@ -1,37 +0,0 @@
import { reactive } from 'vue';
import { CodeBlockConfig } from '../../../type';
interface State {
/** 是否展示代码块编辑区 */
isShowCodeBlockEditor: boolean;
/** 代码块配置 */
codeConfig: CodeBlockConfig | null;
}
const state = reactive<State>({
isShowCodeBlockEditor: false,
codeConfig: null,
});
const getUniqueId = () => Date.now().toString(36) + Math.random().toString(36).substring(2);
// 关闭代码块面板
const closePanel = () => (state.isShowCodeBlockEditor = false);
// 新增代码块
const createCodeBlock = () => {
// todo 如果已有代码块打开,需要先保存关闭
closePanel();
state.isShowCodeBlockEditor = true;
state.codeConfig = {
id: getUniqueId(),
name: '代码块',
content: `(app) => {\n // place your code here\n}`,
};
};
export default () => ({
state,
closePanel,
createCodeBlock,
});

View File

@ -7,7 +7,30 @@
}
.divider {
margin: 20px 0;
margin: 10px 0 0 0;
}
.list-container {
width: 100%;
overflow: hidden;
.list-item {
display: flex;
align-items: center;
.edit-icon {
position: absolute;
right: 15px;
padding-left: 5px;
background-color: #fff;
}
.code-name {
font-size: 14px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
padding: 10px 15px;
margin-right: 15px;
}
}
}
}
.m-editor-code-block-editor-panel {

View File

@ -314,3 +314,22 @@ export interface CodeBlockConfig {
/** 代码块内容 */
content: string;
}
export interface CodeBlockMap {
[id: string]: CodeBlockContent;
}
export interface CodeBlockContent {
/** 代码块名称 */
name: string;
/** 代码块内容 */
content: string;
}
export type State = {
/** 是否展示代码块编辑区 */
isShowCodeBlockEditor: boolean;
/** 代码块配置 */
codeConfig: CodeBlockConfig | null;
/** 代码块列表 */
codeBlockMap: CodeBlockMap | null;
};