mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2025-04-06 03:57:56 +08:00
feat(data-source,utils,runtime): 数据源setData支持指定路径
This commit is contained in:
parent
6b4bfae30b
commit
d3777b236d
@ -38,7 +38,7 @@ import {
|
|||||||
|
|
||||||
import Env from './Env';
|
import Env from './Env';
|
||||||
import { bindCommonEventListener, isCommonMethod, triggerCommonMethod } from './events';
|
import { bindCommonEventListener, isCommonMethod, triggerCommonMethod } from './events';
|
||||||
import type Node from './Node';
|
import Node from './Node';
|
||||||
import Page from './Page';
|
import Page from './Page';
|
||||||
import { fillBackgroundImage, isNumber, style2Obj } from './utils';
|
import { fillBackgroundImage, isNumber, style2Obj } from './utils';
|
||||||
|
|
||||||
@ -265,20 +265,21 @@ class App extends EventEmitter implements AppCore {
|
|||||||
for (const [, value] of this.page.nodes) {
|
for (const [, value] of this.page.nodes) {
|
||||||
value.events?.forEach((event) => {
|
value.events?.forEach((event) => {
|
||||||
const eventName = `${event.name}_${value.data.id}`;
|
const eventName = `${event.name}_${value.data.id}`;
|
||||||
const eventHanlder = (fromCpt: Node, ...args: any[]) => {
|
const eventHandler = (fromCpt: Node, ...args: any[]) => {
|
||||||
this.eventHandler(event, fromCpt, args);
|
this.eventHandler(event, fromCpt, args);
|
||||||
};
|
};
|
||||||
this.eventList.set(eventHanlder, eventName);
|
this.eventList.set(eventHandler, eventName);
|
||||||
this.on(eventName, eventHanlder);
|
this.on(eventName, eventHandler);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public emit(name: string | symbol, node: any, ...args: any[]): boolean {
|
public emit(name: string | symbol, ...args: any[]): boolean {
|
||||||
if (node?.data?.id) {
|
const [node, ...otherArgs] = args;
|
||||||
return super.emit(`${String(name)}_${node.data.id}`, node, ...args);
|
if (node instanceof Node && node?.data?.id) {
|
||||||
|
return super.emit(`${String(name)}_${node.data.id}`, node, ...otherArgs);
|
||||||
}
|
}
|
||||||
return super.emit(name, node, ...args);
|
return super.emit(name, ...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,7 +24,7 @@ import type { AppCore, DataSourceSchema, Id, MNode } from '@tmagic/schema';
|
|||||||
import { compiledCond, compiledNode, DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX, isObject } from '@tmagic/utils';
|
import { compiledCond, compiledNode, DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX, isObject } from '@tmagic/utils';
|
||||||
|
|
||||||
import { DataSource, HttpDataSource } from './data-sources';
|
import { DataSource, HttpDataSource } from './data-sources';
|
||||||
import type { DataSourceManagerData, DataSourceManagerOptions } from './types';
|
import type { ChangeEvent, DataSourceManagerData, DataSourceManagerOptions } from './types';
|
||||||
|
|
||||||
class DataSourceManager extends EventEmitter {
|
class DataSourceManager extends EventEmitter {
|
||||||
private static dataSourceClassMap = new Map<string, typeof DataSource>();
|
private static dataSourceClassMap = new Map<string, typeof DataSource>();
|
||||||
@ -123,14 +123,14 @@ class DataSourceManager extends EventEmitter {
|
|||||||
|
|
||||||
this.data[ds.id] = ds.data;
|
this.data[ds.id] = ds.data;
|
||||||
|
|
||||||
ds.on('change', () => {
|
ds.on('change', (changeEvent: ChangeEvent) => {
|
||||||
this.setData(ds);
|
this.setData(ds, changeEvent);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public setData(ds: DataSource) {
|
public setData(ds: DataSource, changeEvent: ChangeEvent) {
|
||||||
Object.assign(this.data[ds.id], ds.data);
|
this.data[ds.id] = ds.data;
|
||||||
this.emit('change', ds.id);
|
this.emit('change', ds.id, changeEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeDataSource(id: string) {
|
public removeDataSource(id: string) {
|
||||||
|
@ -21,7 +21,7 @@ import type { AppCore } from '@tmagic/schema';
|
|||||||
import { getDepNodeIds, getNodes, replaceChildNode } from '@tmagic/utils';
|
import { getDepNodeIds, getNodes, replaceChildNode } from '@tmagic/utils';
|
||||||
|
|
||||||
import DataSourceManager from './DataSourceManager';
|
import DataSourceManager from './DataSourceManager';
|
||||||
import { DataSourceManagerData } from './types';
|
import type { ChangeEvent, DataSourceManagerData } from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建数据源管理器
|
* 创建数据源管理器
|
||||||
@ -52,7 +52,7 @@ export const createDataSourceManager = (app: AppCore, useMock?: boolean, initial
|
|||||||
// ssr环境下,数据应该是提前准备好的(放到initialData中),不应该发生变化,无需监听
|
// ssr环境下,数据应该是提前准备好的(放到initialData中),不应该发生变化,无需监听
|
||||||
// 有initialData不一定是在ssr环境下
|
// 有initialData不一定是在ssr环境下
|
||||||
if (app.jsEngine !== 'nodejs') {
|
if (app.jsEngine !== 'nodejs') {
|
||||||
dataSourceManager.on('change', (sourceId: string) => {
|
dataSourceManager.on('change', (sourceId: string, changeEvent: ChangeEvent) => {
|
||||||
const dep = dsl.dataSourceDeps?.[sourceId] || {};
|
const dep = dsl.dataSourceDeps?.[sourceId] || {};
|
||||||
const condDep = dsl.dataSourceCondDeps?.[sourceId] || {};
|
const condDep = dsl.dataSourceCondDeps?.[sourceId] || {};
|
||||||
|
|
||||||
@ -66,6 +66,7 @@ export const createDataSourceManager = (app: AppCore, useMock?: boolean, initial
|
|||||||
return dataSourceManager.compiledNode(newNode);
|
return dataSourceManager.compiledNode(newNode);
|
||||||
}),
|
}),
|
||||||
sourceId,
|
sourceId,
|
||||||
|
changeEvent,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,9 @@
|
|||||||
import EventEmitter from 'events';
|
import EventEmitter from 'events';
|
||||||
|
|
||||||
import type { AppCore, CodeBlockContent, DataSchema, DataSourceSchema } from '@tmagic/schema';
|
import type { AppCore, CodeBlockContent, DataSchema, DataSourceSchema } from '@tmagic/schema';
|
||||||
import { getDefaultValueFromFields } from '@tmagic/utils';
|
import { getDefaultValueFromFields, setValueByKeyPath } from '@tmagic/utils';
|
||||||
|
|
||||||
import type { DataSourceOptions } from '@data-source/types';
|
import type { ChangeEvent, DataSourceOptions } from '@data-source/types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 静态数据源
|
* 静态数据源
|
||||||
@ -101,10 +101,20 @@ export default class DataSource<T extends DataSourceSchema = DataSourceSchema> e
|
|||||||
this.#methods = methods;
|
this.#methods = methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setData(data: Record<string, any>) {
|
public setData(data: any, path?: string) {
|
||||||
// todo: 校验数据,看是否符合 schema
|
if (path) {
|
||||||
this.data = data;
|
setValueByKeyPath(path, data, this.data);
|
||||||
this.emit('change');
|
} else {
|
||||||
|
// todo: 校验数据,看是否符合 schema
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const changeEvent: ChangeEvent = {
|
||||||
|
updateData: data,
|
||||||
|
path,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.emit('change', changeEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getDefaultData() {
|
public getDefaultData() {
|
||||||
|
@ -37,3 +37,8 @@ export interface DataSourceManagerOptions {
|
|||||||
export interface DataSourceManagerData {
|
export interface DataSourceManagerData {
|
||||||
[key: string]: Record<string, any>;
|
[key: string]: Record<string, any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ChangeEvent {
|
||||||
|
path?: string;
|
||||||
|
updateData: any;
|
||||||
|
}
|
||||||
|
@ -34,3 +34,74 @@ describe('DataSource', () => {
|
|||||||
expect(ds.isInit).toBeTruthy();
|
expect(ds.isInit).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('DataSource setData', () => {
|
||||||
|
test('setData', () => {
|
||||||
|
const ds = new DataSource({
|
||||||
|
schema: {
|
||||||
|
type: 'base',
|
||||||
|
id: '1',
|
||||||
|
fields: [{ name: 'name', defaultValue: 'name' }],
|
||||||
|
methods: [],
|
||||||
|
},
|
||||||
|
app: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
ds.init();
|
||||||
|
|
||||||
|
expect(ds.data.name).toBe('name');
|
||||||
|
|
||||||
|
ds.setData({ name: 'name2' });
|
||||||
|
|
||||||
|
expect(ds.data.name).toBe('name2');
|
||||||
|
|
||||||
|
ds.setData('name3', 'name');
|
||||||
|
|
||||||
|
expect(ds.data.name).toBe('name3');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('setDataByPath', () => {
|
||||||
|
const ds = new DataSource({
|
||||||
|
schema: {
|
||||||
|
type: 'base',
|
||||||
|
id: '1',
|
||||||
|
fields: [
|
||||||
|
{ name: 'name', defaultValue: 'name' },
|
||||||
|
{
|
||||||
|
name: 'obj',
|
||||||
|
type: 'object',
|
||||||
|
fields: [{ name: 'a' }, { name: 'b', type: 'array', fields: [{ name: 'c' }] }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
methods: [],
|
||||||
|
},
|
||||||
|
app: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
ds.init();
|
||||||
|
|
||||||
|
expect(ds.data.name).toBe('name');
|
||||||
|
expect(ds.data.obj.b).toHaveLength(0);
|
||||||
|
|
||||||
|
ds.setData({
|
||||||
|
name: 'name',
|
||||||
|
obj: {
|
||||||
|
a: 'a',
|
||||||
|
b: [
|
||||||
|
{
|
||||||
|
c: 'c',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(ds.data.obj.b).toHaveLength(1);
|
||||||
|
expect(ds.data.obj.b[0].c).toBe('c');
|
||||||
|
|
||||||
|
ds.setData('c1', 'obj.b.0.c');
|
||||||
|
expect(ds.data.obj.b[0].c).toBe('c1');
|
||||||
|
expect(ds.data.obj.a).toBe('a');
|
||||||
|
ds.setData('a1', 'obj.a');
|
||||||
|
expect(ds.data.obj.a).toBe('a1');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -17,12 +17,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { reactive } from 'vue';
|
import { reactive } from 'vue';
|
||||||
import { cloneDeep, get, mergeWith, set } from 'lodash-es';
|
import { cloneDeep, mergeWith } from 'lodash-es';
|
||||||
|
|
||||||
import { DepTargetType } from '@tmagic/dep';
|
import { DepTargetType } from '@tmagic/dep';
|
||||||
import type { FormConfig } from '@tmagic/form';
|
import type { FormConfig } from '@tmagic/form';
|
||||||
import type { Id, MComponent, MNode } from '@tmagic/schema';
|
import type { Id, MComponent, MNode } from '@tmagic/schema';
|
||||||
import { guid, toLine } from '@tmagic/utils';
|
import { getValueByKeyPath, guid, setValueByKeyPath, toLine } from '@tmagic/utils';
|
||||||
|
|
||||||
import depService from '@editor/services/dep';
|
import depService from '@editor/services/dep';
|
||||||
import editorService from '@editor/services/editor';
|
import editorService from '@editor/services/editor';
|
||||||
@ -194,17 +194,22 @@ class Props extends BaseService {
|
|||||||
public replaceRelateId(originConfigs: MNode[], targetConfigs: MNode[]) {
|
public replaceRelateId(originConfigs: MNode[], targetConfigs: MNode[]) {
|
||||||
const relateIdMap = this.getRelateIdMap();
|
const relateIdMap = this.getRelateIdMap();
|
||||||
if (Object.keys(relateIdMap).length === 0) return;
|
if (Object.keys(relateIdMap).length === 0) return;
|
||||||
|
|
||||||
const target = depService.getTarget(DepTargetType.RELATED_COMP_WHEN_COPY, DepTargetType.RELATED_COMP_WHEN_COPY);
|
const target = depService.getTarget(DepTargetType.RELATED_COMP_WHEN_COPY, DepTargetType.RELATED_COMP_WHEN_COPY);
|
||||||
if (!target) return;
|
if (!target) return;
|
||||||
|
|
||||||
originConfigs.forEach((config: MNode) => {
|
originConfigs.forEach((config: MNode) => {
|
||||||
const newId = relateIdMap[config.id];
|
const newId = relateIdMap[config.id];
|
||||||
const targetConfig = targetConfigs.find((targetConfig) => targetConfig.id === newId);
|
const targetConfig = targetConfigs.find((targetConfig) => targetConfig.id === newId);
|
||||||
|
|
||||||
if (!targetConfig) return;
|
if (!targetConfig) return;
|
||||||
|
|
||||||
target.deps[config.id]?.keys?.forEach((fullKey) => {
|
target.deps[config.id]?.keys?.forEach((fullKey) => {
|
||||||
const relateOriginId = get(config, fullKey);
|
const relateOriginId = getValueByKeyPath(fullKey, config);
|
||||||
const relateTargetId = relateIdMap[relateOriginId];
|
const relateTargetId = relateIdMap[relateOriginId];
|
||||||
if (!relateTargetId) return;
|
if (!relateTargetId) return;
|
||||||
set(targetConfig, fullKey, relateTargetId);
|
|
||||||
|
setValueByKeyPath(fullKey, relateTargetId, targetConfig);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -31,12 +31,14 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tmagic/schema": "1.3.8",
|
"@tmagic/schema": "1.3.8",
|
||||||
"dayjs": "^1.11.4"
|
"dayjs": "^1.11.4",
|
||||||
|
"lodash-es": "^4.17.21"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"dayjs": "^1.11.4"
|
"dayjs": "^1.11.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/lodash-es": "^4.17.4",
|
||||||
"@types/node": "^18.19.0",
|
"@types/node": "^18.19.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"typescript": "^5.0.4",
|
"typescript": "^5.0.4",
|
||||||
|
@ -18,6 +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 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';
|
||||||
@ -164,22 +165,10 @@ export const guid = (digit = 8): string =>
|
|||||||
return v.toString(16);
|
return v.toString(16);
|
||||||
});
|
});
|
||||||
|
|
||||||
export const getValueByKeyPath: any = (keys: string, value: Record<string | number, any> = {}) => {
|
export const getValueByKeyPath: any = (keys: string, data: Record<string | number, any> = {}) => objectGet(data, keys);
|
||||||
const path = keys.split('.');
|
|
||||||
const pathLength = path.length;
|
|
||||||
|
|
||||||
return path.reduce((accumulator, currentValue: any, currentIndex: number) => {
|
export const setValueByKeyPath: any = (keys: string, value: any, data: Record<string | number, any> = {}) =>
|
||||||
if (Object.prototype.toString.call(accumulator) === '[object Object]' || Array.isArray(accumulator)) {
|
objectSet(data, keys, value);
|
||||||
return accumulator[currentValue];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pathLength - 1 === currentIndex) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}, value);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getNodes = (ids: Id[], data: MNode[] = []): MNode[] => {
|
export const getNodes = (ids: Id[], data: MNode[] = []): MNode[] => {
|
||||||
const nodes: MNode[] = [];
|
const nodes: MNode[] = [];
|
||||||
@ -266,32 +255,25 @@ export const compiledNode = (
|
|||||||
const keyPrefix = '__magic__';
|
const keyPrefix = '__magic__';
|
||||||
|
|
||||||
keys.forEach((key) => {
|
keys.forEach((key) => {
|
||||||
const keyPath = `${key}`.split('.');
|
const cacheKey = `${keyPrefix}${key}`;
|
||||||
const keyPathLength = keyPath.length;
|
|
||||||
keyPath.reduce((accumulator, currentValue: any, currentIndex) => {
|
|
||||||
if (keyPathLength - 1 === currentIndex) {
|
|
||||||
const cacheKey = `${keyPrefix}${currentValue}`;
|
|
||||||
|
|
||||||
if (typeof accumulator[cacheKey] === 'undefined') {
|
const value = getValueByKeyPath(key, node);
|
||||||
accumulator[cacheKey] = accumulator[currentValue];
|
let templateValue = getValueByKeyPath(cacheKey, node);
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
if (typeof templateValue === 'undefined') {
|
||||||
accumulator[currentValue] = compile(accumulator[cacheKey]);
|
setValueByKeyPath(cacheKey, value, node);
|
||||||
} catch (e) {
|
templateValue = value;
|
||||||
console.error(e);
|
}
|
||||||
accumulator[currentValue] = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
return accumulator;
|
let newValue;
|
||||||
}
|
try {
|
||||||
|
newValue = compile(templateValue);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
newValue = '';
|
||||||
|
}
|
||||||
|
|
||||||
if (isObject(accumulator) || Array.isArray(accumulator)) {
|
setValueByKeyPath(key, newValue, node);
|
||||||
return accumulator[currentValue];
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}, node);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (Array.isArray(node.items)) {
|
if (Array.isArray(node.items)) {
|
||||||
@ -368,7 +350,8 @@ export const getDefaultValueFromFields = (fields: DataSchema[]) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
data[field.name] = field.defaultValue;
|
data[field.name] = cloneDeep(field.defaultValue);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,6 +331,28 @@ describe('getValueByKeyPath', () => {
|
|||||||
expect(value).toBe(1);
|
expect(value).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('array', () => {
|
||||||
|
const value = util.getValueByKeyPath('a.0.b', {
|
||||||
|
a: [
|
||||||
|
{
|
||||||
|
b: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(value).toBe(1);
|
||||||
|
|
||||||
|
const value1 = util.getValueByKeyPath('a[0].b', {
|
||||||
|
a: [
|
||||||
|
{
|
||||||
|
b: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(value1).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
test('error', () => {
|
test('error', () => {
|
||||||
const value = util.getValueByKeyPath('a.b.c.d', {
|
const value = util.getValueByKeyPath('a.b.c.d', {
|
||||||
a: {},
|
a: {},
|
||||||
@ -475,7 +497,7 @@ describe('replaceChildNode', () => {
|
|||||||
expect(root[1].items[0].items[0].text).toBe('文本');
|
expect(root[1].items[0].items[0].text).toBe('文本');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('replace whith parent', () => {
|
test('replace with parent', () => {
|
||||||
const root = [
|
const root = [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
@ -532,19 +554,21 @@ describe('compiledNode', () => {
|
|||||||
{
|
{
|
||||||
id: 61705611,
|
id: 61705611,
|
||||||
type: 'text',
|
type: 'text',
|
||||||
text: '456',
|
text: {
|
||||||
|
value: '456',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ds_bebcb2d5: {
|
ds_bebcb2d5: {
|
||||||
61705611: {
|
61705611: {
|
||||||
name: '文本',
|
name: '文本',
|
||||||
keys: ['text'],
|
keys: ['text.value'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(node.text).toBe('123');
|
expect(node.text.value).toBe('123');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('compile with source id', () => {
|
test('compile with source id', () => {
|
||||||
@ -595,61 +619,61 @@ describe('compiledNode', () => {
|
|||||||
|
|
||||||
describe('getDefaultValueFromFields', () => {
|
describe('getDefaultValueFromFields', () => {
|
||||||
test('最简单', () => {
|
test('最简单', () => {
|
||||||
const fileds = [
|
const fields = [
|
||||||
{
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const data = util.getDefaultValueFromFields(fileds);
|
const data = util.getDefaultValueFromFields(fields);
|
||||||
expect(data).toHaveProperty('name');
|
expect(data).toHaveProperty('name');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('默认值为string', () => {
|
test('默认值为string', () => {
|
||||||
const fileds = [
|
const fields = [
|
||||||
{
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
defaultValue: 'name',
|
defaultValue: 'name',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const data = util.getDefaultValueFromFields(fileds);
|
const data = util.getDefaultValueFromFields(fields);
|
||||||
expect(data.name).toBe('name');
|
expect(data.name).toBe('name');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('type 为 object', () => {
|
test('type 为 object', () => {
|
||||||
const fileds: DataSchema[] = [
|
const fields: DataSchema[] = [
|
||||||
{
|
{
|
||||||
type: 'object',
|
type: 'object',
|
||||||
name: 'name',
|
name: 'name',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const data = util.getDefaultValueFromFields(fileds);
|
const data = util.getDefaultValueFromFields(fields);
|
||||||
expect(data.name).toEqual({});
|
expect(data.name).toEqual({});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('type 为 array', () => {
|
test('type 为 array', () => {
|
||||||
const fileds: DataSchema[] = [
|
const fields: DataSchema[] = [
|
||||||
{
|
{
|
||||||
type: 'array',
|
type: 'array',
|
||||||
name: 'name',
|
name: 'name',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const data = util.getDefaultValueFromFields(fileds);
|
const data = util.getDefaultValueFromFields(fields);
|
||||||
expect(data.name).toEqual([]);
|
expect(data.name).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('type 为 null', () => {
|
test('type 为 null', () => {
|
||||||
const fileds: DataSchema[] = [
|
const fields: DataSchema[] = [
|
||||||
{
|
{
|
||||||
type: 'null',
|
type: 'null',
|
||||||
name: 'name',
|
name: 'name',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const data = util.getDefaultValueFromFields(fileds);
|
const data = util.getDefaultValueFromFields(fields);
|
||||||
expect(data.name).toBeNull();
|
expect(data.name).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('object 嵌套', () => {
|
test('object 嵌套', () => {
|
||||||
const fileds: DataSchema[] = [
|
const fields: DataSchema[] = [
|
||||||
{
|
{
|
||||||
type: 'object',
|
type: 'object',
|
||||||
name: 'name',
|
name: 'name',
|
||||||
@ -661,7 +685,7 @@ describe('getDefaultValueFromFields', () => {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const data = util.getDefaultValueFromFields(fileds);
|
const data = util.getDefaultValueFromFields(fields);
|
||||||
expect(data.name.key).toBe('key');
|
expect(data.name.key).toBe('key');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
14
pnpm-lock.yaml
generated
14
pnpm-lock.yaml
generated
@ -1,5 +1,9 @@
|
|||||||
lockfileVersion: '6.0'
|
lockfileVersion: '6.0'
|
||||||
|
|
||||||
|
settings:
|
||||||
|
autoInstallPeers: true
|
||||||
|
excludeLinksFromLockfile: false
|
||||||
|
|
||||||
importers:
|
importers:
|
||||||
|
|
||||||
.:
|
.:
|
||||||
@ -711,7 +715,13 @@ importers:
|
|||||||
dayjs:
|
dayjs:
|
||||||
specifier: ^1.11.4
|
specifier: ^1.11.4
|
||||||
version: 1.11.4
|
version: 1.11.4
|
||||||
|
lodash-es:
|
||||||
|
specifier: ^4.17.21
|
||||||
|
version: 4.17.21
|
||||||
devDependencies:
|
devDependencies:
|
||||||
|
'@types/lodash-es':
|
||||||
|
specifier: ^4.17.4
|
||||||
|
version: 4.17.7
|
||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^18.19.0
|
specifier: ^18.19.0
|
||||||
version: 18.19.3
|
version: 18.19.3
|
||||||
@ -11263,7 +11273,3 @@ packages:
|
|||||||
/zwitch@2.0.4:
|
/zwitch@2.0.4:
|
||||||
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
settings:
|
|
||||||
autoInstallPeers: true
|
|
||||||
excludeLinksFromLockfile: false
|
|
||||||
|
@ -20,6 +20,7 @@ import React, { useContext, useState } from 'react';
|
|||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
|
||||||
import Core from '@tmagic/core';
|
import Core from '@tmagic/core';
|
||||||
|
import type { ChangeEvent } from '@tmagic/data-source';
|
||||||
import type { MNode } from '@tmagic/schema';
|
import type { MNode } from '@tmagic/schema';
|
||||||
import { AppContent } from '@tmagic/ui-react';
|
import { AppContent } from '@tmagic/ui-react';
|
||||||
import { replaceChildNode } from '@tmagic/utils';
|
import { replaceChildNode } from '@tmagic/utils';
|
||||||
@ -31,11 +32,20 @@ function App() {
|
|||||||
|
|
||||||
const [config, setConfig] = useState(app.page.data);
|
const [config, setConfig] = useState(app.page.data);
|
||||||
|
|
||||||
app.dataSourceManager?.on('update-data', (nodes: MNode[]) => {
|
app.dataSourceManager?.on('update-data', (nodes: MNode[], sourceId: string, event: ChangeEvent) => {
|
||||||
nodes.forEach((node) => {
|
nodes.forEach((node) => {
|
||||||
replaceChildNode(node, [config]);
|
replaceChildNode(node, [config]);
|
||||||
setConfig(cloneDeep(config));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setConfig(cloneDeep(config));
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
app.emit('replaced-node', {
|
||||||
|
...event,
|
||||||
|
nodes,
|
||||||
|
sourceId,
|
||||||
|
});
|
||||||
|
}, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
const MagicUiPage = app.resolveComponent('page');
|
const MagicUiPage = app.resolveComponent('page');
|
||||||
|
@ -54,7 +54,7 @@ const getLocalConfig = (): MApp[] => {
|
|||||||
window.magicDSL = [];
|
window.magicDSL = [];
|
||||||
|
|
||||||
Object.entries(datasources).forEach(([type, ds]: [string, any]) => {
|
Object.entries(datasources).forEach(([type, ds]: [string, any]) => {
|
||||||
DataSourceManager.registe(type, ds);
|
DataSourceManager.register(type, ds);
|
||||||
});
|
});
|
||||||
|
|
||||||
const app = new Core({
|
const app = new Core({
|
||||||
|
@ -59,7 +59,7 @@ window.appInstance = app;
|
|||||||
let curPageId = '';
|
let curPageId = '';
|
||||||
|
|
||||||
const updateConfig = (root: MApp) => {
|
const updateConfig = (root: MApp) => {
|
||||||
app?.setConfig(root,curPageId);
|
app?.setConfig(root, curPageId);
|
||||||
renderDom();
|
renderDom();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3,10 +3,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, inject, reactive } from 'vue';
|
import { defineComponent, inject, nextTick, reactive } from 'vue';
|
||||||
|
|
||||||
import Core from '@tmagic/core';
|
import Core from '@tmagic/core';
|
||||||
import { MNode } from '@tmagic/schema';
|
import type { ChangeEvent } from '@tmagic/data-source';
|
||||||
|
import type { MNode } from '@tmagic/schema';
|
||||||
import { replaceChildNode } from '@tmagic/utils';
|
import { replaceChildNode } from '@tmagic/utils';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
@ -16,10 +17,16 @@ export default defineComponent({
|
|||||||
const app = inject<Core | undefined>('app');
|
const app = inject<Core | undefined>('app');
|
||||||
const pageConfig = reactive(app?.page?.data || {});
|
const pageConfig = reactive(app?.page?.data || {});
|
||||||
|
|
||||||
app?.dataSourceManager?.on('update-data', (nodes: MNode[]) => {
|
app?.dataSourceManager?.on('update-data', (nodes: MNode[], sourceId: string, changeEvent: ChangeEvent) => {
|
||||||
nodes.forEach((node) => {
|
nodes.forEach((node) => {
|
||||||
replaceChildNode(reactive(node), [pageConfig as MNode]);
|
replaceChildNode(reactive(node), [pageConfig as MNode]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!app) return;
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
app.emit('replaced-node', { nodes, sourceId, ...changeEvent });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -39,7 +39,7 @@ Object.keys(components).forEach((type: string) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Object.entries(datasources).forEach(([type, ds]: [string, any]) => {
|
Object.entries(datasources).forEach(([type, ds]: [string, any]) => {
|
||||||
DataSourceManager.registe(type, ds);
|
DataSourceManager.register(type, ds);
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.values(plugins).forEach((plugin: any) => {
|
Object.values(plugins).forEach((plugin: any) => {
|
||||||
|
@ -3,10 +3,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, inject, reactive } from 'vue';
|
import { defineComponent, inject, nextTick, reactive } from 'vue';
|
||||||
|
|
||||||
import Core from '@tmagic/core';
|
import Core from '@tmagic/core';
|
||||||
import { MNode } from '@tmagic/schema';
|
import type { ChangeEvent } from '@tmagic/data-source';
|
||||||
|
import type { MNode } from '@tmagic/schema';
|
||||||
import { replaceChildNode } from '@tmagic/utils';
|
import { replaceChildNode } from '@tmagic/utils';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
@ -16,10 +17,16 @@ export default defineComponent({
|
|||||||
const app = inject<Core | undefined>('app');
|
const app = inject<Core | undefined>('app');
|
||||||
const pageConfig = reactive(app?.page?.data || {});
|
const pageConfig = reactive(app?.page?.data || {});
|
||||||
|
|
||||||
app?.dataSourceManager?.on('update-data', (nodes: MNode[]) => {
|
app?.dataSourceManager?.on('update-data', (nodes: MNode[], sourceId: string, changeEvent: ChangeEvent) => {
|
||||||
nodes.forEach((node) => {
|
nodes.forEach((node) => {
|
||||||
replaceChildNode(reactive(node), [pageConfig as MNode]);
|
replaceChildNode(reactive(node), [pageConfig as MNode]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!app) return;
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
app.emit('replaced-node', { nodes, sourceId, ...changeEvent });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -41,7 +41,7 @@ Object.entries(components).forEach(([type, component]: [string, any]) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Object.entries(datasources).forEach(([type, ds]: [string, any]) => {
|
Object.entries(datasources).forEach(([type, ds]: [string, any]) => {
|
||||||
DataSourceManager.registe(type, ds);
|
DataSourceManager.register(type, ds);
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.values(plugins).forEach((plugin: any) => {
|
Object.values(plugins).forEach((plugin: any) => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user