mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-13 01:21:58 +00:00
can load legao assets
This commit is contained in:
parent
469c26985b
commit
208bccfcb9
@ -9,6 +9,7 @@ import {
|
||||
getRegisteredMetadataTransducers,
|
||||
registerMetadataTransducer,
|
||||
computed,
|
||||
NestingFilter,
|
||||
} from '@ali/lowcode-globals';
|
||||
import { Node, NodeParent } from './document';
|
||||
import { Designer } from './designer';
|
||||
@ -24,6 +25,9 @@ function ensureAList(list?: string | string[]): string[] | null {
|
||||
return null;
|
||||
}
|
||||
if (!Array.isArray(list)) {
|
||||
if (typeof list !== 'string') {
|
||||
return null;
|
||||
}
|
||||
list = list.split(/ *[ ,|] */).filter(Boolean);
|
||||
}
|
||||
if (list.length < 1) {
|
||||
@ -32,6 +36,27 @@ function ensureAList(list?: string | string[]): string[] | null {
|
||||
return list;
|
||||
}
|
||||
|
||||
function isRegExp(obj: any): obj is RegExp {
|
||||
return obj && obj.test && obj.exec && obj.compile;
|
||||
}
|
||||
|
||||
function buildFilter(rule?: string | string[] | RegExp | NestingFilter) {
|
||||
if (!rule) {
|
||||
return null;
|
||||
}
|
||||
if (typeof rule === 'function') {
|
||||
return rule;
|
||||
}
|
||||
if (isRegExp(rule)) {
|
||||
return (testNode: Node | NodeSchema) => rule.test(testNode.componentName);
|
||||
}
|
||||
const list = ensureAList(rule);
|
||||
if (!list) {
|
||||
return null;
|
||||
}
|
||||
return (testNode: Node | NodeSchema) => list.includes(testNode.componentName);
|
||||
}
|
||||
|
||||
export class ComponentMeta {
|
||||
readonly isComponentMeta = true;
|
||||
private _npm?: NpmInfo;
|
||||
@ -64,8 +89,8 @@ export class ComponentMeta {
|
||||
return config?.combined || config?.props || [];
|
||||
}
|
||||
|
||||
private parentWhitelist?: string[] | null;
|
||||
private childWhitelist?: string[] | null;
|
||||
private parentWhitelist?: NestingFilter | null;
|
||||
private childWhitelist?: NestingFilter | null;
|
||||
|
||||
private _title?: TitleContent;
|
||||
get title() {
|
||||
@ -123,8 +148,8 @@ export class ComponentMeta {
|
||||
this._rectSelector = component.rectSelector;
|
||||
if (component.nestingRule) {
|
||||
const { parentWhitelist, childWhitelist } = component.nestingRule;
|
||||
this.parentWhitelist = ensureAList(parentWhitelist);
|
||||
this.childWhitelist = ensureAList(childWhitelist);
|
||||
this.parentWhitelist = buildFilter(parentWhitelist);
|
||||
this.childWhitelist = buildFilter(childWhitelist);
|
||||
}
|
||||
} else {
|
||||
this._isContainer = false;
|
||||
@ -172,7 +197,7 @@ export class ComponentMeta {
|
||||
checkNestingUp(my: Node | NodeData, parent: NodeParent) {
|
||||
// 检查父子关系,直接约束型,在画布中拖拽直接掠过目标容器
|
||||
if (this.parentWhitelist) {
|
||||
return this.parentWhitelist.includes(parent.componentName);
|
||||
return this.parentWhitelist(parent, my);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -180,7 +205,7 @@ export class ComponentMeta {
|
||||
checkNestingDown(my: Node, target: Node | NodeSchema) {
|
||||
// 检查父子关系,直接约束型,在画布中拖拽直接掠过目标容器
|
||||
if (this.childWhitelist) {
|
||||
return this.childWhitelist.includes(target.componentName);
|
||||
return this.childWhitelist(target, my);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ import {
|
||||
import { Project } from '../project';
|
||||
import { Node, DocumentModel, insertChildren, isRootNode, NodeParent } from '../document';
|
||||
import { ComponentMeta } from '../component-meta';
|
||||
import { INodeSelector } from '../simulator';
|
||||
import { INodeSelector, Component } from '../simulator';
|
||||
import { Scroller, IScrollable } from './scroller';
|
||||
import { Dragon, isDragNodeObject, isDragNodeDataObject, LocateEvent, DragObject } from './dragon';
|
||||
import { ActiveTracker } from './active-tracker';
|
||||
@ -306,6 +306,7 @@ export class Designer {
|
||||
private _lostComponentMetasMap = new Map<string, ComponentMeta>();
|
||||
|
||||
private buildComponentMetasMap(metas: ComponentMetadata[]) {
|
||||
console.info(this._componentMetasMap);
|
||||
metas.forEach((data) => this.createComponentMeta(data));
|
||||
}
|
||||
|
||||
@ -352,10 +353,13 @@ export class Designer {
|
||||
return meta;
|
||||
}
|
||||
|
||||
@computed get componentsMap(): { [key: string]: NpmInfo } {
|
||||
@computed get componentsMap(): { [key: string]: NpmInfo | Component } {
|
||||
const maps: any = {};
|
||||
this._componentMetasMap.forEach((config, key) => {
|
||||
if (config.npm) {
|
||||
const view = config.getMetadata().experimental?.view;
|
||||
if (view) {
|
||||
maps[key] = view;
|
||||
} else if (config.npm) {
|
||||
maps[key] = config.npm;
|
||||
}
|
||||
});
|
||||
|
||||
@ -466,6 +466,36 @@ export class Node {
|
||||
this.props.purge();
|
||||
this.document.internalRemoveAndPurgeNode(this);
|
||||
}
|
||||
|
||||
// ======= compatibles ====
|
||||
isEmpty(): boolean {
|
||||
return this.children?.isEmpty() || true;
|
||||
}
|
||||
getStatus() {
|
||||
return 'default';
|
||||
}
|
||||
setStatus() {
|
||||
|
||||
}
|
||||
getDOMNode() {
|
||||
const instance = this.document.simulator?.getComponentInstances(this)?.[0];
|
||||
if (!instance) {
|
||||
return;
|
||||
}
|
||||
return this.document.simulator?.findDOMNodes(instance)?.[0];
|
||||
}
|
||||
getChildren() {
|
||||
return this.children;
|
||||
}
|
||||
getPage() {
|
||||
return this.document;
|
||||
}
|
||||
getComponentName() {
|
||||
return this.componentName;
|
||||
}
|
||||
insertBefore(node: Node, ref?: Node) {
|
||||
this.children?.insert(node, ref ? ref.index : null);
|
||||
}
|
||||
}
|
||||
|
||||
export interface NodeParent extends Node {
|
||||
|
||||
@ -109,7 +109,7 @@ export interface I18nConfig {
|
||||
export type I18nFunction = (key: string, params: any) => string;
|
||||
|
||||
export interface Utils {
|
||||
[key: string]: (...args: []) => any;
|
||||
[key: string]: (...args: any[]) => any;
|
||||
}
|
||||
|
||||
export interface PluginProps {
|
||||
|
||||
@ -35,8 +35,8 @@ export default class DesignerPlugin extends PureComponent<PluginProps, DesignerP
|
||||
}
|
||||
const { components, packages } = assets;
|
||||
const state = {
|
||||
componentMetadatas: components ? components.filter(item => item.type === 'ComponentMetadata') : [],
|
||||
library: packages ? Object.values(packages) : [],
|
||||
componentMetadatas: components || [],
|
||||
library: packages || [],
|
||||
};
|
||||
this.setState(state);
|
||||
};
|
||||
@ -63,6 +63,8 @@ export default class DesignerPlugin extends PureComponent<PluginProps, DesignerP
|
||||
return null;
|
||||
}
|
||||
|
||||
console.info('metadatas', componentMetadatas);
|
||||
|
||||
return (
|
||||
<DesignerView
|
||||
onMount={this.handleDesignerMount}
|
||||
|
||||
@ -153,6 +153,9 @@
|
||||
& > svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
* {
|
||||
fill: var(--color-icon-normal, rgba(31, 56, 88, 0.4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ export default class SettingsMainView extends Component {
|
||||
if (this.main.isMulti) {
|
||||
return (
|
||||
<div className="lc-settings-navigator">
|
||||
{createIcon(this.main.componentMeta?.icon)}
|
||||
{createIcon(this.main.componentMeta?.icon, { className: 'lc-settings-navigator-icon'})}
|
||||
<Title title={this.main.componentMeta!.title} />
|
||||
<span>x {this.main.nodes.length}</span>
|
||||
</div>
|
||||
@ -57,7 +57,7 @@ export default class SettingsMainView extends Component {
|
||||
|
||||
return (
|
||||
<div className="lc-settings-navigator">
|
||||
{createIcon(this.main.componentMeta?.icon)}
|
||||
{createIcon(this.main.componentMeta?.icon, { className: 'lc-settings-navigator-icon'})}
|
||||
<Breadcrumb className="lc-settings-node-breadcrumb">{items}</Breadcrumb>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -4,6 +4,7 @@ import { ComponentMeta, Node, Designer, Selection } from '@ali/lowcode-designer'
|
||||
import { TitleContent, FieldExtraProps, SetterType, CustomView, FieldConfig, isCustomView } from '@ali/lowcode-globals';
|
||||
import { getTreeMaster } from '@ali/lowcode-plugin-outline-pane';
|
||||
import Editor from '@ali/lowcode-editor-core';
|
||||
import { Transducer } from './utils';
|
||||
|
||||
export interface SettingTarget {
|
||||
// 所设置的节点集,至少一个
|
||||
@ -91,6 +92,7 @@ export class SettingField implements SettingTarget {
|
||||
readonly componentMeta: ComponentMeta | null;
|
||||
readonly designer: Designer;
|
||||
readonly top: SettingTarget;
|
||||
readonly transducer: Transducer;
|
||||
get path() {
|
||||
const path = this.parent.path.slice();
|
||||
if (this.type === 'field') {
|
||||
@ -139,6 +141,8 @@ export class SettingField implements SettingTarget {
|
||||
if (this.type === 'group' && items) {
|
||||
this.initItems(items);
|
||||
}
|
||||
|
||||
this.transducer = new Transducer(this, { setter });
|
||||
}
|
||||
|
||||
onEffect(action: () => void): () => void {
|
||||
@ -272,6 +276,27 @@ export class SettingField implements SettingTarget {
|
||||
purge() {
|
||||
this.disposeItems();
|
||||
}
|
||||
|
||||
// ======= compatibles ====
|
||||
getHotValue(): any {
|
||||
return this.transducer.toHot(this.getValue());
|
||||
}
|
||||
|
||||
setHotValue(data: any) {
|
||||
this.setValue(this.transducer.toNative(data));
|
||||
}
|
||||
|
||||
getNode() {
|
||||
return this.nodes[0];
|
||||
}
|
||||
|
||||
getProps() {
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
onValueChange() {
|
||||
return () => {};
|
||||
}
|
||||
}
|
||||
|
||||
export function isSettingField(obj: any): obj is SettingField {
|
||||
|
||||
@ -111,7 +111,7 @@ class SettingFieldView extends Component<{ field: SettingField }> {
|
||||
forceInline: extraProps.forceInline,
|
||||
key: field.id,
|
||||
// === injection
|
||||
prop: field, // for compatible
|
||||
prop: field, // for compatible vision
|
||||
field,
|
||||
// === IO
|
||||
value, // reaction point
|
||||
|
||||
@ -1,36 +1,3 @@
|
||||
:root {
|
||||
--color-brand: #006cff;
|
||||
--color-brand-light: #197aff;
|
||||
--color-brand-dark: #0060e5;
|
||||
--color-icon-normal: rgba(31, 56, 88, 0.4);
|
||||
--color-icon-hover: rgba(31, 56, 88, 0.6);
|
||||
--color-icon-active: #006cff;
|
||||
--color-icon-reverse: #ffffff;
|
||||
--color-line-light: rgba(31, 56, 88, 0.05);
|
||||
--color-line-normal: rgba(31, 56, 88, 0.1);
|
||||
--color-line-darken: rgba(18, 32, 50, 0.1);
|
||||
--color-title: rgba(0, 0, 0, 0.8);
|
||||
--color-text: rgba(0, 0, 0, 0.6);
|
||||
--color-text-dark: rgba(0, 0, 0, 0.6);
|
||||
--color-text-light: rgba(26, 26, 26, 0.6);
|
||||
--color-text-reverse: rgba(255, 255, 255, 0.8);
|
||||
--color-text-regular: rgba(31, 56, 88, 0.8);
|
||||
--color-field-label: rgba(0, 0, 0, 0.4);
|
||||
--color-field-text: rgba(0, 0, 0, 0.6);
|
||||
--color-field-placeholder: rgba(31, 56, 88, 0.3);
|
||||
--color-field-border: rgba(31, 56, 88, 0.3);
|
||||
--color-field-border-hover: rgba(31, 56, 88, 0.4);
|
||||
--color-field-border-active: rgba(31, 56, 88, 0.6);
|
||||
--color-field-background: #ffffff;
|
||||
--color-pane-background: #ffffff;
|
||||
--color-block-background-normal: #ffffff;
|
||||
--color-block-background-light: rgba(31, 56, 88, 0.03);
|
||||
--color-block-background-shallow: rgba(31, 56, 88, 0.06);
|
||||
--color-block-background-dark: rgba(31, 56, 88, 0.1);
|
||||
--color-block-background-disabled: rgba(31, 56, 88, 0.2);
|
||||
--color-block-background-deep-dark: #BAC3CC;
|
||||
}
|
||||
|
||||
.lc-settings-main {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
@ -50,6 +17,13 @@
|
||||
align-items: center;
|
||||
padding-left: 5px;
|
||||
border-bottom: 1px solid var(--color-line-normal);
|
||||
.lc-settings-navigator-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
* {
|
||||
fill: var(--color-icon-normal, rgba(31, 56, 88, 0.4));
|
||||
}
|
||||
}
|
||||
.lc-settings-node-breadcrumb {
|
||||
margin-left: 5px;
|
||||
.next-breadcrumb {
|
||||
@ -126,6 +100,8 @@
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
overflow-y: auto;
|
||||
outline: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
.lc-outline-pane {
|
||||
|
||||
41
packages/plugin-settings-pane/src/utils.js
Normal file
41
packages/plugin-settings-pane/src/utils.js
Normal file
@ -0,0 +1,41 @@
|
||||
function getHotterFromSetter(setter) {
|
||||
return setter && (setter.Hotter || (setter.type && setter.type.Hotter)) || []; // eslint-disable-line
|
||||
}
|
||||
|
||||
function getTransducerFromSetter(setter) {
|
||||
return setter && (
|
||||
setter.transducer || setter.Transducer
|
||||
|| (setter.type && (setter.type.transducer || setter.type.Transducer))
|
||||
) || null; // eslint-disable-line
|
||||
}
|
||||
|
||||
function combineTransducer(transducer, arr, context) {
|
||||
if (!transducer && Array.isArray(arr)) {
|
||||
const [toHot, toNative] = arr;
|
||||
transducer = { toHot, toNative };
|
||||
}
|
||||
|
||||
return {
|
||||
toHot: (transducer && transducer.toHot || (x => x)).bind(context), // eslint-disable-line
|
||||
toNative: (transducer && transducer.toNative || (x => x)).bind(context), // eslint-disable-line
|
||||
};
|
||||
}
|
||||
|
||||
export class Transducer {
|
||||
constructor(context, config) {
|
||||
this.setterTransducer = combineTransducer(
|
||||
getTransducerFromSetter(config.setter),
|
||||
getHotterFromSetter(config.setter),
|
||||
context,
|
||||
);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
toHot(data) {
|
||||
return this.setterTransducer.toHot(data);
|
||||
}
|
||||
|
||||
toNative(data) {
|
||||
return this.setterTransducer.toNative(data);
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { PureComponent, createElement as reactCreateElement } from 'react';
|
||||
import React, { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Debug from 'debug';
|
||||
import Div from '@ali/iceluna-comp-div';
|
||||
@ -312,9 +312,9 @@ export default class BaseEngine extends PureComponent {
|
||||
} else if (typeof idx === 'number' && !props.key) {
|
||||
props.key = idx;
|
||||
}
|
||||
const createElement = engine.props.customCreateElement || reactCreateElement;
|
||||
props.__id = schema.id;
|
||||
const renderComp = (props) => {
|
||||
return createElement(
|
||||
return engine.createElement(
|
||||
Comp,
|
||||
props,
|
||||
(!isFileSchema(schema) &&
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import React, { PureComponent, createElement as reactCreateElement } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import Debug from 'debug';
|
||||
@ -85,8 +85,12 @@ export default class Engine extends PureComponent {
|
||||
}
|
||||
};
|
||||
|
||||
createElement(Component, props, children) {
|
||||
return (this.props.customCreateElement || reactCreateElement)(Component, props, children);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { schema, designMode, appHelper, components } = this.props;
|
||||
const { schema, designMode, appHelper, components, customCreateElement } = this.props;
|
||||
if (isEmpty(schema)) {
|
||||
return null;
|
||||
}
|
||||
@ -94,7 +98,7 @@ export default class Engine extends PureComponent {
|
||||
return '模型结构异常';
|
||||
}
|
||||
debug('entry.render');
|
||||
const allComponents = { ...ENGINE_COMPS, ...components };
|
||||
const allComponents = { ...components, ...ENGINE_COMPS };
|
||||
const Comp = allComponents[schema.componentName];
|
||||
if (Comp) {
|
||||
return (
|
||||
|
||||
@ -3,6 +3,7 @@ import { ReactInstance, Fragment, Component, createElement } from 'react';
|
||||
import { observer } from '@recore/obx-react';
|
||||
import { SimulatorRenderer } from './renderer';
|
||||
import './renderer.less';
|
||||
import { host } from './host';
|
||||
|
||||
export default class SimulatorRendererView extends Component<{ renderer: SimulatorRenderer }> {
|
||||
render() {
|
||||
@ -50,8 +51,11 @@ class Renderer extends Component<{ renderer: SimulatorRenderer }> {
|
||||
designMode={renderer.designMode}
|
||||
suspended={renderer.suspended}
|
||||
self={renderer.scope}
|
||||
customCreateElement={(Component, props, children) => {
|
||||
return createElement(Component, props, children);
|
||||
customCreateElement={(Component: any, props: any, children: any) => {
|
||||
const { __id, __desingMode, ...viewProps } = props;
|
||||
viewProps.componentId = __id;
|
||||
viewProps._leaf = host.document.getNode(__id);
|
||||
return createElement(Component, viewProps, children);
|
||||
}}
|
||||
onCompGetRef={(schema: any, ref: ReactInstance | null) => {
|
||||
renderer.mountInstance(schema.id, ref);
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { createElement, ReactInstance } from 'react';
|
||||
import { createElement, ReactInstance, ComponentType } from 'react';
|
||||
import { render as reactRender } from 'react-dom';
|
||||
import { host } from './host';
|
||||
import SimulatorRendererView from './renderer-view';
|
||||
import { computed, obx } from '@recore/obx';
|
||||
import { Asset } from '@ali/lowcode-globals';
|
||||
import { Asset, isReactComponent } from '@ali/lowcode-globals';
|
||||
import { getClientRects } from './utils/get-client-rects';
|
||||
import loader from './utils/loader';
|
||||
import { reactFindDOMNodes, FIBER_KEY } from './utils/react-find-dom-nodes';
|
||||
@ -311,12 +311,17 @@ export interface LibraryMap {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
function buildComponents(libraryMap: LibraryMap, componentsMap: { [componentName: string]: NpmInfo }) {
|
||||
function buildComponents(libraryMap: LibraryMap, componentsMap: { [componentName: string]: NpmInfo | ComponentType<any> }) {
|
||||
const components: any = {};
|
||||
Object.keys(componentsMap).forEach((componentName) => {
|
||||
const component = findComponent(libraryMap, componentName, componentsMap[componentName]);
|
||||
if (component) {
|
||||
let component = componentsMap[componentName];
|
||||
if (isReactComponent(component)) {
|
||||
components[componentName] = component;
|
||||
} else {
|
||||
component = findComponent(libraryMap, componentName, component);
|
||||
if (component) {
|
||||
components[componentName] = component;
|
||||
}
|
||||
}
|
||||
});
|
||||
return components;
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
{
|
||||
"entry": {
|
||||
"index": "src/demo/index.ts"
|
||||
"index": "src/demo/index.ts",
|
||||
"react-simulator-renderer": "../react-simulator-renderer/src/index.ts",
|
||||
"vision": "src/vision.ts"
|
||||
},
|
||||
"vendor": false,
|
||||
"devServer": {
|
||||
@ -12,7 +14,8 @@
|
||||
"react-dom": "window.ReactDOM",
|
||||
"prop-types": "window.PropTypes",
|
||||
"@alifd/next": "window.Next",
|
||||
"@ali/lowcode-globals": "window.LCEGlobals"
|
||||
"@ali/visualengine": "window.VisualEngine",
|
||||
"@ali/visualengine-utils": "window.VisualEngineUtils"
|
||||
},
|
||||
"plugins": [
|
||||
[
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
"@ali/lowcode-plugin-undo-redo": "^0.8.6",
|
||||
"@ali/lowcode-plugin-zh-en": "^0.8.8",
|
||||
"@ali/lowcode-setters": "^0.8.8",
|
||||
"@ali/ve-i18n-util": "^2.0.2",
|
||||
"@ali/ve-icons": "^4.1.9",
|
||||
"@ali/ve-less-variables": "2.0.3",
|
||||
"@ali/ve-popups": "^4.2.5",
|
||||
|
||||
@ -9,17 +9,67 @@
|
||||
<script src="https://g.alicdn.com/code/lib/react/16.9.0/umd/react.development.js"></script>
|
||||
<script src="https://g.alicdn.com/code/lib/react-dom/16.9.0/umd/react-dom.development.js"></script>
|
||||
<script src="https://g.alicdn.com/code/lib/prop-types/15.7.2/prop-types.js"></script>
|
||||
<script> React.PropTypes = PropTypes; </script>
|
||||
<script>
|
||||
React.PropTypes = PropTypes;
|
||||
</script>
|
||||
<script src="https://g.alicdn.com/platform/c/??react15-polyfill/0.0.1/dist/index.js,lodash/4.6.1/lodash.min.js,immutable/3.7.6/dist/immutable.min.js,natty-storage/2.0.2/dist/natty-storage.min.js,natty-fetch/2.6.0/dist/natty-fetch.pc.min.js,tinymce/4.2.5/tinymce-full.js"></script>
|
||||
<script src="https://g.alicdn.com/mylib/moment/2.24.0/min/moment.min.js"></script>
|
||||
<link rel="stylesheet" href="https://alifd.alicdn.com/npm/@alifd/next/1.11.6/next.min.css" />
|
||||
<script src="https://unpkg.alibaba-inc.com/@alifd/next@1.18.17/dist/next.min.js"></script>
|
||||
<script src="https://g.alicdn.com/vision/visualengine-utils/4.3.1/engine-utils.js"></script>
|
||||
<!-- lowcode engine globals -->
|
||||
<link rel="stylesheet" href="https://dev.g.alicdn.com/ali-lowcode/ali-lowcode-engine/0.9.0/globals.css" />
|
||||
<link href="/css/vision.css" rel="stylesheet" />
|
||||
<script>
|
||||
window.pageConfig = {
|
||||
env: 'release',
|
||||
locale: 'zh_CN',
|
||||
pageType: 'single',
|
||||
deviceType: 'web',
|
||||
appName: '基础包管理后台',
|
||||
appType: 'legao_base_packages',
|
||||
templateType: '',
|
||||
pageId: 'FORM-3KYJN7RV-DIOD8LLK1WGQ89S7NHA92-QJVH497K-V',
|
||||
slug: 'test',
|
||||
appMode: 'back',
|
||||
isAppAdmin: 'y',
|
||||
isSuperAdmin: 'n',
|
||||
isBetaDeveloper: 'n',
|
||||
formType: 'display',
|
||||
title: { en_US: '测试', type: 'i18n', zh_CN: '测试' },
|
||||
urlPrefix: 'https://go.alibaba-inc.com',
|
||||
APIUrlPrefix: 'https://go.alibaba-inc.com',
|
||||
devVersion: '0.1.0', // 这个是子应用的变更 id
|
||||
subAppType: '0.1.0',
|
||||
appKey: 'legao_base_packages',
|
||||
RE_VERSION: '7.1.1',
|
||||
appSource: '',
|
||||
isDomainDefault: 'n',
|
||||
useReleaseBundle: 'n',
|
||||
isDomainPkg: 'n',
|
||||
medusaAppName: '',
|
||||
domainCode: 'kS6SyH',
|
||||
aecp: {
|
||||
mdcDomain: '',
|
||||
projectId: '',
|
||||
appCode: '',
|
||||
},
|
||||
designerConfigs: {},
|
||||
navConfig:
|
||||
'{"appName":{"en_US":"基础包管理后台","key":"","type":"i18n","zh_CN":"基础包管理后台"},"bgColor":"white","data":[{"children":[],"hidden":false,"icon":"","inner":true,"navUuid":"FORM-3KYJN7RV-DIOD8LLK1WGQ89S7NHA92-QJVH497K-V","relateUuid":"FORM-3KYJN7RV-DIOD8LLK1WGQ89S7NHA92-QJVH497K-V","slug":"test","targetNew":false,"title":{"en_US":"测试","type":"i18n","zh_CN":"测试"}}],"isFixed":"y","isFold":"y","isFoldHorizontal":"n","languageChangeUrl":{"en_US":"/common/account/changeAccountLanguage.json","type":"i18n","zh_CN":"/common/account/changeAccountLanguage.json"},"layout":"auto","navStyle":"orange","navTheme":"light","openSubMode":false,"showAppTitle":true,"showCrumb":true,"showIcon":false,"showLanguageChange":true,"showNav":true,"showSearch":"n","singletons":{"FORM-3KYJN7RV-DIOD8LLK1WGQ89S7NHA92-QJVH497K-V":{"isFixed":"n","isFold":"n","isFoldHorizontal":"n","showAppTitle":false,"showCrumb":false,"showLanguageChange":false,"showNav":false,"showSearch":"n","singleton":false},"test":{"$ref":"$.singletons.FORM\\-3KYJN7RV\\-DIOD8LLK1WGQ89S7NHA92\\-QJVH497K\\-V"}},"type":"top_fold"}',
|
||||
historyType: 'HASH',
|
||||
isSinglePage: 'n',
|
||||
rhino: 'n',
|
||||
isMiniApp: '',
|
||||
taskId: '',
|
||||
appSchema: 'V5',
|
||||
openSubMode: 'n',
|
||||
};
|
||||
window.g_config = {};
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- lowcode engine globals -->
|
||||
<script src="https://dev.g.alicdn.com/ali-lowcode/ali-lowcode-engine/0.9.0/globals.js"></script>
|
||||
<script src="/js/vision.js"></script>
|
||||
<script src="https://g.alicdn.com/vision/visualengine-utils/4.3.1/engine-utils.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -148,7 +148,7 @@ class Prototype {
|
||||
static overridePropsConfigure = overridePropsConfigure;
|
||||
static create(config: OldPrototypeConfig | ComponentMetadata | ComponentMeta) {
|
||||
return new Prototype(config);
|
||||
};
|
||||
}
|
||||
|
||||
private id: string;
|
||||
private meta: ComponentMeta;
|
||||
@ -241,6 +241,7 @@ class Prototype {
|
||||
setPackageName(name: string) {
|
||||
this.meta.setNpm({
|
||||
package: name,
|
||||
componentName: this.getComponentName(),
|
||||
});
|
||||
}
|
||||
|
||||
@ -256,7 +257,10 @@ class Prototype {
|
||||
}
|
||||
|
||||
getView() {
|
||||
return this.meta.getMetadata().experimental?.view || designer.currentDocument?.simulator?.getComponent(this.getComponentName());
|
||||
return (
|
||||
this.meta.getMetadata().experimental?.view ||
|
||||
designer.currentDocument?.simulator?.getComponent(this.getComponentName())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -143,11 +143,11 @@ export interface OldPrototypeConfig {
|
||||
canSelecting?: boolean;
|
||||
canContain?: (dragment: Node) => boolean; // => nestingRule
|
||||
|
||||
canDropTo?: ((container: Node) => boolean) | string | string[]; // => nestingRule
|
||||
canDropto?: (container: Node) => boolean; // => nestingRule
|
||||
canDropTo?: ((container: Node) => boolean) | boolean | string | string[]; // => nestingRule
|
||||
canDropto?: ((container: Node) => boolean) | boolean | string | string[]; // => nestingRule
|
||||
|
||||
canDropIn?: ((dragment: Node) => boolean) | string | string[]; // => nestingRule
|
||||
canDroping?: (dragment: Node) => boolean; // => nestingRule
|
||||
canDropIn?: ((dragment: Node) => boolean) | boolean | string | string[]; // => nestingRule
|
||||
canDroping?: ((dragment: Node) => boolean) | boolean | string | string[]; // => nestingRule
|
||||
|
||||
didDropOut?: (dragment: any, container: any) => void; // => hooks
|
||||
didDropIn?: (dragment: any, container: any) => void; // => hooks
|
||||
@ -387,9 +387,9 @@ export function upgradePropConfig(config: OldPropConfig) {
|
||||
}
|
||||
|
||||
export function upgradeConfigure(items: OldPropConfig[]) {
|
||||
const configure = [];
|
||||
const configure: any[] = [];
|
||||
let ignoreSlotName: any = null;
|
||||
return items.forEach((config) => {
|
||||
items.forEach((config) => {
|
||||
if (config.slotName) {
|
||||
ignoreSlotName = config.slotName;
|
||||
} else if (ignoreSlotName) {
|
||||
@ -401,6 +401,7 @@ export function upgradeConfigure(items: OldPropConfig[]) {
|
||||
}
|
||||
configure.push(upgradePropConfig(config));
|
||||
});
|
||||
return configure;
|
||||
}
|
||||
|
||||
export function upgradeActions(actions?: Array<ComponentType<any> | ReactElement> | (() => ReactElement)) {
|
||||
@ -507,11 +508,21 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) {
|
||||
if (canContain) {
|
||||
nestingRule.descendantWhitelist = canContain;
|
||||
}
|
||||
if (canDropTo || canDropto) {
|
||||
nestingRule.parentWhitelist = canDropTo || canDropto;
|
||||
if (canDropTo != null || canDropto != null) {
|
||||
if (canDropTo === false || canDropto === false) {
|
||||
nestingRule.parentWhitelist = () => false;
|
||||
}
|
||||
if (canDropTo !== true && canDropto !== true) {
|
||||
nestingRule.parentWhitelist = canDropTo || canDropto;
|
||||
}
|
||||
}
|
||||
if (canDropIn || canDroping) {
|
||||
nestingRule.childWhitelist = canDropIn || canDroping;
|
||||
if (canDropIn != null || canDroping != null) {
|
||||
if (canDropIn === false || canDroping === false) {
|
||||
nestingRule.childWhitelist = () => false;
|
||||
}
|
||||
if (canDropIn !== true && canDroping !== true) {
|
||||
nestingRule.childWhitelist = canDropIn || canDroping;
|
||||
}
|
||||
}
|
||||
component.nestingRule = nestingRule;
|
||||
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import Engine from '../vision'; // VisualEngine
|
||||
import { editor } from '../editor';
|
||||
// @ts-ignore
|
||||
import Engine from '@ali/visualengine';
|
||||
import loadUrls from './loader';
|
||||
|
||||
const { editor } = Engine;
|
||||
|
||||
Engine.init();
|
||||
|
||||
load();
|
||||
@ -12,14 +14,7 @@ async function load() {
|
||||
loadSchema();
|
||||
}
|
||||
|
||||
const externals = [
|
||||
'react',
|
||||
'react-dom',
|
||||
'prop-types',
|
||||
'react-router',
|
||||
'react-router-dom',
|
||||
'@ali/recore',
|
||||
];
|
||||
const externals = ['react', 'react-dom', 'prop-types', 'react-router', 'react-router-dom', '@ali/recore'];
|
||||
async function loadAssets() {
|
||||
const assets = await editor.utils.get('./legao-assets.json');
|
||||
// Trunk.setPackages(assets.packages);
|
||||
@ -28,7 +23,7 @@ async function loadAssets() {
|
||||
assets.packages.forEach((item: any) => {
|
||||
if (item.package.indexOf('@ali/vc-') === 0 && item.urls) {
|
||||
item.urls = item.urls.filter((url: string) => {
|
||||
return url.indexOf('view.mobile') < 0
|
||||
return url.indexOf('view.mobile') < 0;
|
||||
});
|
||||
} else if (item.package && externals.indexOf(item.package) > -1) {
|
||||
item.urls = null;
|
||||
|
||||
@ -4,7 +4,7 @@ import { Designer } from '@ali/lowcode-designer';
|
||||
import { registerSetters } from '@ali/lowcode-setters';
|
||||
import OutlinePane from '@ali/lowcode-plugin-outline-pane';
|
||||
import SettingsPane from '@ali/lowcode-plugin-settings-pane';
|
||||
import DesignerView from '@ali/lowcode-plugin-designer';
|
||||
import DesignerPlugin from '@ali/lowcode-plugin-designer';
|
||||
import { Skeleton } from './skeleton/skeleton';
|
||||
|
||||
registerSetters();
|
||||
@ -21,7 +21,7 @@ editor.set(Designer, designer);
|
||||
skeleton.mainArea.add({
|
||||
name: 'designer',
|
||||
type: 'Widget',
|
||||
content: DesignerView,
|
||||
content: DesignerPlugin,
|
||||
});
|
||||
skeleton.rightArea.add({
|
||||
name: 'settingsPane',
|
||||
|
||||
88
packages/vision-polyfill/src/env.ts
Normal file
88
packages/vision-polyfill/src/env.ts
Normal file
@ -0,0 +1,88 @@
|
||||
import { EventEmitter } from 'events';
|
||||
import { ALI_SCHEMA_VERSION } from './base/const';
|
||||
|
||||
interface ILiteralObject {
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export class Env {
|
||||
|
||||
public envs: ILiteralObject;
|
||||
|
||||
private emitter: EventEmitter;
|
||||
private featureMap: ILiteralObject;
|
||||
|
||||
constructor() {
|
||||
this.emitter = new EventEmitter();
|
||||
this.emitter.setMaxListeners(0);
|
||||
this.envs = {};
|
||||
this.featureMap = {};
|
||||
}
|
||||
|
||||
public get(name: string): any {
|
||||
return this.getEnv(name);
|
||||
}
|
||||
|
||||
public getEnv(name: string): any {
|
||||
return this.envs[name];
|
||||
}
|
||||
|
||||
public set(name: string, value: any) {
|
||||
return this.setEnv(name, value);
|
||||
}
|
||||
|
||||
public setEnv(name: string, value: any) {
|
||||
const orig = this.envs[name];
|
||||
if (JSON.stringify(orig) === JSON.stringify(value)) {
|
||||
return;
|
||||
}
|
||||
this.envs[name] = value;
|
||||
this.emitter.emit('envchange', this.envs, name, value);
|
||||
}
|
||||
|
||||
public setEnvMap(envs: ILiteralObject): void {
|
||||
this.envs = Object.assign(this.envs, envs);
|
||||
this.emitter.emit('envchange', this.envs);
|
||||
}
|
||||
|
||||
public getLocale(): string {
|
||||
return this.getEnv('locale') || 'zh_CN';
|
||||
}
|
||||
|
||||
public setLocale(locale: string) {
|
||||
this.setEnv('locale', locale);
|
||||
}
|
||||
|
||||
public setExpertMode(flag: string) {
|
||||
this.setEnv('expertMode', !!flag);
|
||||
}
|
||||
|
||||
public isExpertMode() {
|
||||
return !!this.getEnv('expertMode');
|
||||
}
|
||||
|
||||
public getSupportFeatures() {
|
||||
return Object.assign({}, this.featureMap);
|
||||
}
|
||||
|
||||
public setSupportFeatures(features: ILiteralObject) {
|
||||
this.featureMap = Object.assign({}, this.featureMap, features);
|
||||
}
|
||||
|
||||
public supports(name = 'supports') {
|
||||
return !!this.featureMap[name];
|
||||
}
|
||||
|
||||
public onEnvChange(func: (envs: ILiteralObject, name: string, value: any) => any) {
|
||||
this.emitter.on('envchange', func);
|
||||
return () => {
|
||||
this.emitter.removeListener('envchange', func);
|
||||
};
|
||||
}
|
||||
|
||||
public getAliSchemaVersion() {
|
||||
return ALI_SCHEMA_VERSION;
|
||||
}
|
||||
}
|
||||
|
||||
export default new Env();
|
||||
17
packages/vision-polyfill/src/field.tsx
Normal file
17
packages/vision-polyfill/src/field.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import { Component } from "react";
|
||||
|
||||
export class Placeholder extends Component {
|
||||
|
||||
}
|
||||
|
||||
const Field = {
|
||||
SettingField: Placeholder,
|
||||
Stage: Placeholder,
|
||||
PopupField: Placeholder,
|
||||
EntryField: Placeholder,
|
||||
AccordionField: Placeholder,
|
||||
BlockField: Placeholder,
|
||||
InlineField: Placeholder
|
||||
};
|
||||
|
||||
export default Field;
|
||||
52
packages/vision-polyfill/src/pages.ts
Normal file
52
packages/vision-polyfill/src/pages.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import { designer } from './editor';
|
||||
import { RootSchema } from '@ali/lowcode-globals';
|
||||
import { DocumentModel } from '@ali/lowcode-designer';
|
||||
|
||||
const { project } = designer;
|
||||
|
||||
export interface OldPageData {
|
||||
id: string;
|
||||
layout: RootSchema;
|
||||
[dataAddon: string]: any;
|
||||
}
|
||||
|
||||
const pages = Object.assign(project, {
|
||||
setPages(pages: OldPageData[]) {
|
||||
project.load({
|
||||
version: '1.0.0',
|
||||
componentsMap: [],
|
||||
componentsTree: pages.map(page => page.layout),
|
||||
});
|
||||
},
|
||||
addPage(data: OldPageData) {
|
||||
return project.open(data.layout);
|
||||
},
|
||||
getPage(fnOrIndex: ((page: DocumentModel) => boolean) | number) {
|
||||
if (typeof fnOrIndex === 'number') {
|
||||
return project.documents[fnOrIndex];
|
||||
} else if (typeof fnOrIndex === 'function') {
|
||||
return project.documents.find(fnOrIndex);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
removePage(page: DocumentModel) {
|
||||
page.remove();
|
||||
},
|
||||
getPages() {
|
||||
return project.documents;
|
||||
},
|
||||
setCurrentPage(page: DocumentModel) {
|
||||
page.active();
|
||||
},
|
||||
getCurrentPage() {
|
||||
return project.currentDocument;
|
||||
},
|
||||
onPagesChange() {
|
||||
// noop
|
||||
},
|
||||
onCurrentPageChange(fn: (page: DocumentModel) => void) {
|
||||
return project.onCurrentDocumentChange(fn);
|
||||
}
|
||||
});
|
||||
|
||||
export default pages;
|
||||
616
packages/vision-polyfill/src/prop.ts
Normal file
616
packages/vision-polyfill/src/prop.ts
Normal file
@ -0,0 +1,616 @@
|
||||
import { Component } from 'react';
|
||||
import { EventEmitter } from 'events';
|
||||
import { fromJS, Iterable, Map as IMMap } from 'immutable';
|
||||
import logger from '@ali/vu-logger';
|
||||
import { uniqueId, cloneDeep, isDataEqual, combineInitial, Transducer } from '@ali/ve-utils';
|
||||
import I18nUtil from '@ali/ve-i18n-util';
|
||||
import { getSetter } from '@ali/lowcode-globals';
|
||||
import { editor } from './editor';
|
||||
import { OldPropConfig, DISPLAY_TYPE } from './bundle/upgrade-metadata';
|
||||
|
||||
type IPropConfig = OldPropConfig;
|
||||
|
||||
// 1: chain -1: start 0: discard
|
||||
const CHAIN_START = -1;
|
||||
const CHAIN_HAS_REACH = 0;
|
||||
|
||||
export enum PROP_VALUE_CHANGED_TYPE {
|
||||
/**
|
||||
* normal set value
|
||||
*/
|
||||
SET_VALUE = 'SET_VALUE',
|
||||
/**
|
||||
* value changed caused by sub-prop value change
|
||||
*/
|
||||
SUB_VALUE_CHANGE = 'SUB_VALUE_CHANGE',
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamic setter will use 've.plugin.setterProvider' to
|
||||
* calculate setter type in runtime
|
||||
*/
|
||||
let dynamicSetterProvider: any;
|
||||
|
||||
export interface IHotDataMap extends IMMap<string, any> {
|
||||
value: any;
|
||||
hotValue: any;
|
||||
}
|
||||
|
||||
export interface ISetValueOptions {
|
||||
disableMutator?: boolean;
|
||||
type?: PROP_VALUE_CHANGED_TYPE;
|
||||
}
|
||||
|
||||
export interface IVariableSettable {
|
||||
useVariable?: boolean;
|
||||
variableValue: string;
|
||||
isUseVariable: () => boolean;
|
||||
isSupportVariable: () => boolean;
|
||||
setVariableValue: (value: string) => void;
|
||||
setUseVariable: (flag?: boolean) => void;
|
||||
getVariableValue: () => string;
|
||||
onUseVariableChange: (func: (data: { isUseVariable: boolean }) => any) => void;
|
||||
}
|
||||
|
||||
export default class Prop implements IVariableSettable {
|
||||
|
||||
/**
|
||||
* Setters predefined as default options
|
||||
* can by selected by user for every prop
|
||||
*
|
||||
* @static
|
||||
* @memberof Prop
|
||||
*/
|
||||
public static INSET_SETTER = {};
|
||||
|
||||
public id: string;
|
||||
public emitter: EventEmitter;
|
||||
|
||||
public inited: boolean;
|
||||
public i18nLink: any;
|
||||
public loopLock: boolean;
|
||||
|
||||
public props: any;
|
||||
public parent: any;
|
||||
|
||||
public config: IPropConfig;
|
||||
public initial: any;
|
||||
public initialData: any;
|
||||
|
||||
public expanded: boolean;
|
||||
public useVariable?: boolean;
|
||||
|
||||
/**
|
||||
* value to be saved in schema it is usually JSON serialized
|
||||
* prototype.js can config Transducer.toNative to generate value
|
||||
*/
|
||||
public value: any;
|
||||
/**
|
||||
* value to be used in VisualDesigner more flexible
|
||||
* prototype.js can config Transducer.toHot to generate hotValue
|
||||
*/
|
||||
public hotValue: any;
|
||||
/**
|
||||
* 启用变量之后,变量表达式字符串值
|
||||
*/
|
||||
public variableValue: string;
|
||||
public hotData: IMMap<string, IHotDataMap>;
|
||||
public defaultValue: any;
|
||||
public transducer: any;
|
||||
public inGroup: boolean;
|
||||
|
||||
constructor(parent: any, config: IPropConfig, data?: any) {
|
||||
if (parent.isProps) {
|
||||
this.props = parent;
|
||||
this.parent = null;
|
||||
} else {
|
||||
this.props = parent.getProps();
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
this.id = uniqueId(null as any, 'prop', 'engine-prop');
|
||||
|
||||
if (typeof config.setter === 'string') {
|
||||
config.setter = getSetter(config.setter)?.component as any;
|
||||
}
|
||||
this.config = config;
|
||||
this.emitter = new EventEmitter();
|
||||
this.emitter.setMaxListeners(100);
|
||||
this.initialData = data;
|
||||
this.useVariable = false;
|
||||
|
||||
dynamicSetterProvider = editor.get('ve.plugin.setterProvider');
|
||||
|
||||
this.beforeInit();
|
||||
}
|
||||
|
||||
public getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public isTab() {
|
||||
return this.getDisplay() === 'tab';
|
||||
}
|
||||
|
||||
public isGroup() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public beforeInit() {
|
||||
if (IMMap.isMap(this.initialData)) {
|
||||
this.value = this.initialData.get('value');
|
||||
if (this.value && typeof this.value.toJS === 'function') {
|
||||
this.value = this.value.toJS();
|
||||
}
|
||||
this.hotData = this.initialData;
|
||||
} else {
|
||||
this.value = this.initialData;
|
||||
}
|
||||
|
||||
this.resolveValue();
|
||||
|
||||
let defaultValue = null;
|
||||
if (this.config.defaultValue !== undefined) {
|
||||
defaultValue = this.config.defaultValue;
|
||||
} else if (typeof this.config.initialValue !== 'function') {
|
||||
defaultValue = this.config.initialValue;
|
||||
}
|
||||
this.defaultValue = defaultValue;
|
||||
this.transducer = new Transducer(this, this.config);
|
||||
this.initial = combineInitial(this, this.config);
|
||||
}
|
||||
|
||||
public resolveValue() {
|
||||
if (this.value && this.value.type === 'variable') {
|
||||
const { value, variable } = this.value;
|
||||
this.value = value;
|
||||
this.variableValue = variable;
|
||||
this.useVariable = this.isSupportVariable();
|
||||
} else {
|
||||
this.useVariable = false;
|
||||
}
|
||||
}
|
||||
|
||||
public init(defaultValue?: any) {
|
||||
if (this.inited) { return; }
|
||||
|
||||
this.value = this.initial(this.value,
|
||||
this.defaultValue != null ? this.defaultValue : defaultValue);
|
||||
|
||||
if (this.hotData) {
|
||||
const tempVal = this.hotData.get('value');
|
||||
// if we create a prop from runtime data, we don't need initial() or set with defaultValue process
|
||||
// but if we got an empty value, we fill with the initial() process and default value
|
||||
if (Iterable.isIterable(tempVal)) {
|
||||
this.value = tempVal.toJS() || this.value;
|
||||
} else {
|
||||
this.value = tempVal || this.value;
|
||||
}
|
||||
this.resolveValue();
|
||||
}
|
||||
|
||||
this.i18nLink = I18nUtil.attach(this, this.value,
|
||||
((val: any) => { this.setValue(val, false, true); }) as any);
|
||||
|
||||
// call config.accessor
|
||||
const value = this.getValue();
|
||||
|
||||
if (this.hotData) {
|
||||
this.hotValue = this.hotData.get('hotValue');
|
||||
if (this.hotValue && Iterable.isIterable(this.hotValue)) {
|
||||
this.hotValue = this.hotValue.toJS();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
this.hotValue = this.transducer.toHot(value);
|
||||
} catch (e) {
|
||||
logger.log('ERROR_PROP_VALUE');
|
||||
logger.warn('属性初始化错误:', this);
|
||||
}
|
||||
|
||||
this.hotData = fromJS({
|
||||
hotValue: this.hotValue,
|
||||
value: this.getMixValue(value),
|
||||
});
|
||||
}
|
||||
this.inited = true;
|
||||
}
|
||||
|
||||
public isInited() {
|
||||
return this.inited;
|
||||
}
|
||||
|
||||
public getHotData() {
|
||||
return this.hotData;
|
||||
}
|
||||
|
||||
public getProps() {
|
||||
return this.props;
|
||||
}
|
||||
|
||||
public getNode(): any {
|
||||
return this.getProps().getNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得属性名称
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
public getName(): string {
|
||||
const ns = this.parent ? `${this.parent.getName()}.` : '';
|
||||
return ns + this.config.name;
|
||||
}
|
||||
|
||||
public getKey() {
|
||||
return this.config.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得属性标题
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
public getTitle() {
|
||||
return this.config.title || this.getName();
|
||||
}
|
||||
|
||||
public getTip() {
|
||||
return this.config.tip || null;
|
||||
}
|
||||
|
||||
public getValue(disableCache?: boolean, options?: {
|
||||
disableAccessor?: boolean;
|
||||
}) {
|
||||
const accessor = this.config.accessor;
|
||||
if (accessor && (!options || !options.disableAccessor)) {
|
||||
const value = accessor.call(this, this.value);
|
||||
if (!disableCache) {
|
||||
this.value = value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public getMixValue(value?: any) {
|
||||
if (value == null) {
|
||||
value = this.getValue();
|
||||
}
|
||||
if (this.isUseVariable()) {
|
||||
value = {
|
||||
type: 'variable',
|
||||
value,
|
||||
variable: this.getVariableValue(),
|
||||
};
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public toData() {
|
||||
return cloneDeep(this.getMixValue());
|
||||
}
|
||||
|
||||
public getDefaultValue() {
|
||||
return this.defaultValue;
|
||||
}
|
||||
|
||||
public getHotValue() {
|
||||
return this.hotValue;
|
||||
}
|
||||
|
||||
public getConfig<K extends keyof IPropConfig>(configName?: K): IPropConfig[K] | IPropConfig {
|
||||
if (configName) {
|
||||
return this.config[configName];
|
||||
}
|
||||
|
||||
return this.config;
|
||||
}
|
||||
|
||||
public sync() {
|
||||
if (this.props.hasReach(this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sync = this.config.sync;
|
||||
if (sync) {
|
||||
const value = sync.call(this, this.getValue(true));
|
||||
if (value !== undefined) {
|
||||
this.setValue(value);
|
||||
}
|
||||
} else {
|
||||
// sync 的时候不再需要调用经过 accessor 处理之后的值了
|
||||
// 这里之所以需要 setValue 是为了过 getValue() 中的 accessor 修饰函数
|
||||
this.setValue(this.getValue(true), false, false, {
|
||||
disableMutator: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public isUseVariable() {
|
||||
return this.useVariable || false;
|
||||
}
|
||||
|
||||
public isSupportVariable() {
|
||||
return this.config.supportVariable || false;
|
||||
}
|
||||
|
||||
public setVariableValue(value: string) {
|
||||
if (!this.isUseVariable()) { return; }
|
||||
|
||||
const state = this.props.chainReach(this);
|
||||
if (state === CHAIN_HAS_REACH) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.variableValue = value;
|
||||
|
||||
if (this.modify()) {
|
||||
this.valueChange();
|
||||
this.props.syncPass(this);
|
||||
}
|
||||
|
||||
if (state === CHAIN_START) {
|
||||
this.props.endChain();
|
||||
}
|
||||
}
|
||||
|
||||
public setUseVariable(flag: boolean = false) {
|
||||
if (this.useVariable === flag) { return; }
|
||||
|
||||
const state = this.props.chainReach(this);
|
||||
if (state === CHAIN_HAS_REACH) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.useVariable = flag;
|
||||
this.expanded = true;
|
||||
|
||||
if (this.modify()) {
|
||||
this.valueChange();
|
||||
this.props.syncPass(this);
|
||||
}
|
||||
|
||||
if (state === CHAIN_START) {
|
||||
this.props.endChain();
|
||||
}
|
||||
|
||||
this.emitter.emit('ve.prop.useVariableChange', { isUseVariable: flag });
|
||||
if (this.config.useVariableChange) {
|
||||
this.config.useVariableChange.call(this, { isUseVariable: flag });
|
||||
}
|
||||
}
|
||||
|
||||
public getVariableValue() {
|
||||
return this.variableValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value
|
||||
* @param isHotValue 是否为设计器热状态值
|
||||
* @param force 是否强制触发更新
|
||||
*/
|
||||
public setValue(value: any, isHotValue?: boolean, force?: boolean, extraOptions?: ISetValueOptions) {
|
||||
const state = this.props.chainReach(this);
|
||||
if (state === CHAIN_HAS_REACH) {
|
||||
return;
|
||||
}
|
||||
|
||||
const preValue = this.value;
|
||||
const preHotValue = this.hotValue;
|
||||
|
||||
if (isHotValue) {
|
||||
this.hotValue = value;
|
||||
this.value = this.transducer.toNative(this.hotValue);
|
||||
} else {
|
||||
if (!isDataEqual(value, this.value)) {
|
||||
this.hotValue = this.transducer.toHot(value);
|
||||
}
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
this.i18nLink = I18nUtil.attach(this, this.value, ((val: any) => this.setValue(val, false, true)) as any);
|
||||
|
||||
const mutator = this.config.mutator;
|
||||
|
||||
if (!extraOptions) {
|
||||
extraOptions = {};
|
||||
}
|
||||
|
||||
if (mutator && !extraOptions.disableMutator) {
|
||||
mutator.call(this, this.value);
|
||||
}
|
||||
|
||||
if (this.modify(force)) {
|
||||
this.valueChange(extraOptions);
|
||||
this.props.syncPass(this);
|
||||
}
|
||||
|
||||
if (state === CHAIN_START) {
|
||||
this.props.endChain();
|
||||
}
|
||||
}
|
||||
|
||||
public setHotValue(hotValue: any, options?: ISetValueOptions) {
|
||||
try {
|
||||
this.setValue(hotValue, true, false, options);
|
||||
} catch (e) {
|
||||
logger.log('ERROR_PROP_VALUE');
|
||||
logger.warn('属性值设置错误:', e, hotValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证是否存在变更
|
||||
* @param force 是否强制返回已变更
|
||||
*/
|
||||
public modify(force?: boolean) {
|
||||
const hotData = this.hotData.merge(fromJS({
|
||||
hotValue: this.getHotValue(),
|
||||
value: this.getMixValue(),
|
||||
}));
|
||||
|
||||
if (!force && hotData.equals(this.hotData)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.hotData = hotData;
|
||||
|
||||
(this.parent || this.props).modify(this.getName());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public setHotData(hotData: IMMap<string, IHotDataMap>, options?: ISetValueOptions) {
|
||||
if (!IMMap.isMap(hotData)) {
|
||||
return;
|
||||
}
|
||||
this.hotData = hotData;
|
||||
let value = hotData.get('value');
|
||||
if (value && typeof value.toJS === 'function') {
|
||||
value = value.toJS();
|
||||
}
|
||||
let hotValue = hotData.get('hotValue');
|
||||
if (hotValue && typeof hotValue.toJS === 'function') {
|
||||
hotValue = hotValue.toJS();
|
||||
}
|
||||
|
||||
const preValue = value;
|
||||
const preHotValue = hotValue;
|
||||
|
||||
this.value = value;
|
||||
this.hotValue = hotValue;
|
||||
this.resolveValue();
|
||||
|
||||
if (!options || !options.disableMutator) {
|
||||
const mutator = this.config.mutator;
|
||||
if (mutator) {
|
||||
mutator.call(this, value);
|
||||
}
|
||||
}
|
||||
|
||||
this.valueChange();
|
||||
}
|
||||
|
||||
public valueChange(options?: ISetValueOptions) {
|
||||
if (this.loopLock) { return; }
|
||||
|
||||
this.emitter.emit('valuechange', options);
|
||||
if (this.parent) {
|
||||
this.parent.valueChange(options);
|
||||
}
|
||||
}
|
||||
|
||||
public getDisplay() {
|
||||
return this.config.display || this.config.fieldStyle || 'block';
|
||||
}
|
||||
|
||||
public isHidden() {
|
||||
if (!this.isInited() || this.getDisplay() === DISPLAY_TYPE.NONE || this.isDisabled()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let hidden = this.config.hidden;
|
||||
if (typeof hidden === 'function') {
|
||||
hidden = hidden.call(this, this.getValue());
|
||||
}
|
||||
return hidden === true;
|
||||
}
|
||||
|
||||
public isDisabled() {
|
||||
let disabled = this.config.disabled;
|
||||
if (typeof disabled === 'function') {
|
||||
disabled = disabled.call(this, this.getValue());
|
||||
}
|
||||
return disabled === true;
|
||||
}
|
||||
|
||||
public isIgnore() {
|
||||
if (this.isDisabled()) { return true; }
|
||||
|
||||
let ignore = this.config.ignore;
|
||||
if (typeof ignore === 'function') {
|
||||
ignore = ignore.call(this, this.getValue());
|
||||
}
|
||||
return ignore === true;
|
||||
}
|
||||
|
||||
public isExpand() {
|
||||
if (this.expanded == null) {
|
||||
this.expanded = !(this.config.collapsed || this.config.fieldCollapsed);
|
||||
}
|
||||
return this.expanded;
|
||||
}
|
||||
|
||||
public toggleExpand() {
|
||||
if (this.expanded) {
|
||||
this.expanded = false;
|
||||
} else {
|
||||
this.expanded = true;
|
||||
}
|
||||
this.emitter.emit('expandchange', this.expanded);
|
||||
}
|
||||
|
||||
public getSetter() {
|
||||
if (dynamicSetterProvider) {
|
||||
const setter = dynamicSetterProvider.call(this, this, this.getNode().getPrototype());
|
||||
if (setter) {
|
||||
return setter;
|
||||
}
|
||||
}
|
||||
const setterConfig = this.config.setter;
|
||||
if (typeof setterConfig === 'function' && !(setterConfig.prototype instanceof Component)) {
|
||||
return (setterConfig as any).call(this, this.getValue());
|
||||
}
|
||||
if (Array.isArray(setterConfig)) {
|
||||
let item;
|
||||
for (item of setterConfig) {
|
||||
if (item.condition?.call(this, this.getValue())) {
|
||||
return item.setter;
|
||||
}
|
||||
}
|
||||
return setterConfig[0].setter;
|
||||
}
|
||||
return setterConfig;
|
||||
}
|
||||
|
||||
public getSetterData(): any {
|
||||
if (Array.isArray(this.config.setter)) {
|
||||
let item;
|
||||
for (item of this.config.setter) {
|
||||
if (item.condition?.call(this, this.getValue())) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return this.config.setter[0];
|
||||
}
|
||||
return { };
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
if (this.i18nLink) {
|
||||
this.i18nLink.detach();
|
||||
}
|
||||
}
|
||||
|
||||
public onValueChange(func: () => any) {
|
||||
this.emitter.on('valuechange', func);
|
||||
return () => {
|
||||
this.emitter.removeListener('valuechange', func);
|
||||
};
|
||||
}
|
||||
|
||||
public onExpandChange(func: () => any) {
|
||||
this.emitter.on('expandchange', func);
|
||||
return () => {
|
||||
this.emitter.removeListener('expandchange', func);
|
||||
};
|
||||
}
|
||||
|
||||
public onUseVariableChange(func: (data: { isUseVariable: boolean }) => any) {
|
||||
this.emitter.on('ve.prop.useVariableChange', func);
|
||||
return () => {
|
||||
this.emitter.removeListener('ve.prop.useVariableChange', func);
|
||||
};
|
||||
}
|
||||
}
|
||||
47
packages/vision-polyfill/src/vision.less
Normal file
47
packages/vision-polyfill/src/vision.less
Normal file
@ -0,0 +1,47 @@
|
||||
html.engine-cursor-move, html.engine-cursor-move * {
|
||||
cursor: grabbing !important
|
||||
}
|
||||
|
||||
html.engine-cursor-copy, html.engine-cursor-copy * {
|
||||
cursor: copy !important
|
||||
}
|
||||
|
||||
html.engine-cursor-ew-resize, html.engine-cursor-ew-resize * {
|
||||
cursor: ew-resize !important
|
||||
}
|
||||
|
||||
body, #engine {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
-webkit-text-size-adjust: none;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
html {
|
||||
min-width: 1024px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
html.engine-blur #engine {
|
||||
-webkit-filter: blur(4px);
|
||||
}
|
||||
@ -2,11 +2,12 @@ import * as utils from '@ali/ve-utils';
|
||||
import Popup from '@ali/ve-popups';
|
||||
import Icons from '@ali/ve-icons';
|
||||
import { render } from 'react-dom';
|
||||
import I18nUtil from '@ali/ve-i18n-util';
|
||||
import { createElement } from 'react';
|
||||
import { VE_EVENTS as EVENTS, VE_HOOKS as HOOKS } from './const';
|
||||
import Bus from './bus';
|
||||
import Symbols from './symbols';
|
||||
import { skeleton } from './editor';
|
||||
import { skeleton, editor } from './editor';
|
||||
import { VisionWorkbench } from './skeleton/workbench';
|
||||
import Panes from './panes';
|
||||
import Exchange from './exchange';
|
||||
@ -15,6 +16,11 @@ import VisualManager from './base/visualManager';
|
||||
import Trunk from './bundle/trunk';
|
||||
import Prototype from './bundle/prototype';
|
||||
import Bundle from './bundle/bundle';
|
||||
import Pages from './pages';
|
||||
import Field from './field';
|
||||
import Prop from './prop';
|
||||
import Env from './env';
|
||||
import './vision.less';
|
||||
|
||||
function init(container?: Element) {
|
||||
if (!container) {
|
||||
@ -31,7 +37,13 @@ function init(container?: Element) {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* VE.ui.xxx
|
||||
*
|
||||
* Core UI Components
|
||||
*/
|
||||
const ui = {
|
||||
Field,
|
||||
Icon: Icons,
|
||||
Icons,
|
||||
Popup,
|
||||
@ -39,11 +51,14 @@ const ui = {
|
||||
|
||||
const modules = {
|
||||
VisualManager,
|
||||
I18nUtil,
|
||||
Prop,
|
||||
};
|
||||
|
||||
const context = new VisualEngineContext();
|
||||
|
||||
const VisualEngine = {
|
||||
editor,
|
||||
/**
|
||||
* VE.Popup
|
||||
*/
|
||||
@ -52,6 +67,8 @@ const VisualEngine = {
|
||||
* VE Utils
|
||||
*/
|
||||
utils,
|
||||
I18nUtil,
|
||||
Env,
|
||||
/* pub/sub 集线器 */
|
||||
Bus,
|
||||
/* 事件 */
|
||||
@ -74,11 +91,13 @@ const VisualEngine = {
|
||||
Trunk,
|
||||
Prototype,
|
||||
Bundle,
|
||||
Pages,
|
||||
};
|
||||
|
||||
export default VisualEngine;
|
||||
|
||||
(window as any).VisualEngine = VisualEngine;
|
||||
|
||||
/*
|
||||
console.log(
|
||||
`%cLowcodeEngine %cv${VERSION}`,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user