199 lines
4.5 KiB
Vue

<template>
<TMagicCard shadow="never">
<template #header>
<div class="code-name-wrapper">
<div class="code-name-label">代码块名称</div>
<TMagicInput class="code-name-input" v-model="codeName" :disabled="!editable" />
</div>
<div class="code-name-wrapper">
<div class="code-name-label">参数</div>
<m-form-table
style="width: 800px"
:config="tableConfig"
:model="tableModel"
:enableToggleMode="false"
:disabled="!editable"
name="params"
prop="params"
size="small"
>
</m-form-table>
</div>
</template>
<CodeDraftEditor
ref="codeDraftEditor"
:id="id"
:content="codeContent"
:editable="editable"
:autoSaveDraft="autoSaveDraft"
:codeOptions="codeOptions"
language="javascript"
@saveAndClose="saveAndClose"
@close="close"
></CodeDraftEditor>
</TMagicCard>
</template>
<script lang="ts" setup>
import { inject, provide, ref, watchEffect } from 'vue';
import { cloneDeep } from 'lodash-es';
import { TMagicCard, TMagicInput, tMagicMessage } from '@tmagic/design';
import { ColumnConfig, TableConfig } from '@tmagic/form';
import { CodeParam, Id } from '@tmagic/schema';
import type { Services } from '@editor/type';
import { getConfig } from '@editor/utils/config';
import CodeDraftEditor from './CodeDraftEditor.vue';
defineOptions({
name: 'MEditorFunctionEditor',
});
provide('mForm', null);
const defaultParamColConfig: ColumnConfig = {
type: 'row',
label: '参数类型',
items: [
{
text: '参数类型',
labelWidth: '70px',
type: 'select',
name: 'type',
options: [
{
text: '数字',
label: '数字',
value: 'number',
},
{
text: '字符串',
label: '字符串',
value: 'text',
},
],
},
],
};
const props = withDefaults(
defineProps<{
/** 代码块id */
id: Id;
/** 代码块名称 */
name: string;
/** 代码内容 */
content: string;
/** 是否可编辑 */
editable?: boolean;
/** 是否自动保存草稿 */
autoSaveDraft?: boolean;
/** 编辑器扩展参数 */
codeOptions?: object;
/** 代码参数扩展配置 */
paramsColConfig?: ColumnConfig;
}>(),
{
editable: true,
autoSaveDraft: true,
},
);
const paramsColConfig = props.paramsColConfig || defaultParamColConfig;
const tableConfig: TableConfig = {
type: 'table',
border: true,
enableFullscreen: false,
name: 'params',
maxHeight: '300px',
dropSort: false,
items: [
{
type: 'text',
label: '参数名',
name: 'name',
width: 200,
},
{
type: 'text',
label: '参数注释',
name: 'extra',
width: 200,
},
paramsColConfig,
],
};
const services = inject<Services>('services');
const codeName = ref<string>('');
const codeContent = ref<string>('');
const evalRes = ref(true);
const tableModel = ref<{ params: CodeParam[] }>();
watchEffect(() => {
codeName.value = props.name;
codeContent.value = props.content;
});
const initTableModel = (): void => {
const codeDsl = cloneDeep(services?.codeBlockService.getCodeDsl());
if (!codeDsl) return;
tableModel.value = {
params: codeDsl[props.id]?.params || [],
};
};
initTableModel();
// 保存前钩子
const beforeSave = (codeValue: string): boolean => {
try {
// 检测js代码是否存在语法错误
getConfig('parseDSL')(codeValue);
return true;
} catch (e: any) {
tMagicMessage.error(e.stack);
return false;
}
};
// 保存代码
const saveCode = async (codeValue: string): Promise<void> => {
if (!props.editable) return;
evalRes.value = beforeSave(codeValue);
if (evalRes.value) {
// 存入dsl
await services?.codeBlockService.setCodeDslById(props.id, {
name: codeName.value,
content: codeValue,
params: tableModel.value?.params || [],
});
tMagicMessage.success('代码成功保存到本地');
// 删除草稿
services?.codeBlockService.removeCodeDraft(props.id);
}
};
// 保存并关闭
const saveAndClose = async (codeValue: string): Promise<void> => {
await saveCode(codeValue);
if (evalRes.value) {
close();
}
};
// 关闭弹窗
const close = (): void => {
services?.codeBlockService.setCodeEditorShowStatus(false);
};
const codeDraftEditor = ref<InstanceType<typeof CodeDraftEditor>>();
defineExpose({
codeDraftEditor,
});
</script>