mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2025-05-18 19:36:50 +08:00
feat: 支持迭代器容器
This commit is contained in:
parent
6dbac52c50
commit
e692e01c4f
@ -21,10 +21,16 @@ import EventEmitter from 'events';
|
|||||||
import { cloneDeep, template } from 'lodash-es';
|
import { cloneDeep, template } from 'lodash-es';
|
||||||
|
|
||||||
import type { AppCore, DataSourceSchema, Id, MNode } from '@tmagic/schema';
|
import type { AppCore, DataSourceSchema, Id, MNode } from '@tmagic/schema';
|
||||||
import { compiledCond, compiledNode, DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX, isObject } from '@tmagic/utils';
|
import {
|
||||||
|
compiledNode,
|
||||||
|
DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX,
|
||||||
|
DSL_NODE_KEY_COPY_PREFIX,
|
||||||
|
getValueByKeyPath,
|
||||||
|
} from '@tmagic/utils';
|
||||||
|
|
||||||
import { DataSource, HttpDataSource } from './data-sources';
|
import { DataSource, HttpDataSource } from './data-sources';
|
||||||
import type { ChangeEvent, DataSourceManagerData, DataSourceManagerOptions } from './types';
|
import type { ChangeEvent, DataSourceManagerData, DataSourceManagerOptions } from './types';
|
||||||
|
import { compliedConditions, createIteratorContentData } from './utils';
|
||||||
|
|
||||||
class DataSourceManager extends EventEmitter {
|
class DataSourceManager extends EventEmitter {
|
||||||
private static dataSourceClassMap = new Map<string, typeof DataSource>();
|
private static dataSourceClassMap = new Map<string, typeof DataSource>();
|
||||||
@ -189,15 +195,7 @@ class DataSourceManager extends EventEmitter {
|
|||||||
|
|
||||||
if (!data) return value;
|
if (!data) return value;
|
||||||
|
|
||||||
return fields.reduce((accumulator, currentValue: any) => {
|
return getValueByKeyPath(fields.join('.'), data);
|
||||||
if (Array.isArray(accumulator)) return accumulator;
|
|
||||||
|
|
||||||
if (isObject(accumulator)) {
|
|
||||||
return accumulator[currentValue];
|
|
||||||
}
|
|
||||||
|
|
||||||
return '';
|
|
||||||
}, data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,34 +208,39 @@ class DataSourceManager extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public compliedConds(node: MNode) {
|
public compliedConds(node: MNode) {
|
||||||
if (!node.displayConds || !Array.isArray(node.displayConds) || !node.displayConds.length) return true;
|
return compliedConditions(node, this.data);
|
||||||
|
}
|
||||||
|
|
||||||
for (const { cond } of node.displayConds) {
|
public compliedIteratorItems(itemData: any, items: MNode[], dataSourceField: string[] = []) {
|
||||||
if (!cond) continue;
|
return items.map((item) => {
|
||||||
|
const keys: string[] = [];
|
||||||
|
const [dsId, ...fields] = dataSourceField;
|
||||||
|
|
||||||
let result = true;
|
Object.entries(item).forEach(([key, value]) => {
|
||||||
for (const { op, value, range, field } of cond) {
|
if (
|
||||||
const [sourceId, fieldKey] = field;
|
typeof value === 'string' &&
|
||||||
|
!key.startsWith(DSL_NODE_KEY_COPY_PREFIX) &&
|
||||||
const dsData = this.data[sourceId];
|
value.includes(`${dsId}`) &&
|
||||||
|
/\$\{([\s\S]+?)\}/.test(value)
|
||||||
if (!dsData || !fieldKey) {
|
) {
|
||||||
break;
|
keys.push(key);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const fieldValue = dsData[fieldKey];
|
return compiledNode(
|
||||||
if (!compiledCond(op, fieldValue, value, range)) {
|
(value: string) => template(value)(createIteratorContentData(itemData, dsId, fields)),
|
||||||
result = false;
|
cloneDeep(item),
|
||||||
break;
|
{
|
||||||
}
|
[dsId]: {
|
||||||
}
|
[item.id]: {
|
||||||
|
name: '',
|
||||||
if (result) {
|
keys,
|
||||||
return true;
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
|
dsId,
|
||||||
return false;
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public destroy() {
|
public destroy() {
|
||||||
|
@ -17,11 +17,12 @@
|
|||||||
*/
|
*/
|
||||||
import { cloneDeep, union } from 'lodash-es';
|
import { cloneDeep, union } from 'lodash-es';
|
||||||
|
|
||||||
import type { AppCore, MApp, MNode, MPage, MPageFragment } from '@tmagic/schema';
|
import type { AppCore } from '@tmagic/schema';
|
||||||
import { getDepNodeIds, getNodes, isPage, isPageFragment, replaceChildNode } from '@tmagic/utils';
|
import { getDepNodeIds, getNodes } from '@tmagic/utils';
|
||||||
|
|
||||||
import DataSourceManager from './DataSourceManager';
|
import DataSourceManager from './DataSourceManager';
|
||||||
import type { ChangeEvent, DataSourceManagerData } from './types';
|
import type { ChangeEvent, DataSourceManagerData } from './types';
|
||||||
|
import { updateNode } from './utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建数据源管理器
|
* 创建数据源管理器
|
||||||
@ -73,12 +74,3 @@ export const createDataSourceManager = (app: AppCore, useMock?: boolean, initial
|
|||||||
|
|
||||||
return dataSourceManager;
|
return dataSourceManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateNode = (node: MNode, dsl: MApp) => {
|
|
||||||
if (isPage(node) || isPageFragment(node)) {
|
|
||||||
const index = dsl.items?.findIndex((child: MNode) => child.id === node.id);
|
|
||||||
dsl.items.splice(index, 1, node as MPage | MPageFragment);
|
|
||||||
} else {
|
|
||||||
replaceChildNode(node, dsl!.items);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
@ -19,4 +19,5 @@
|
|||||||
export { default as DataSourceManager } from './DataSourceManager';
|
export { default as DataSourceManager } from './DataSourceManager';
|
||||||
export * from './data-sources';
|
export * from './data-sources';
|
||||||
export * from './createDataSourceManager';
|
export * from './createDataSourceManager';
|
||||||
|
export * from './utils';
|
||||||
export * from './types';
|
export * from './types';
|
||||||
|
59
packages/data-source/src/utils.ts
Normal file
59
packages/data-source/src/utils.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import type { MApp, MNode, MPage, MPageFragment } from '@tmagic/schema';
|
||||||
|
import { compiledCond, getValueByKeyPath, isPage, isPageFragment, replaceChildNode } from '@tmagic/utils';
|
||||||
|
|
||||||
|
import type { DataSourceManagerData } from './types';
|
||||||
|
|
||||||
|
export const compliedConditions = (node: MNode, data: DataSourceManagerData) => {
|
||||||
|
if (!node.displayConds || !Array.isArray(node.displayConds) || !node.displayConds.length) return true;
|
||||||
|
|
||||||
|
for (const { cond } of node.displayConds) {
|
||||||
|
if (!cond) continue;
|
||||||
|
|
||||||
|
let result = true;
|
||||||
|
for (const { op, value, range, field } of cond) {
|
||||||
|
const [sourceId, ...fields] = field;
|
||||||
|
|
||||||
|
const dsData = data[sourceId];
|
||||||
|
|
||||||
|
if (!dsData || !fields.length) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fieldValue = getValueByKeyPath(fields.join('.'), data[sourceId]);
|
||||||
|
|
||||||
|
if (!compiledCond(op, fieldValue, value, range)) {
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateNode = (node: MNode, dsl: MApp) => {
|
||||||
|
if (isPage(node) || isPageFragment(node)) {
|
||||||
|
const index = dsl.items?.findIndex((child: MNode) => child.id === node.id);
|
||||||
|
dsl.items.splice(index, 1, node as MPage | MPageFragment);
|
||||||
|
} else {
|
||||||
|
replaceChildNode(node, dsl!.items);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createIteratorContentData = (itemData: any, dsId: string, fields: string[] = []) => {
|
||||||
|
const data = {
|
||||||
|
[dsId]: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
fields.reduce((obj: any, field, index) => {
|
||||||
|
obj[field] = index === fields.length - 1 ? itemData : {};
|
||||||
|
|
||||||
|
return obj[field];
|
||||||
|
}, data[dsId]);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
};
|
@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
type CodeBlockContent,
|
type CodeBlockContent,
|
||||||
|
type DataSchema,
|
||||||
type DataSourceSchema,
|
type DataSourceSchema,
|
||||||
type DepData,
|
type DepData,
|
||||||
type HookData,
|
type HookData,
|
||||||
@ -46,14 +47,55 @@ export const createDataSourceTarget = (ds: DataSourceSchema, initialDeps: DepDat
|
|||||||
isTarget: (key: string | number, value: any) => {
|
isTarget: (key: string | number, value: any) => {
|
||||||
// 关联数据源对象,如:{ isBindDataSource: true, dataSourceId: 'xxx'}
|
// 关联数据源对象,如:{ isBindDataSource: true, dataSourceId: 'xxx'}
|
||||||
// 使用data-source-select value: 'value' 可以配置出来
|
// 使用data-source-select value: 'value' 可以配置出来
|
||||||
// 或者在模板在使用数据源,如:`xxx${id.field}xxx`
|
|
||||||
if (
|
if (value?.isBindDataSource && value.dataSourceId && value.dataSourceId === ds.id) {
|
||||||
(value?.isBindDataSource && value.dataSourceId && value.dataSourceId === ds.id) ||
|
|
||||||
(typeof value === 'string' && value.includes(`${ds.id}`) && /\$\{([\s\S]+?)\}/.test(value))
|
|
||||||
) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 或者在模板在使用数据源,如:`xxx${dsId.field}xxx${dsId.field}`
|
||||||
|
if (typeof value === 'string' && value.includes(`${ds.id}`) && /\$\{([\s\S]+?)\}/.test(value)) {
|
||||||
|
// 模板中可能会存在多个表达式,将表达式从模板中提取出来
|
||||||
|
const templates = value.match(/\$\{([\s\S]+?)\}/g) || [];
|
||||||
|
|
||||||
|
for (const tpl of templates) {
|
||||||
|
const keys = tpl
|
||||||
|
// 将${dsId.xxxx} 转成 dsId.xxxx
|
||||||
|
.substring(2, tpl.length - 1)
|
||||||
|
// 将 array[0] 转成 array.0
|
||||||
|
.replaceAll(/\[(\d+)\]/g, '.$1')
|
||||||
|
.split('.');
|
||||||
|
const dsId = keys.shift();
|
||||||
|
|
||||||
|
if (!dsId || dsId !== ds.id) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ${dsId.array} ${dsId.array[0]} ${dsId.array[0].a} 这种是依赖
|
||||||
|
// ${dsId.array.a} 这种不是依赖,这种需要再迭代器容器中的组件才能使用,依赖由迭代器处理
|
||||||
|
let includeArray = false;
|
||||||
|
keys.reduce((accumulator: DataSchema[], currentValue: string, currentIndex: number) => {
|
||||||
|
const field = accumulator.find(({ name }) => name === currentValue);
|
||||||
|
if (
|
||||||
|
field &&
|
||||||
|
field.type === 'array' &&
|
||||||
|
typeof keys[currentIndex + 1] !== 'number' &&
|
||||||
|
currentIndex < keys.length - 1
|
||||||
|
) {
|
||||||
|
includeArray = true;
|
||||||
|
}
|
||||||
|
return field?.fields || [];
|
||||||
|
}, ds.fields);
|
||||||
|
|
||||||
|
if (includeArray) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// 指定数据源的字符串模板,如:{ isBindDataSourceField: true, dataSourceId: 'id', template: `xxx${field}xxx`}
|
// 指定数据源的字符串模板,如:{ isBindDataSourceField: true, dataSourceId: 'id', template: `xxx${field}xxx`}
|
||||||
if (
|
if (
|
||||||
value?.isBindDataSourceField &&
|
value?.isBindDataSourceField &&
|
||||||
|
@ -1,23 +1,32 @@
|
|||||||
<template>
|
<template>
|
||||||
<m-form-container
|
<MCascader
|
||||||
:config="{
|
:config="cascaderConfig"
|
||||||
...config,
|
|
||||||
...cascaderConfig,
|
|
||||||
}"
|
|
||||||
:model="model"
|
:model="model"
|
||||||
|
:name="name"
|
||||||
|
:disabled="disabled"
|
||||||
|
:size="size"
|
||||||
|
:last-values="lastValues"
|
||||||
|
:init-values="initValues"
|
||||||
|
:values="values"
|
||||||
|
:prop="`${prop}${prop ? '.' : ''}${name}`"
|
||||||
@change="onChangeHandler"
|
@change="onChangeHandler"
|
||||||
></m-form-container>
|
></MCascader>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, inject } from 'vue';
|
import { computed, inject } from 'vue';
|
||||||
|
|
||||||
import type { CascaderOption, FieldProps } from '@tmagic/form';
|
import type { CascaderConfig, CascaderOption, FieldProps } from '@tmagic/form';
|
||||||
import type { DataSchema } from '@tmagic/schema';
|
import { MCascader } from '@tmagic/form';
|
||||||
|
import type { DataSchema, DataSourceFieldType } from '@tmagic/schema';
|
||||||
import { DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX } from '@tmagic/utils';
|
import { DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX } from '@tmagic/utils';
|
||||||
|
|
||||||
import type { DataSourceFieldSelectConfig, Services } from '@editor/type';
|
import type { DataSourceFieldSelectConfig, Services } from '@editor/type';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'MEditorDataSourceFieldSelect',
|
||||||
|
});
|
||||||
|
|
||||||
const services = inject<Services>('services');
|
const services = inject<Services>('services');
|
||||||
const emit = defineEmits(['change']);
|
const emit = defineEmits(['change']);
|
||||||
|
|
||||||
@ -27,29 +36,31 @@ const props = withDefaults(defineProps<FieldProps<DataSourceFieldSelectConfig>>(
|
|||||||
|
|
||||||
const dataSources = computed(() => services?.dataSourceService.get('dataSources'));
|
const dataSources = computed(() => services?.dataSourceService.get('dataSources'));
|
||||||
|
|
||||||
const getOptionChildren = (fields: DataSchema[] = []): CascaderOption[] =>
|
const getOptionChildren = (fields: DataSchema[] = [], fieldType: DataSourceFieldType[] = []): CascaderOption[] =>
|
||||||
fields.map((field) => ({
|
fields
|
||||||
label: field.title || field.name,
|
.filter((field) => !fieldType.length || fieldType.includes(field.type || 'string') || field.type === 'object')
|
||||||
value: field.name,
|
.map((field) => ({
|
||||||
children: field.type === 'array' ? [] : getOptionChildren(field.fields),
|
label: field.title || field.name,
|
||||||
}));
|
value: field.name,
|
||||||
|
children: field.type === 'array' ? [] : getOptionChildren(field.fields, fieldType),
|
||||||
|
}));
|
||||||
|
|
||||||
const cascaderConfig = computed(() => {
|
const cascaderConfig = computed<CascaderConfig>(() => {
|
||||||
const valueIsKey = props.config.value === 'key';
|
const valueIsKey = props.config.value === 'key';
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'cascader',
|
type: 'cascader',
|
||||||
name: props.name,
|
checkStrictly: props.config.checkStrictly ?? !valueIsKey,
|
||||||
checkStrictly: !valueIsKey,
|
popperClass: 'm-editor-data-source-field-select-popper',
|
||||||
text: '',
|
options: () => {
|
||||||
options: () =>
|
const options =
|
||||||
dataSources.value
|
dataSources.value?.map((ds) => ({
|
||||||
?.filter((ds) => ds.fields?.length)
|
|
||||||
?.map((ds) => ({
|
|
||||||
label: ds.title || ds.id,
|
label: ds.title || ds.id,
|
||||||
value: valueIsKey ? ds.id : `${DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX}${ds.id}`,
|
value: valueIsKey ? ds.id : `${DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX}${ds.id}`,
|
||||||
children: getOptionChildren(ds.fields),
|
children: getOptionChildren(ds.fields, props.config.fieldType),
|
||||||
})) || [],
|
})) || [];
|
||||||
|
return options.filter((option) => option.children.length);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ import { computed, inject, ref } from 'vue';
|
|||||||
import { TMagicButton, tMagicMessage, tMagicMessageBox } from '@tmagic/design';
|
import { TMagicButton, tMagicMessage, tMagicMessageBox } from '@tmagic/design';
|
||||||
import { type FieldProps, type FormConfig, type FormState, MFormDrawer } from '@tmagic/form';
|
import { type FieldProps, type FormConfig, type FormState, MFormDrawer } from '@tmagic/form';
|
||||||
import type { DataSchema } from '@tmagic/schema';
|
import type { DataSchema } from '@tmagic/schema';
|
||||||
import { MagicTable } from '@tmagic/table';
|
import { type ColumnConfig, MagicTable } from '@tmagic/table';
|
||||||
import { getDefaultValueFromFields } from '@tmagic/utils';
|
import { getDefaultValueFromFields } from '@tmagic/utils';
|
||||||
|
|
||||||
import type { Services } from '@editor/type';
|
import type { Services } from '@editor/type';
|
||||||
@ -86,7 +86,7 @@ const fieldChange = ({ index, ...value }: Record<string, any>) => {
|
|||||||
emit('change', props.model[props.name]);
|
emit('change', props.model[props.name]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const fieldColumns = [
|
const fieldColumns: ColumnConfig[] = [
|
||||||
{
|
{
|
||||||
label: '属性名称',
|
label: '属性名称',
|
||||||
prop: 'title',
|
prop: 'title',
|
||||||
@ -102,6 +102,13 @@ const fieldColumns = [
|
|||||||
{
|
{
|
||||||
label: '默认值',
|
label: '默认值',
|
||||||
prop: 'defaultValue',
|
prop: 'defaultValue',
|
||||||
|
formatter(item, row) {
|
||||||
|
try {
|
||||||
|
return JSON.stringify(row.defaultValue);
|
||||||
|
} catch (e) {
|
||||||
|
return row.defaultValue;
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '操作',
|
label: '操作',
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
import { TMagicButton } from '@tmagic/design';
|
import { TMagicButton } from '@tmagic/design';
|
||||||
import type { FieldProps } from '@tmagic/form';
|
import type { FieldProps } from '@tmagic/form';
|
||||||
import type { CodeBlockContent } from '@tmagic/schema';
|
import type { CodeBlockContent } from '@tmagic/schema';
|
||||||
import { MagicTable } from '@tmagic/table';
|
import { type ColumnConfig, MagicTable } from '@tmagic/table';
|
||||||
|
|
||||||
import CodeBlockEditor from '@editor/components/CodeBlockEditor.vue';
|
import CodeBlockEditor from '@editor/components/CodeBlockEditor.vue';
|
||||||
import { useDataSourceMethod } from '@editor/hooks/use-data-source-method';
|
import { useDataSourceMethod } from '@editor/hooks/use-data-source-method';
|
||||||
@ -49,7 +49,7 @@ const emit = defineEmits(['change']);
|
|||||||
|
|
||||||
const { codeConfig, codeBlockEditor, createCode, editCode, deleteCode, submitCode } = useDataSourceMethod();
|
const { codeConfig, codeBlockEditor, createCode, editCode, deleteCode, submitCode } = useDataSourceMethod();
|
||||||
|
|
||||||
const methodColumns = [
|
const methodColumns: ColumnConfig[] = [
|
||||||
{
|
{
|
||||||
label: '名称',
|
label: '名称',
|
||||||
prop: 'name',
|
prop: 'name',
|
||||||
|
@ -26,7 +26,7 @@ import { computed, inject, ref } from 'vue';
|
|||||||
import { TMagicButton, tMagicMessageBox, TMagicSwitch } from '@tmagic/design';
|
import { TMagicButton, tMagicMessageBox, TMagicSwitch } from '@tmagic/design';
|
||||||
import { type FieldProps, type FormConfig, type FormState, MFormDrawer } from '@tmagic/form';
|
import { type FieldProps, type FormConfig, type FormState, MFormDrawer } from '@tmagic/form';
|
||||||
import type { MockSchema } from '@tmagic/schema';
|
import type { MockSchema } from '@tmagic/schema';
|
||||||
import { MagicTable } from '@tmagic/table';
|
import { type ColumnConfig, MagicTable } from '@tmagic/table';
|
||||||
import { getDefaultValueFromFields } from '@tmagic/utils';
|
import { getDefaultValueFromFields } from '@tmagic/utils';
|
||||||
|
|
||||||
import CodeEditor from '@editor/layouts/CodeEditor.vue';
|
import CodeEditor from '@editor/layouts/CodeEditor.vue';
|
||||||
@ -117,7 +117,7 @@ const formConfig: FormConfig = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const columns = [
|
const columns: ColumnConfig[] = [
|
||||||
{
|
{
|
||||||
type: 'expand',
|
type: 'expand',
|
||||||
component: CodeEditor,
|
component: CodeEditor,
|
||||||
|
@ -640,7 +640,9 @@ export interface DataSourceFieldSelectConfig extends FormItem {
|
|||||||
* value: 要编译(数据源data[`${filed}`])
|
* value: 要编译(数据源data[`${filed}`])
|
||||||
* */
|
* */
|
||||||
value?: 'key' | 'value';
|
value?: 'key' | 'value';
|
||||||
fieldType?: DataSourceFieldType;
|
/** 是否严格的遵守父子节点不互相关联 */
|
||||||
|
checkStrictly?: boolean;
|
||||||
|
fieldType?: DataSourceFieldType[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 可新增的数据源类型选项 */
|
/** 可新增的数据源类型选项 */
|
||||||
|
@ -91,6 +91,19 @@ export const styleTabConfig: TabPaneConfig = {
|
|||||||
name: 'height',
|
name: 'height',
|
||||||
text: '高度',
|
text: '高度',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
text: 'overflow',
|
||||||
|
name: 'overflow',
|
||||||
|
type: 'select',
|
||||||
|
options: [
|
||||||
|
{ text: 'visible', value: 'visible' },
|
||||||
|
{ text: 'hidden', value: 'hidden' },
|
||||||
|
{ text: 'clip', value: 'clip' },
|
||||||
|
{ text: 'scroll', value: 'scroll' },
|
||||||
|
{ text: 'auto', value: 'auto' },
|
||||||
|
{ text: 'overlay', value: 'overlay' },
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -247,15 +260,23 @@ export const displayTabConfig: TabPaneConfig = {
|
|||||||
name: 'field',
|
name: 'field',
|
||||||
value: 'key',
|
value: 'key',
|
||||||
label: '字段',
|
label: '字段',
|
||||||
|
checkStrictly: false,
|
||||||
|
fieldType: ['string', 'number', 'boolean', 'any'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'select',
|
type: 'select',
|
||||||
options: (mForm, { model }) => {
|
options: (mForm, { model }) => {
|
||||||
const [id, field] = model.field;
|
const [id, ...fieldNames] = model.field;
|
||||||
|
|
||||||
const ds = dataSourceService.getDataSourceById(id);
|
const ds = dataSourceService.getDataSourceById(id);
|
||||||
|
|
||||||
const type = ds?.fields.find((f) => f.name === field)?.type;
|
let fields = ds?.fields || [];
|
||||||
|
let type = '';
|
||||||
|
(fieldNames || []).forEach((fieldName: string) => {
|
||||||
|
const field = fields.find((f) => f.name === fieldName);
|
||||||
|
fields = field?.fields || [];
|
||||||
|
type = field?.type || '';
|
||||||
|
});
|
||||||
|
|
||||||
if (type === 'array') {
|
if (type === 'array') {
|
||||||
return arrayOptions;
|
return arrayOptions;
|
||||||
@ -287,11 +308,17 @@ export const displayTabConfig: TabPaneConfig = {
|
|||||||
{
|
{
|
||||||
name: 'value',
|
name: 'value',
|
||||||
type: (mForm, { model }) => {
|
type: (mForm, { model }) => {
|
||||||
const [id, field] = model.field;
|
const [id, ...fieldNames] = model.field;
|
||||||
|
|
||||||
const ds = dataSourceService.getDataSourceById(id);
|
const ds = dataSourceService.getDataSourceById(id);
|
||||||
|
|
||||||
const type = ds?.fields.find((f) => f.name === field)?.type;
|
let fields = ds?.fields || [];
|
||||||
|
let type = '';
|
||||||
|
(fieldNames || []).forEach((fieldName: string) => {
|
||||||
|
const field = fields.find((f) => f.name === fieldName);
|
||||||
|
fields = field?.fields || [];
|
||||||
|
type = field?.type || '';
|
||||||
|
});
|
||||||
|
|
||||||
if (type === 'number') {
|
if (type === 'number') {
|
||||||
return 'number';
|
return 'number';
|
||||||
|
@ -72,6 +72,7 @@ import ActionsColumn from './ActionsColumn.vue';
|
|||||||
import ComponentColumn from './ComponentColumn.vue';
|
import ComponentColumn from './ComponentColumn.vue';
|
||||||
import ExpandColumn from './ExpandColumn.vue';
|
import ExpandColumn from './ExpandColumn.vue';
|
||||||
import PopoverColumn from './PopoverColumn.vue';
|
import PopoverColumn from './PopoverColumn.vue';
|
||||||
|
import type { ColumnConfig } from './schema';
|
||||||
import TextColumn from './TextColumn.vue';
|
import TextColumn from './TextColumn.vue';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -81,7 +82,7 @@ defineOptions({
|
|||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
data: any[];
|
data: any[];
|
||||||
columns?: any[];
|
columns?: ColumnConfig[];
|
||||||
/** 合并行或列的计算方法 */
|
/** 合并行或列的计算方法 */
|
||||||
spanMethod?: (data: { row: any; column: any; rowIndex: number; columnIndex: number }) => [number, number];
|
spanMethod?: (data: { row: any; column: any; rowIndex: number; columnIndex: number }) => [number, number];
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
|
@ -21,6 +21,8 @@ import { App } from 'vue';
|
|||||||
import Table from './Table.vue';
|
import Table from './Table.vue';
|
||||||
|
|
||||||
export { default as MagicTable } from './Table.vue';
|
export { default as MagicTable } from './Table.vue';
|
||||||
|
export * from './schema';
|
||||||
|
export * from './utils';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
install(app: App) {
|
install(app: App) {
|
||||||
|
@ -20,10 +20,10 @@ import { FormConfig, FormValue } from '@tmagic/form';
|
|||||||
|
|
||||||
export interface ColumnActionConfig {
|
export interface ColumnActionConfig {
|
||||||
type?: 'delete' | 'copy' | 'edit';
|
type?: 'delete' | 'copy' | 'edit';
|
||||||
buttonType: string;
|
buttonType?: string;
|
||||||
display?: (row: any) => boolean;
|
display?: (row: any) => boolean;
|
||||||
text: string | ((row: any) => string);
|
text?: string | ((row: any) => string);
|
||||||
name: string;
|
name?: string;
|
||||||
tooltip?: string;
|
tooltip?: string;
|
||||||
tooltipPlacement?: string;
|
tooltipPlacement?: string;
|
||||||
icon?: any;
|
icon?: any;
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tmagic/core": "1.3.16",
|
"@tmagic/core": "1.3.16",
|
||||||
"@tmagic/schema": "1.3.16",
|
"@tmagic/schema": "1.3.16",
|
||||||
|
"@tmagic/utils": "1.3.16",
|
||||||
"qrcode": "^1.5.0",
|
"qrcode": "^1.5.0",
|
||||||
"react": "^17.0.0",
|
"react": "^17.0.0",
|
||||||
"react-dom": "^17.0.0"
|
"react-dom": "^17.0.0"
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
import Button from './button';
|
import Button from './button';
|
||||||
import Container from './container';
|
import Container from './container';
|
||||||
import Img from './img';
|
import Img from './img';
|
||||||
|
import IteratorContainer from './iterator-container';
|
||||||
import Overlay from './overlay';
|
import Overlay from './overlay';
|
||||||
import Page from './page';
|
import Page from './page';
|
||||||
import pageFragment from './page-fragment';
|
import pageFragment from './page-fragment';
|
||||||
@ -40,6 +41,7 @@ const ui: Record<string, any> = {
|
|||||||
overlay: Overlay,
|
overlay: Overlay,
|
||||||
'page-fragment': pageFragment,
|
'page-fragment': pageFragment,
|
||||||
'page-fragment-container': pageFragmentContainer,
|
'page-fragment-container': pageFragmentContainer,
|
||||||
|
'iterator-container': IteratorContainer,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ui;
|
export default ui;
|
||||||
|
24
packages/ui-react/src/iterator-container/index.ts
Normal file
24
packages/ui-react/src/iterator-container/index.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import IteratorContainer from './src/IteratorContainer';
|
||||||
|
|
||||||
|
export { default as config } from './src/formConfig';
|
||||||
|
export { default as value } from './src/initValue';
|
||||||
|
|
||||||
|
export default IteratorContainer;
|
@ -0,0 +1,58 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import type { MContainer } from '@tmagic/schema';
|
||||||
|
|
||||||
|
import useApp from '../../useApp';
|
||||||
|
|
||||||
|
interface IteratorContainerProps extends MContainer {
|
||||||
|
config: MContainer & {
|
||||||
|
type: 'iterator-container';
|
||||||
|
iteratorData: any[];
|
||||||
|
dsField: string[];
|
||||||
|
itemConfig: {
|
||||||
|
layout: string;
|
||||||
|
style: Record<string, string | number>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
className: string;
|
||||||
|
style: Record<string, any>;
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const IteratorContainer: React.FC<IteratorContainerProps> = ({ config, id }) => {
|
||||||
|
const { app } = useApp({ config });
|
||||||
|
|
||||||
|
const { iteratorData = [] } = config;
|
||||||
|
|
||||||
|
if (app?.platform === 'editor' && !iteratorData.length) {
|
||||||
|
iteratorData.push({});
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
|
const MagicUiComp = app?.resolveComponent('container');
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
id={`${id || config.id || ''}`}
|
||||||
|
className="magic-ui-iterator-container"
|
||||||
|
style={app?.transformStyle(config.style || {})}
|
||||||
|
>
|
||||||
|
{iteratorData.map((itemData, index) => {
|
||||||
|
const itemConfig = {
|
||||||
|
items: app?.dataSourceManager?.compliedIteratorItems(itemData, config.items, config.dsField) ?? config.items,
|
||||||
|
id: '',
|
||||||
|
style: {
|
||||||
|
...config.itemConfig.style,
|
||||||
|
position: 'relative',
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return <MagicUiComp config={itemConfig} key={index}></MagicUiComp>;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
IteratorContainer.displayName = 'magic-ui-iterator-container';
|
||||||
|
|
||||||
|
export default IteratorContainer;
|
110
packages/ui-react/src/iterator-container/src/formConfig.ts
Normal file
110
packages/ui-react/src/iterator-container/src/formConfig.ts
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import { DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX } from '@tmagic/utils';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
name: 'iteratorData',
|
||||||
|
text: '数据源数据',
|
||||||
|
value: 'value',
|
||||||
|
fieldType: ['array'],
|
||||||
|
checkStrictly: false,
|
||||||
|
type: 'data-source-field-select',
|
||||||
|
onChange: (vm: any, v: string[] = [], { model }: any) => {
|
||||||
|
const [dsId, ...keys] = v;
|
||||||
|
model.dsField = [dsId.replace(DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX, ''), ...keys];
|
||||||
|
return v;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'dsField',
|
||||||
|
type: 'hidden',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'panel',
|
||||||
|
title: '子项配置',
|
||||||
|
name: 'itemConfig',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
name: 'layout',
|
||||||
|
text: '容器布局',
|
||||||
|
type: 'select',
|
||||||
|
defaultValue: 'absolute',
|
||||||
|
options: [
|
||||||
|
{ value: 'absolute', text: '绝对定位' },
|
||||||
|
{ value: 'relative', text: '流式布局', disabled: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'fieldset',
|
||||||
|
legend: '样式',
|
||||||
|
name: 'style',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
name: 'width',
|
||||||
|
text: '宽度',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'height',
|
||||||
|
text: '高度',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'overflow',
|
||||||
|
name: 'overflow',
|
||||||
|
type: 'select',
|
||||||
|
options: [
|
||||||
|
{ text: 'visible', value: 'visible' },
|
||||||
|
{ text: 'hidden', value: 'hidden' },
|
||||||
|
{ text: 'clip', value: 'clip' },
|
||||||
|
{ text: 'scroll', value: 'scroll' },
|
||||||
|
{ text: 'auto', value: 'auto' },
|
||||||
|
{ text: 'overlay', value: 'overlay' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'backgroundImage',
|
||||||
|
text: '背景图',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'backgroundColor',
|
||||||
|
text: '背景颜色',
|
||||||
|
type: 'colorPicker',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'backgroundRepeat',
|
||||||
|
text: '背景图重复',
|
||||||
|
type: 'select',
|
||||||
|
defaultValue: 'no-repeat',
|
||||||
|
options: [
|
||||||
|
{ text: 'repeat', value: 'repeat' },
|
||||||
|
{ text: 'repeat-x', value: 'repeat-x' },
|
||||||
|
{ text: 'repeat-y', value: 'repeat-y' },
|
||||||
|
{ text: 'no-repeat', value: 'no-repeat' },
|
||||||
|
{ text: 'inherit', value: 'inherit' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'backgroundSize',
|
||||||
|
text: '背景图大小',
|
||||||
|
defaultValue: '100% 100%',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
31
packages/ui-react/src/iterator-container/src/initValue.ts
Normal file
31
packages/ui-react/src/iterator-container/src/initValue.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {
|
||||||
|
style: {
|
||||||
|
width: '375',
|
||||||
|
height: '100',
|
||||||
|
},
|
||||||
|
itemConfig: {
|
||||||
|
style: {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
items: [],
|
||||||
|
};
|
@ -19,11 +19,12 @@
|
|||||||
import Button from './button';
|
import Button from './button';
|
||||||
import Container from './container';
|
import Container from './container';
|
||||||
import Img from './img';
|
import Img from './img';
|
||||||
|
import IteratorContainer from './iterator-container';
|
||||||
import Overlay from './overlay';
|
import Overlay from './overlay';
|
||||||
import Page from './page';
|
import Page from './page';
|
||||||
import PageFragment from './page-fragment';
|
import PageFragment from './page-fragment';
|
||||||
import PageFragmentContainer from './page-fragment-container';
|
import PageFragmentContainer from './page-fragment-container';
|
||||||
import Qrcode from './qrcode';
|
import QRcode from './qrcode';
|
||||||
import Text from './text';
|
import Text from './text';
|
||||||
|
|
||||||
const ui: Record<string, any> = {
|
const ui: Record<string, any> = {
|
||||||
@ -32,10 +33,11 @@ const ui: Record<string, any> = {
|
|||||||
button: Button,
|
button: Button,
|
||||||
text: Text,
|
text: Text,
|
||||||
img: Img,
|
img: Img,
|
||||||
qrcode: Qrcode,
|
qrcode: QRcode,
|
||||||
overlay: Overlay,
|
overlay: Overlay,
|
||||||
'page-fragment': PageFragment,
|
|
||||||
'page-fragment-container': PageFragmentContainer,
|
'page-fragment-container': PageFragmentContainer,
|
||||||
|
'page-fragment': PageFragment,
|
||||||
|
'iterator-container': IteratorContainer,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ui;
|
export default ui;
|
||||||
|
24
packages/ui-vue2/src/iterator-container/index.ts
Normal file
24
packages/ui-vue2/src/iterator-container/index.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import IteratorContainer from './src/IteratorContainer.vue';
|
||||||
|
|
||||||
|
export { default as config } from './src/formConfig';
|
||||||
|
export { default as value } from './src/initValue';
|
||||||
|
|
||||||
|
export default IteratorContainer;
|
@ -0,0 +1,63 @@
|
|||||||
|
<template>
|
||||||
|
<div class="magic-ui-iterator-container" :id="`${config.id || ''}`" :style="style">
|
||||||
|
<Container v-for="(item, index) in configs" :key="index" :config="item"></Container>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, inject } from 'vue';
|
||||||
|
|
||||||
|
import Core from '@tmagic/core';
|
||||||
|
import type { MContainer } from '@tmagic/schema';
|
||||||
|
|
||||||
|
import Container from '../../container';
|
||||||
|
import useApp from '../../useApp';
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
config: MContainer & {
|
||||||
|
type: 'iterator-container';
|
||||||
|
iteratorData: any[];
|
||||||
|
dsField: string[];
|
||||||
|
itemConfig: {
|
||||||
|
layout: string;
|
||||||
|
style: Record<string, string | number>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
model?: any;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
model: () => ({}),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const app: Core | undefined = inject('app');
|
||||||
|
|
||||||
|
const style = computed(() => app?.transformStyle(props.config.style || {}));
|
||||||
|
|
||||||
|
const configs = computed(() => {
|
||||||
|
const { iteratorData = [] } = props.config;
|
||||||
|
|
||||||
|
if (app?.platform === 'editor' && !iteratorData.length) {
|
||||||
|
iteratorData.push({});
|
||||||
|
}
|
||||||
|
|
||||||
|
return iteratorData.map((itemData) => ({
|
||||||
|
items:
|
||||||
|
app?.dataSourceManager?.compliedIteratorItems(itemData, props.config.items, props.config.dsField) ??
|
||||||
|
props.config.items,
|
||||||
|
id: '',
|
||||||
|
style: {
|
||||||
|
...props.config.itemConfig.style,
|
||||||
|
position: 'relative',
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
useApp({
|
||||||
|
config: props.config,
|
||||||
|
methods: {},
|
||||||
|
});
|
||||||
|
</script>
|
110
packages/ui-vue2/src/iterator-container/src/formConfig.ts
Normal file
110
packages/ui-vue2/src/iterator-container/src/formConfig.ts
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import { DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX } from '@tmagic/utils';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
name: 'iteratorData',
|
||||||
|
text: '数据源数据',
|
||||||
|
value: 'value',
|
||||||
|
fieldType: ['array'],
|
||||||
|
checkStrictly: false,
|
||||||
|
type: 'data-source-field-select',
|
||||||
|
onChange: (vm: any, v: string[] = [], { model }: any) => {
|
||||||
|
const [dsId, ...keys] = v;
|
||||||
|
model.dsField = [dsId.replace(DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX, ''), ...keys];
|
||||||
|
return v;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'dsField',
|
||||||
|
type: 'hidden',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'panel',
|
||||||
|
title: '子项配置',
|
||||||
|
name: 'itemConfig',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
name: 'layout',
|
||||||
|
text: '容器布局',
|
||||||
|
type: 'select',
|
||||||
|
defaultValue: 'absolute',
|
||||||
|
options: [
|
||||||
|
{ value: 'absolute', text: '绝对定位' },
|
||||||
|
{ value: 'relative', text: '流式布局', disabled: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'fieldset',
|
||||||
|
legend: '样式',
|
||||||
|
name: 'style',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
name: 'width',
|
||||||
|
text: '宽度',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'height',
|
||||||
|
text: '高度',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'overflow',
|
||||||
|
name: 'overflow',
|
||||||
|
type: 'select',
|
||||||
|
options: [
|
||||||
|
{ text: 'visible', value: 'visible' },
|
||||||
|
{ text: 'hidden', value: 'hidden' },
|
||||||
|
{ text: 'clip', value: 'clip' },
|
||||||
|
{ text: 'scroll', value: 'scroll' },
|
||||||
|
{ text: 'auto', value: 'auto' },
|
||||||
|
{ text: 'overlay', value: 'overlay' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'backgroundImage',
|
||||||
|
text: '背景图',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'backgroundColor',
|
||||||
|
text: '背景颜色',
|
||||||
|
type: 'colorPicker',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'backgroundRepeat',
|
||||||
|
text: '背景图重复',
|
||||||
|
type: 'select',
|
||||||
|
defaultValue: 'no-repeat',
|
||||||
|
options: [
|
||||||
|
{ text: 'repeat', value: 'repeat' },
|
||||||
|
{ text: 'repeat-x', value: 'repeat-x' },
|
||||||
|
{ text: 'repeat-y', value: 'repeat-y' },
|
||||||
|
{ text: 'no-repeat', value: 'no-repeat' },
|
||||||
|
{ text: 'inherit', value: 'inherit' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'backgroundSize',
|
||||||
|
text: '背景图大小',
|
||||||
|
defaultValue: '100% 100%',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
31
packages/ui-vue2/src/iterator-container/src/initValue.ts
Normal file
31
packages/ui-vue2/src/iterator-container/src/initValue.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {
|
||||||
|
style: {
|
||||||
|
width: '375',
|
||||||
|
height: '100',
|
||||||
|
},
|
||||||
|
itemConfig: {
|
||||||
|
style: {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
items: [],
|
||||||
|
};
|
@ -19,11 +19,12 @@
|
|||||||
import Button from './button';
|
import Button from './button';
|
||||||
import Container from './container';
|
import Container from './container';
|
||||||
import Img from './img';
|
import Img from './img';
|
||||||
|
import IteratorContainer from './iterator-container';
|
||||||
import Overlay from './overlay';
|
import Overlay from './overlay';
|
||||||
import Page from './page';
|
import Page from './page';
|
||||||
import PageFragment from './page-fragment';
|
import PageFragment from './page-fragment';
|
||||||
import PageFragmentContainer from './page-fragment-container';
|
import PageFragmentContainer from './page-fragment-container';
|
||||||
import Qrcode from './qrcode';
|
import QRcode from './qrcode';
|
||||||
import Text from './text';
|
import Text from './text';
|
||||||
|
|
||||||
const ui: Record<string, any> = {
|
const ui: Record<string, any> = {
|
||||||
@ -32,10 +33,11 @@ const ui: Record<string, any> = {
|
|||||||
button: Button,
|
button: Button,
|
||||||
text: Text,
|
text: Text,
|
||||||
img: Img,
|
img: Img,
|
||||||
qrcode: Qrcode,
|
qrcode: QRcode,
|
||||||
overlay: Overlay,
|
overlay: Overlay,
|
||||||
'page-fragment-container': PageFragmentContainer,
|
'page-fragment-container': PageFragmentContainer,
|
||||||
'page-fragment': PageFragment,
|
'page-fragment': PageFragment,
|
||||||
|
'iterator-container': IteratorContainer,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ui;
|
export default ui;
|
||||||
|
24
packages/ui/src/iterator-container/index.ts
Normal file
24
packages/ui/src/iterator-container/index.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import IteratorContainer from './src/IteratorContainer.vue';
|
||||||
|
|
||||||
|
export { default as config } from './src/formConfig';
|
||||||
|
export { default as value } from './src/initValue';
|
||||||
|
|
||||||
|
export default IteratorContainer;
|
63
packages/ui/src/iterator-container/src/IteratorContainer.vue
Normal file
63
packages/ui/src/iterator-container/src/IteratorContainer.vue
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<template>
|
||||||
|
<div class="magic-ui-iterator-container" :id="`${config.id || ''}`" :style="style">
|
||||||
|
<Container v-for="(item, index) in configs" :key="index" :config="item"></Container>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, inject } from 'vue';
|
||||||
|
|
||||||
|
import Core from '@tmagic/core';
|
||||||
|
import type { MContainer } from '@tmagic/schema';
|
||||||
|
|
||||||
|
import Container from '../../container';
|
||||||
|
import useApp from '../../useApp';
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
config: MContainer & {
|
||||||
|
type: 'iterator-container';
|
||||||
|
iteratorData: any[];
|
||||||
|
dsField: string[];
|
||||||
|
itemConfig: {
|
||||||
|
layout: string;
|
||||||
|
style: Record<string, string | number>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
model?: any;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
model: () => ({}),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const app: Core | undefined = inject('app');
|
||||||
|
|
||||||
|
const style = computed(() => app?.transformStyle(props.config.style || {}));
|
||||||
|
|
||||||
|
const configs = computed(() => {
|
||||||
|
const { iteratorData = [] } = props.config;
|
||||||
|
|
||||||
|
if (app?.platform === 'editor' && !iteratorData.length) {
|
||||||
|
iteratorData.push({});
|
||||||
|
}
|
||||||
|
|
||||||
|
return iteratorData.map((itemData) => ({
|
||||||
|
items:
|
||||||
|
app?.dataSourceManager?.compliedIteratorItems(itemData, props.config.items, props.config.dsField) ??
|
||||||
|
props.config.items,
|
||||||
|
id: '',
|
||||||
|
style: {
|
||||||
|
...props.config.itemConfig.style,
|
||||||
|
position: 'relative',
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
useApp({
|
||||||
|
config: props.config,
|
||||||
|
methods: {},
|
||||||
|
});
|
||||||
|
</script>
|
110
packages/ui/src/iterator-container/src/formConfig.ts
Normal file
110
packages/ui/src/iterator-container/src/formConfig.ts
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import { DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX } from '@tmagic/utils';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
name: 'iteratorData',
|
||||||
|
text: '数据源数据',
|
||||||
|
value: 'value',
|
||||||
|
fieldType: ['array'],
|
||||||
|
checkStrictly: false,
|
||||||
|
type: 'data-source-field-select',
|
||||||
|
onChange: (vm: any, v: string[] = [], { model }: any) => {
|
||||||
|
const [dsId, ...keys] = v;
|
||||||
|
model.dsField = [dsId.replace(DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX, ''), ...keys];
|
||||||
|
return v;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'dsField',
|
||||||
|
type: 'hidden',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'panel',
|
||||||
|
title: '子项配置',
|
||||||
|
name: 'itemConfig',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
name: 'layout',
|
||||||
|
text: '容器布局',
|
||||||
|
type: 'select',
|
||||||
|
defaultValue: 'absolute',
|
||||||
|
options: [
|
||||||
|
{ value: 'absolute', text: '绝对定位' },
|
||||||
|
{ value: 'relative', text: '流式布局', disabled: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'fieldset',
|
||||||
|
legend: '样式',
|
||||||
|
name: 'style',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
name: 'width',
|
||||||
|
text: '宽度',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'height',
|
||||||
|
text: '高度',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'overflow',
|
||||||
|
name: 'overflow',
|
||||||
|
type: 'select',
|
||||||
|
options: [
|
||||||
|
{ text: 'visible', value: 'visible' },
|
||||||
|
{ text: 'hidden', value: 'hidden' },
|
||||||
|
{ text: 'clip', value: 'clip' },
|
||||||
|
{ text: 'scroll', value: 'scroll' },
|
||||||
|
{ text: 'auto', value: 'auto' },
|
||||||
|
{ text: 'overlay', value: 'overlay' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'backgroundImage',
|
||||||
|
text: '背景图',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'backgroundColor',
|
||||||
|
text: '背景颜色',
|
||||||
|
type: 'colorPicker',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'backgroundRepeat',
|
||||||
|
text: '背景图重复',
|
||||||
|
type: 'select',
|
||||||
|
defaultValue: 'no-repeat',
|
||||||
|
options: [
|
||||||
|
{ text: 'repeat', value: 'repeat' },
|
||||||
|
{ text: 'repeat-x', value: 'repeat-x' },
|
||||||
|
{ text: 'repeat-y', value: 'repeat-y' },
|
||||||
|
{ text: 'no-repeat', value: 'no-repeat' },
|
||||||
|
{ text: 'inherit', value: 'inherit' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'backgroundSize',
|
||||||
|
text: '背景图大小',
|
||||||
|
defaultValue: '100% 100%',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
31
packages/ui/src/iterator-container/src/initValue.ts
Normal file
31
packages/ui/src/iterator-container/src/initValue.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {
|
||||||
|
style: {
|
||||||
|
width: '375',
|
||||||
|
height: '100',
|
||||||
|
},
|
||||||
|
itemConfig: {
|
||||||
|
style: {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
items: [],
|
||||||
|
};
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import utc from 'dayjs/plugin/utc';
|
import utc from 'dayjs/plugin/utc';
|
||||||
import { cloneDeep, get as objectGet, set as objectSet } from 'lodash-es';
|
import { cloneDeep, set as objectSet } from 'lodash-es';
|
||||||
|
|
||||||
import type { DataSchema, DataSourceDeps, Id, MComponent, MNode } from '@tmagic/schema';
|
import type { DataSchema, DataSourceDeps, Id, MComponent, MNode } from '@tmagic/schema';
|
||||||
import { NodeType } from '@tmagic/schema';
|
import { NodeType } from '@tmagic/schema';
|
||||||
@ -165,7 +165,18 @@ export const guid = (digit = 8): string =>
|
|||||||
return v.toString(16);
|
return v.toString(16);
|
||||||
});
|
});
|
||||||
|
|
||||||
export const getValueByKeyPath: any = (keys: string, data: Record<string | number, any> = {}) => objectGet(data, keys);
|
export const getValueByKeyPath: any = (keys = '', data: Record<string | number, any> = {}) =>
|
||||||
|
// 将 array[0] 转成 array.0
|
||||||
|
keys
|
||||||
|
.replaceAll(/\[(\d+)\]/g, '.$1')
|
||||||
|
.split('.')
|
||||||
|
.reduce((accumulator, currentValue: any) => {
|
||||||
|
if (isObject(accumulator) || Array.isArray(accumulator)) {
|
||||||
|
return accumulator[currentValue];
|
||||||
|
}
|
||||||
|
|
||||||
|
return void 0;
|
||||||
|
}, data);
|
||||||
|
|
||||||
export const setValueByKeyPath: any = (keys: string, value: any, data: Record<string | number, any> = {}) =>
|
export const setValueByKeyPath: any = (keys: string, value: any, data: Record<string | number, any> = {}) =>
|
||||||
objectSet(data, keys, value);
|
objectSet(data, keys, value);
|
||||||
@ -238,6 +249,8 @@ export const replaceChildNode = (newNode: MNode, data?: MNode[], parentId?: Id)
|
|||||||
parent.items.splice(index, 1, newNode);
|
parent.items.splice(index, 1, newNode);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const DSL_NODE_KEY_COPY_PREFIX = '__magic__';
|
||||||
|
|
||||||
export const compiledNode = (
|
export const compiledNode = (
|
||||||
compile: (value: any) => any,
|
compile: (value: any) => any,
|
||||||
node: MNode,
|
node: MNode,
|
||||||
@ -252,10 +265,8 @@ export const compiledNode = (
|
|||||||
keys = dep?.[node.id].keys || [];
|
keys = dep?.[node.id].keys || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const keyPrefix = '__magic__';
|
|
||||||
|
|
||||||
keys.forEach((key) => {
|
keys.forEach((key) => {
|
||||||
const cacheKey = `${keyPrefix}${key}`;
|
const cacheKey = `${DSL_NODE_KEY_COPY_PREFIX}${key}`;
|
||||||
|
|
||||||
const value = getValueByKeyPath(key, node);
|
const value = getValueByKeyPath(key, node);
|
||||||
let templateValue = getValueByKeyPath(cacheKey, node);
|
let templateValue = getValueByKeyPath(cacheKey, node);
|
||||||
@ -276,10 +287,6 @@ export const compiledNode = (
|
|||||||
setValueByKeyPath(key, newValue, node);
|
setValueByKeyPath(key, newValue, node);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (Array.isArray(node.items)) {
|
|
||||||
node.items.forEach((item) => compiledNode(compile, item, dataSourceDeps));
|
|
||||||
}
|
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss" scoped>
|
||||||
.m-editor-nav-menu {
|
.m-editor-nav-menu {
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { FolderOpened, Grid, PictureFilled, SwitchButton, Ticket, Tickets } from '@element-plus/icons-vue';
|
import { Files, FolderOpened, Grid, PictureFilled, SwitchButton, Ticket, Tickets } from '@element-plus/icons-vue';
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
@ -19,6 +19,11 @@ export default [
|
|||||||
text: '页面片容器',
|
text: '页面片容器',
|
||||||
type: 'page-fragment-container',
|
type: 'page-fragment-container',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
icon: Files,
|
||||||
|
text: '迭代器容器',
|
||||||
|
type: 'iterator-container',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -82,11 +82,6 @@ export default {
|
|||||||
age: 12, // 参数
|
age: 12, // 参数
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
actionType: 'comp',
|
|
||||||
to: 'overlay_2159', // 联动组件id
|
|
||||||
method: 'openOverlay', // 联动组件方法
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -369,13 +364,67 @@ export default {
|
|||||||
description: '按钮',
|
description: '按钮',
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
type: 'string',
|
|
||||||
name: 'text',
|
name: 'text',
|
||||||
title: '按钮文案',
|
title: '按钮文案',
|
||||||
|
type: 'string',
|
||||||
description: '',
|
description: '',
|
||||||
|
enable: true,
|
||||||
defaultValue: '打开弹窗',
|
defaultValue: '打开弹窗',
|
||||||
|
fields: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'array',
|
||||||
|
title: 'array',
|
||||||
|
type: 'array',
|
||||||
|
description: '',
|
||||||
|
enable: true,
|
||||||
|
defaultValue: [
|
||||||
|
{
|
||||||
|
a: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
a: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'a',
|
||||||
|
title: 'a',
|
||||||
|
type: 'number',
|
||||||
|
description: '',
|
||||||
|
enable: true,
|
||||||
|
defaultValue: 1,
|
||||||
|
fields: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'object',
|
||||||
|
title: 'object',
|
||||||
|
type: 'object',
|
||||||
|
description: '',
|
||||||
|
enable: true,
|
||||||
|
defaultValue: {
|
||||||
|
a: 1,
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'a',
|
||||||
|
title: 'a',
|
||||||
|
type: 'number',
|
||||||
|
description: '',
|
||||||
|
enable: true,
|
||||||
|
defaultValue: 1,
|
||||||
|
fields: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
methods: [],
|
||||||
|
events: '',
|
||||||
|
mocks: [],
|
||||||
|
beforeRequest: '',
|
||||||
|
afterResponse: '',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
dataSourceDeps: {
|
dataSourceDeps: {
|
||||||
|
3
pnpm-lock.yaml
generated
3
pnpm-lock.yaml
generated
@ -668,6 +668,9 @@ importers:
|
|||||||
'@tmagic/schema':
|
'@tmagic/schema':
|
||||||
specifier: 1.3.16
|
specifier: 1.3.16
|
||||||
version: link:../schema
|
version: link:../schema
|
||||||
|
'@tmagic/utils':
|
||||||
|
specifier: 1.3.16
|
||||||
|
version: link:../utils
|
||||||
qrcode:
|
qrcode:
|
||||||
specifier: ^1.5.0
|
specifier: ^1.5.0
|
||||||
version: 1.5.0
|
version: 1.5.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user