From d4a8b89e6f9e079d9cfdc1eb8a9935f0f2aacb5b Mon Sep 17 00:00:00 2001 From: roymondchen Date: Sun, 1 Oct 2023 17:44:27 +0800 Subject: [PATCH] =?UTF-8?q?feat(editor,schema):=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=95=B0=E6=8D=AE=E6=BA=90mock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/editor/src/fields/Code.vue | 12 +- .../editor/src/fields/DataSourceFields.vue | 8 +- .../editor/src/fields/DataSourceMocks.vue | 187 ++++++++++++++++++ packages/editor/src/index.ts | 3 + packages/editor/src/layouts/CodeEditor.vue | 24 ++- .../editor/src/utils/data-source/index.ts | 11 ++ packages/schema/src/index.ts | 9 + packages/table/src/ComponentColumn.vue | 17 +- packages/table/src/schema.ts | 4 +- 9 files changed, 260 insertions(+), 15 deletions(-) create mode 100644 packages/editor/src/fields/DataSourceMocks.vue diff --git a/packages/editor/src/fields/Code.vue b/packages/editor/src/fields/Code.vue index aa6b5200..098747fc 100644 --- a/packages/editor/src/fields/Code.vue +++ b/packages/editor/src/fields/Code.vue @@ -7,6 +7,7 @@ ...config.options, readOnly: disabled, }" + :parse="config.parse" @save="save" > @@ -20,14 +21,19 @@ defineOptions({ name: 'MEditorCode', }); -const emit = defineEmits(['change']); +const emit = defineEmits<{ + change: [value: string | any]; +}>(); const props = withDefaults( defineProps< FieldProps<{ language?: string; - options?: Object; + options?: { + [key: string]: any; + }; height?: string; + parse?: boolean; }> >(), { @@ -35,7 +41,7 @@ const props = withDefaults( }, ); -const save = (v: string) => { +const save = (v: string | any) => { props.model[props.name] = v; emit('change', v); }; diff --git a/packages/editor/src/fields/DataSourceFields.vue b/packages/editor/src/fields/DataSourceFields.vue index c2c0cb19..b5f84884 100644 --- a/packages/editor/src/fields/DataSourceFields.vue +++ b/packages/editor/src/fields/DataSourceFields.vue @@ -9,7 +9,7 @@ ('services'); const addDialog = ref>(); const fieldValues = ref>({}); -const filedTitle = ref(''); +const fieldTitle = ref(''); const width = computed(() => globalThis.document.body.clientWidth - (services?.uiService.get('columnWidth').left || 0)); const newHandler = () => { fieldValues.value = {}; - filedTitle.value = '新增属性'; + fieldTitle.value = '新增属性'; addDialog.value?.show(); }; @@ -100,7 +100,7 @@ const fieldColumns = [ ...row, index, }; - filedTitle.value = `编辑${row.title}`; + fieldTitle.value = `编辑${row.title}`; addDialog.value?.show(); }, }, diff --git a/packages/editor/src/fields/DataSourceMocks.vue b/packages/editor/src/fields/DataSourceMocks.vue new file mode 100644 index 00000000..d9ed6764 --- /dev/null +++ b/packages/editor/src/fields/DataSourceMocks.vue @@ -0,0 +1,187 @@ + + + diff --git a/packages/editor/src/index.ts b/packages/editor/src/index.ts index 7989a8a2..53448c36 100644 --- a/packages/editor/src/index.ts +++ b/packages/editor/src/index.ts @@ -26,6 +26,7 @@ import DataSourceFieldSelect from './fields/DataSourceFieldSelect.vue'; import DataSourceInput from './fields/DataSourceInput.vue'; import DataSourceMethods from './fields/DataSourceMethods.vue'; import DataSourceMethodSelect from './fields/DataSourceMethodSelect.vue'; +import DataSourceMocks from './fields/DataSourceMocks.vue'; import DataSourceSelect from './fields/DataSourceSelect.vue'; import EventSelect from './fields/EventSelect.vue'; import KeyValue from './fields/KeyValue.vue'; @@ -59,6 +60,7 @@ export { default as LayerPanel } from './layouts/sidebar/LayerPanel.vue'; export { default as CodeSelect } from './fields/CodeSelect.vue'; export { default as CodeSelectCol } from './fields/CodeSelectCol.vue'; export { default as DataSourceFields } from './fields/DataSourceFields.vue'; +export { default as DataSourceMocks } from './fields/DataSourceMocks.vue'; export { default as DataSourceMethods } from './fields/DataSourceMethods.vue'; export { default as DataSourceInput } from './fields/DataSourceInput.vue'; export { default as DataSourceSelect } from './fields/DataSourceSelect.vue'; @@ -98,6 +100,7 @@ export default { app.component('m-fields-code-select-col', CodeSelectCol); app.component('m-fields-event-select', EventSelect); app.component('m-fields-data-source-fields', DataSourceFields); + app.component('m-fields-data-source-mocks', DataSourceMocks); app.component('m-fields-key-value', KeyValue); app.component('m-fields-data-source-input', DataSourceInput); app.component('m-fields-data-source-select', DataSourceSelect); diff --git a/packages/editor/src/layouts/CodeEditor.vue b/packages/editor/src/layouts/CodeEditor.vue index 1feb8aa8..8fe706e4 100644 --- a/packages/editor/src/layouts/CodeEditor.vue +++ b/packages/editor/src/layouts/CodeEditor.vue @@ -27,6 +27,8 @@ import serialize from 'serialize-javascript'; import { TMagicButton } from '@tmagic/design'; +import { getConfig } from '@editor/utils/config'; + defineOptions({ name: 'MEditorCodeEditor', }); @@ -42,6 +44,7 @@ const props = withDefaults( }; height?: string; autoSave?: boolean; + parse?: boolean; }>(), { autoSave: true, @@ -49,6 +52,7 @@ const props = withDefaults( options: () => ({ tabSize: 2, }), + parse: false, }, ); @@ -57,7 +61,7 @@ const emit = defineEmits(['initd', 'save']); const toString = (v: string | any, language: string): string => { let value = ''; if (typeof v !== 'string') { - if (props.language.toLocaleLowerCase() === 'json') { + if (language === 'json') { value = JSON.stringify(v, null, 2); } else { value = serialize(v, { @@ -74,6 +78,18 @@ const toString = (v: string | any, language: string): string => { return value; }; +const parse = (v: string | any, language: string): any => { + if (typeof v !== 'string') { + return v; + } + + if (language === 'json') { + return JSON.parse(v); + } + + return getConfig('parseDSL')(v); +}; + let vsEditor: monaco.editor.IStandaloneCodeEditor | null = null; let vsDiffEditor: monaco.editor.IStandaloneDiffEditor | null = null; @@ -89,7 +105,7 @@ const resizeObserver = new globalThis.ResizeObserver( ); const setEditorValue = (v: string | any, m: string | any) => { - values.value = toString(v, props.language); + values.value = toString(v, props.language.toLocaleLowerCase()); if (props.type === 'diff') { const originalModel = monaco.editor.createModel(values.value, 'text/javascript'); @@ -135,7 +151,7 @@ const init = async () => { e.stopPropagation(); const newValue = getEditorValue(); values.value = newValue; - emit('save', newValue); + emit('save', props.parse ? parse(newValue, props.language) : newValue); } }); @@ -144,7 +160,7 @@ const init = async () => { const newValue = getEditorValue(); if (values.value !== newValue) { values.value = newValue; - emit('save', newValue); + emit('save', props.parse ? parse(newValue, props.language) : newValue); } }); } diff --git a/packages/editor/src/utils/data-source/index.ts b/packages/editor/src/utils/data-source/index.ts index aa418896..8e004f70 100644 --- a/packages/editor/src/utils/data-source/index.ts +++ b/packages/editor/src/utils/data-source/index.ts @@ -41,6 +41,17 @@ const fillConfig = (config: FormConfig): FormConfig => [ }, ], }, + { + type: 'panel', + title: 'mock数据', + items: [ + { + name: 'mocks', + type: 'data-source-mocks', + defaultValue: () => [], + }, + ], + }, ]; export const getFormConfig = (type: string, configs: Record): FormConfig => { diff --git a/packages/schema/src/index.ts b/packages/schema/src/index.ts index 0f77599b..3c030bb3 100644 --- a/packages/schema/src/index.ts +++ b/packages/schema/src/index.ts @@ -200,6 +200,13 @@ export interface DataSchema { fields?: DataSchema[]; } +export interface MockSchema { + title: string; + description?: string; + enable: boolean; + data: Record; +} + export interface DataSourceSchema { /** 数据源类型,根据类型来实例化;例如http则使用new HttpDataSource */ type: string; @@ -213,6 +220,8 @@ export interface DataSourceSchema { fields: DataSchema[]; /** 方法列表 */ methods: CodeBlockContent[]; + /** mock数据 */ + mocks?: MockSchema[]; /** 扩展字段 */ [key: string]: any; } diff --git a/packages/table/src/ComponentColumn.vue b/packages/table/src/ComponentColumn.vue index b0cf3ac0..b5682fc8 100644 --- a/packages/table/src/ComponentColumn.vue +++ b/packages/table/src/ComponentColumn.vue @@ -8,7 +8,11 @@ :prop="config.prop" > @@ -31,10 +35,17 @@ const props = withDefaults( }, ); -const componentProps = (row: any) => { +const componentProps = (row: any, index: number) => { if (typeof props.config.props === 'function') { - return props.config.props(row) || {}; + return props.config.props(row, index) || {}; } return props.config.props || {}; }; + +const componentListeners = (row: any, index: number) => { + if (typeof props.config.listeners === 'function') { + return props.config.listeners(row, index) || {}; + } + return props.config.listeners || {}; +}; diff --git a/packages/table/src/schema.ts b/packages/table/src/schema.ts index f55a2e68..8108f35d 100644 --- a/packages/table/src/schema.ts +++ b/packages/table/src/schema.ts @@ -62,8 +62,10 @@ export type ColumnConfig = { expandContent?: (row: any, prop?: string) => string; /** 当type为expand时,展开为vue组件;当type为component时显示的组件 */ component?: any; - /** 当type为expand时有效,展开的vue组件props */ + /** 当type为expand时,展开的vue组件props;当type为component时显示的组件的props */ props?: any; + /** 当type为component时显示的组件的事件监听 */ + listeners?: any; /** 当type为tip时有效,显示文案 */ buttonText?: string; };