feat(editor): 代码块支持传递参数 (merge request !9)

Squash merge branch 'feature/parisma_codeDraft' into 'master'
1、 table支持items为函数
2、代码块支持传递参数
This commit is contained in:
parisma 2022-11-15 16:30:09 +08:00 committed by roymondchen
parent cc21c47829
commit 16f671cd8f
11 changed files with 135 additions and 47 deletions

View File

@ -17,7 +17,7 @@
</div>
</div>
</template>
<script lang="ts" setup>
<script lang="ts" setup name="MEditorCodeDraftEditor">
import { computed, inject, ref, watchEffect } from 'vue';
import type * as monaco from 'monaco-editor';

View File

@ -5,6 +5,19 @@
<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: 320px"
:config="tableConfig"
:model="tableModel"
:enableToggleMode="false"
name="params"
prop="params"
size="small"
>
</m-form-table>
</div>
</template>
<CodeDraftEditor
:id="id"
@ -19,16 +32,29 @@
></CodeDraftEditor>
</TMagicCard>
</template>
<script lang="ts" setup>
import { inject, ref, watchEffect } from 'vue';
<script lang="ts" setup name="MEditorFunctionEditor">
import { inject, provide, ref, watchEffect } from 'vue';
import { TMagicCard, TMagicInput, tMagicMessage } from '@tmagic/design';
import { Id } from '@tmagic/schema';
import { CodeParam, Id } from '@tmagic/schema';
import type { Services } from '../type';
import CodeDraftEditor from './CodeDraftEditor.vue';
const tableConfig = {
border: true,
enableFullscreen: false,
name: 'params',
items: [
{
type: 'text',
label: '参数名',
name: 'name',
},
],
};
const props = withDefaults(
defineProps<{
id: Id;
@ -44,20 +70,39 @@ const props = withDefaults(
},
);
const emit = defineEmits(['change', 'field-input']);
const services = inject<Services>('services');
const codeName = ref<string>('');
const codeContent = ref<string>('');
const evalRes = ref(true);
provide('mForm', {
$emit: emit,
setField: () => {},
});
const tableModel = ref<{ params: CodeParam[] }>();
watchEffect(() => {
codeName.value = props.name;
codeContent.value = props.content;
});
const initTableModel = () => {
const codeDsl = services?.codeBlockService.getCodeDslSync();
if (!codeDsl) return;
tableModel.value = {
params: codeDsl[props.id]?.params || [],
};
};
initTableModel();
//
const beforeSave = (codeValue: string): boolean => {
try {
// evaljs
// eslint-disable-next-line no-eval
eval(codeValue);
return true;
@ -76,6 +121,7 @@ const saveCode = async (codeValue: string): Promise<void> => {
await services?.codeBlockService.setCodeDslById(props.id, {
name: codeName.value,
content: codeValue,
params: tableModel.value?.params || [],
});
tMagicMessage.success('代码保存成功');
// 稿

View File

@ -4,6 +4,7 @@
:config="tableConfig"
:model="model[name]"
name="hookData"
:enableToggleMode="false"
:prop="prop"
:size="size"
@change="changeHandler"
@ -17,9 +18,9 @@ import { computed, defineEmits, defineProps, inject, watch } from 'vue';
import { isEmpty, map } from 'lodash-es';
import { FormItem, TableConfig } from '@tmagic/form';
import { HookType } from '@tmagic/schema';
import { HookType, Id } from '@tmagic/schema';
import { Services } from '../type';
import { CodeParamStatement, HookData, Services } from '../type';
const services = inject<Services>('services');
const emit = defineEmits(['change']);
@ -32,19 +33,22 @@ const props = defineProps<{
name: string;
size: 'mini' | 'small' | 'medium';
}>();
const codeDsl = computed(() => services?.codeBlockService.getCodeDslSync());
const tableConfig = computed<FormItem>(() => {
const defaultConfig = {
dropSort: true,
enableFullscreen: false,
border: true,
items: [
{
type: 'select',
label: '代码块',
name: 'codeId',
options: async () => {
const codeDsl = await services?.codeBlockService.getCodeDsl();
if (codeDsl) {
return map(codeDsl, (value, key) => ({
width: '200px',
options: () => {
if (codeDsl.value) {
return map(codeDsl.value, (value, key) => ({
text: `${value.name}${key}`,
label: `${value.name}${key}`,
value: key,
@ -52,6 +56,16 @@ const tableConfig = computed<FormItem>(() => {
}
return [];
},
onChange: (formState: any, codeId: Id, { model }: any) => {
// itemscodeIdmodelcodeIdparams
model.params = {};
},
},
{
name: 'params',
label: '参数',
defaultValue: {},
itemsFunction: (row: HookData) => getParamsConfig(row.codeId),
},
],
};
@ -71,15 +85,6 @@ watch(
hookType: HookType.CODE,
hookData: [],
};
} else if (Array.isArray(value) && value.length > 0) {
// ['code1','code2']
const hookData = value.map((codeId) => ({
codeId,
}));
props.model[props.name] = {
hookType: HookType.CODE,
hookData,
};
}
},
{
@ -90,4 +95,16 @@ watch(
const changeHandler = async () => {
emit('change', props.model[props.name]);
};
const getParamsConfig = (codeId: Id) => {
if (!codeDsl.value) return [];
const paramStatements = codeDsl.value[codeId]?.params;
if (isEmpty(paramStatements)) return [];
return paramStatements.map((paramState: CodeParamStatement) => ({
name: paramState.name,
text: paramState.name,
labelWidth: '100px',
type: 'text',
}));
};
</script>

View File

@ -145,7 +145,7 @@ const initList = async () => {
};
watch(
[() => services?.codeBlockService.getCodeDsl(), () => services?.codeBlockService.refreshCombineInfo()],
[() => services?.codeBlockService.getCodeDslSync(), () => services?.codeBlockService.refreshCombineInfo()],
() => {
initList();
},
@ -165,6 +165,7 @@ const createCodeBlock = async () => {
const codeConfig: CodeBlockContent = {
name: '代码块',
content: `() => {\n // place your code here\n}`,
params: [],
};
await codeBlockService.setMode(CodeEditorMode.EDITOR);
const id = await codeBlockService.getUniqueId();

View File

@ -71,12 +71,17 @@ class CodeBlock extends BaseService {
/**
* dsl数据源dsl中的codeBlocks字段读取
* ,
* @param {boolean} forceRefresh dsl拉取刷新
* @returns {CodeBlockDSL | null}
*/
public async getCodeDsl(forceRefresh = false): Promise<CodeBlockDSL | null> {
return this.getCodeDslSync(forceRefresh);
}
public getCodeDslSync(forceRefresh = false): CodeBlockDSL | null {
if (!this.state.codeDsl || forceRefresh) {
this.state.codeDsl = await editorService.getCodeDsl();
this.state.codeDsl = editorService.getCodeDslSync();
}
return this.state.codeDsl;
}

View File

@ -788,6 +788,12 @@ class Editor extends BaseService {
return root.codeBlocks || null;
}
public getCodeDslSync(): CodeBlockDSL | null {
const root = this.get<MApp | null>('root');
if (!root) return null;
return root.codeBlocks || null;
}
/**
* dsl的codeBlocks字段
* @param {CodeBlockDSL} codeDsl DSL

View File

@ -87,7 +87,7 @@
height: 100%;
background: #fff;
.el-card__body {
height: calc(100% - 80px);
height: 100%;
background: #fff;
}
}
@ -127,6 +127,7 @@
display: flex;
align-items: center;
font-size: 16px;
margin-bottom: 10px;
.code-name-label {
margin-right: 10px;
}
@ -148,7 +149,7 @@
position: absolute;
top: 0;
left: 4px;
width: calc(100% - 9px);
width: 100%;
height: 100%;
z-index: 10;
background: #fff;
@ -160,14 +161,17 @@
.m-editor-wrapper {
height: 100%;
.m-editor-container {
height: calc(100% - 70px);
height: calc(100% - 65px);
}
.m-editor-content-bottom {
height: 40px;
height: 45px;
width: 100%;
display: flex;
justify-content: end;
background: #fff;
position: absolute;
right: 20px;
bottom: 0;
> button {
height: 30px;
margin-top: 15px;

View File

@ -383,3 +383,10 @@ export enum CodeDeleteErrorType {
// 代码块草稿localStorage key
export const CODE_DRAFT_STORAGE_KEY = 'magicCodeDraft';
export interface CodeParamStatement {
/** 参数名称 */
name: string;
/** 参数类型 */
type?: string;
}

View File

@ -101,7 +101,7 @@
labelWidth="0"
:prop="getProp(scope.$index)"
:rules="column.rules"
:config="makeConfig(column)"
:config="makeConfig(column, scope.row)"
:model="scope.row"
:size="size"
@change="$emit('change', model[modelName])"
@ -432,8 +432,11 @@ const toggleRowSelection = (row: any, selected: boolean) => {
tMagicTable.value?.toggleRowSelection.call(tMagicTable.value, row, selected);
};
const makeConfig = (config: ColumnConfig) => {
const makeConfig = (config: ColumnConfig, row: any) => {
const newConfig = cloneDeep(config);
if (typeof config.itemsFunction === 'function') {
newConfig.items = config.itemsFunction(row);
}
delete newConfig.display;
return newConfig;
};

View File

@ -81,10 +81,16 @@ export interface CodeBlockContent {
name: string;
/** 代码块内容 */
content: any;
/** 参数定义 */
params: CodeParam[] | [];
/** 扩展字段 */
[propName: string]: any;
}
export interface CodeParam {
/** 参数名 */
name: string;
}
export interface PastePosition {
left?: number;
top?: number;

View File

@ -24,13 +24,21 @@ export default {
code_5336: {
name: 'getData',
// eslint-disable-next-line no-eval
content: eval(`(vm, params) => {\n console.log("this is getData function",vm,params)\n}`),
params: ['name', 'age'],
content: eval(`(vm, params) => {\n console.log("this is getData function",params)\n}`),
params: [
{
name: 'age',
},
{
name: 'studentName',
},
],
},
code_5316: {
name: 'getList',
// eslint-disable-next-line no-eval
content: eval(`(vm) => {\n console.log("this is getList function")\n}`),
params: [],
},
},
items: [
@ -63,20 +71,13 @@ export default {
{
codeId: 'code_5336',
params: {
name: 'lisa',
age: 12,
studentName: 'lisa',
age: 14,
},
},
{
codeId: 'code_5316',
},
],
},
mounted: {
hookType: 'code',
hookData: [
{
codeId: 'code_5316',
params: {},
},
],
},
@ -104,14 +105,6 @@ export default {
text: 'Tmagic editor 营销活动编辑器',
multiple: true,
events: [],
created: {
hookType: 'code',
hookData: [
{
codeId: 'code_5316',
},
],
},
},
{
type: 'qrcode',