diff --git a/packages/editor/src/fields/Code.vue b/packages/editor/src/fields/Code.vue index aa6b52002..098747fcf 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 c2c0cb193..b5f84884b 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 000000000..d9ed67645 --- /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 7989a8a23..53448c36e 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 1feb8aa82..8fe706e4c 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 aa4188963..8e004f703 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 0f77599bc..3c030bb3c 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 b0cf3ac01..b5682fc8b 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 f55a2e685..8108f35d3 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; };