新增columns的配置

This commit is contained in:
荣彬 2020-07-27 22:13:43 +08:00
commit 23bc6214d6
27 changed files with 1853 additions and 543 deletions

View File

@ -25,6 +25,12 @@
{ {
"componentName": "Page", "componentName": "Page",
"title": "Page", "title": "Page",
"props": [
{
"name": "style",
"propType": "object"
}
],
"configure": { "configure": {
"events": { "events": {
"supportedLifecycles": [ "supportedLifecycles": [
@ -60,6 +66,272 @@
} }
} }
}, },
{
"componentName": "Table",
"title": "Table",
"docUrl": "",
"screenshot": "",
"npm": {
"package": "@alifd/next",
"version": "1.19.18",
"exportName": "Table",
"main": "src/index.js",
"destructuring": true,
"subName": ""
},
"props": [
{
"name": "prefix",
"propType": "string"
},
{
"name": "pure",
"propType": "bool"
},
{
"name": "rtl",
"propType": "bool"
},
{
"name": "tableLayout",
"propType": {
"type": "oneOf",
"value": [
"fixed",
"auto"
]
}
},
{
"name": "tableWidth",
"propType": "number"
},
{
"name": "className",
"propType": "string"
},
{
"name": "style",
"propType": "object"
},
{
"name": "size",
"propType": {
"type": "oneOf",
"value": [
"small",
"medium"
]
}
},
{
"name": "dataSource",
"propType": {
"type": "arrayOf",
"value": "object"
}
},
{
"name": "entireDataSource",
"propType": "array"
},
{
"name": "onRowClick",
"propType": "func"
},
{
"name": "onRowMouseEnter",
"propType": "func"
},
{
"name": "rowProps",
"propType": "func"
},
{
"name": "cellProps",
"propType": "func"
},
{
"name": "hasBorder",
"propType": "bool"
},
{
"name": "hasHeader",
"propType": "bool"
},
{
"name": "isZebra",
"propType": "bool"
},
{
"name": "loading",
"propType": "bool"
},
{
"name": "filterParams",
"propType": "object"
},
{
"name": "sort",
"propType": "object"
},
{
"name": "sortIcons",
"propType": "object"
},
{
"name": "locale",
"propType": "object"
},
{
"name": "components",
"propType": "object"
},
{
"name": "columns",
"propType": "array"
},
{
"name": "emptyContent",
"propType": "node"
},
{
"name": "primaryKey",
"propType": "string"
},
{
"name": "lockType",
"propType": {
"type": "oneOf",
"value": [
"left",
"right"
]
}
},{
"name": "style",
"propType": "object"
},
{
"name": "wrapperContent",
"propType": "any"
},
{
"name": "refs",
"propType": "object"
},
{
"name": "expandedRowRender",
"propType": "func"
},
{
"name": "expandedRowIndent",
"propType": "array"
},
{
"name": "hasExpandedRowCtrl",
"propType": "bool"
},
{
"name": "getExpandedColProps",
"propType": "func"
},
{
"name": "openRowKeys",
"propType": "array"
},
{
"name": "onRowOpen",
"propType": "func"
},
{
"name": "onExpandedRowClick",
"propType": "func"
},
{
"name": "fixedHeader",
"propType": "bool"
},
{
"name": "rowSelection",
"propType": "object"
},
{
"name": "stickyHeader",
"propType": "bool"
},
{
"name": "offsetTop",
"propType": "number"
},
{
"name": "affixProps",
"propType": "object"
},
{
"name": "indent",
"propType": "number"
},
{
"name": "isTree",
"propType": "bool"
},
{
"name": "useVirtual",
"propType": "bool"
},
{
"name": "onBodyScroll",
"propType": "func"
},
{
"name": "expandedIndexSimulate",
"propType": "bool"
},
{
"name": "crossline",
"propType": "bool"
},
{
"name": "lengths",
"propType": "object"
}
],
"configure": {
"component": {
"isContainer": true
},
"props": {
"isExtends": true,
"override": [{
"name": "dataSource",
"setter": "JsonSetter"
}]
}
}
},
{
"componentName": "Table.Column",
"title": "Table.Column",
"npm": {
"package": "@alifd/next",
"version": "1.19.18",
"exportName": "Table",
"main": "src/index.js",
"destructuring": true,
"subName": "Column"
},
"props": [
{
"name": "title",
"propType": "string"
},
{
"name": "dataIndex",
"propType": "string"
}
]
},
{ {
"componentName": "Badge", "componentName": "Badge",
"title": "Badge", "title": "Badge",
@ -614,7 +886,7 @@
"name": "children", "name": "children",
"propType": { "propType": {
"type": "instanceOf", "type": "instanceOf",
"value": "custom" "value": "node"
}, },
"description": "面包屑子节点,需传入 Breadcrumb.Item" "description": "面包屑子节点,需传入 Breadcrumb.Item"
}, },
@ -663,7 +935,12 @@
"name": "style", "name": "style",
"propType": "object" "propType": "object"
} }
] ],
"configure": {
"component": {
"isContainer": true
}
}
}, },
{ {
"componentName": "MCBreadcrumb", "componentName": "MCBreadcrumb",
@ -699,7 +976,7 @@
"name": "children", "name": "children",
"propType": { "propType": {
"type": "instanceOf", "type": "instanceOf",
"value": "custom" "value": "node"
}, },
"description": "面包屑子节点,需传入 Breadcrumb.Item" "description": "面包屑子节点,需传入 Breadcrumb.Item"
}, },
@ -748,7 +1025,12 @@
"name": "style", "name": "style",
"propType": "object" "propType": "object"
} }
] ],
"configure": {
"component": {
"isContainer": true
}
}
}, },
{ {
"componentName": "Breadcrumb.Item", "componentName": "Breadcrumb.Item",
@ -804,7 +1086,12 @@
"name": "style", "name": "style",
"propType": "object" "propType": "object"
} }
] ],
"configure": {
"component": {
"isContainer": true
}
}
}, },
{ {
"componentName": "Button", "componentName": "Button",
@ -962,12 +1249,7 @@
"propType": "object", "propType": "object",
"description": "自定义内联样式" "description": "自定义内联样式"
} }
], ]
"configure": {
"component": {
"isContainer": true
}
}
}, },
{ {
"componentName": "Button.Group", "componentName": "Button.Group",
@ -3823,7 +4105,7 @@
}, },
{ {
"name": "visible", "name": "visible",
"propType": "bool", "propType": "oneOfType",
"description": "是否显示", "description": "是否显示",
"defaultValue": false "defaultValue": false
}, },
@ -4000,7 +4282,11 @@
"name": "style", "name": "style",
"propType": "object" "propType": "object"
} }
] ],
"configure": {
"isContainer": true,
"isModel": true
}
}, },
{ {
"componentName": "Inner", "componentName": "Inner",
@ -4266,26 +4552,6 @@
} }
] ]
}, },
{
"componentName": "Table",
"title": "Table",
"docUrl": "",
"screenshot": "",
"npm": {
"package": "@alifd/next",
"version": "1.19.18",
"exportName": "Table",
"main": "src/index.js",
"destructuring": true,
"subName": ""
},
"props": [
{
"name": "style",
"propType": "object"
}
]
},
{ {
"componentName": "Form", "componentName": "Form",
"title": "Form", "title": "Form",
@ -11888,6 +12154,72 @@
} }
} }
] ]
},{
"componentName": "Table",
"title": "表格",
"icon": "https://alifd.oss-cn-hangzhou.aliyuncs.com/fusion-cool/icons/icon-light/ic_light_table.png",
"package": "@alife/next",
"library": "Next",
"snippets": [
{
"title": "表格",
"screenshot": "https://alifd.oss-cn-hangzhou.aliyuncs.com/fusion-cool/icons/icon-light/ic_light_table.png",
"schema": {
"componentName": "Table",
"props": {
"dataSource": [{
"id": 1, "time": "2016"
},{
"id": 2, "time": "2017"
}],
"size": "medium",
"prefix": "next-",
"hasBorder": true,
"hasHeader": true,
"isZebra": false,
"loading": false,
"expandedIndexSimulate": false,
"primaryKey": "id",
"locale": "zhCN.Table",
"crossline": false
},
"children": [
{
"componentName": "Table.Column",
"props": {
"title": "id",
"dataIndex": "id"
}
},
{
"componentName": "Table.Column",
"props": {
"title": "time",
"dataIndex": "time"
}
}
]
}
}
]
},{
"componentName": "Table.Column",
"title": "表格列",
"icon": "https://alifd.oss-cn-hangzhou.aliyuncs.com/fusion-cool/icons/icon-light/ic_light_table.png",
"package": "@alife/next",
"library": "Next",
"snippets": [
{
"title": "表格列",
"screenshot": "https://alifd.oss-cn-hangzhou.aliyuncs.com/fusion-cool/icons/icon-light/ic_light_table.png",
"schema": {
"componentName": "Table.Column",
"props": {
"title": "name"
}
}
}
]
}, },
{ {
"componentName": "Calendar", "componentName": "Calendar",
@ -12381,6 +12713,54 @@
} }
] ]
}, },
{
"componentName": "Button.Group",
"title": "按钮组",
"icon": "",
"package": "@alife/next",
"library": "Next",
"snippets": [
{
"title": "按钮组",
"screenshot": "https://img.alicdn.com/tfs/TB1t6dhvV67gK0jSZPfXXahhFXa-310-122.png",
"schema": {
"componentName": "Button.Group",
"props": {
},
"children": [{
"componentName": "Button",
"props": {
"type": "primary",
"style": {
"margin": "0 5px 0 5px"
},
"htmlType": "submit"
},
"children": [
{
"componentName": "Icon",
"props": {
"type": "success"
}
},
"提交"
]
}, {
"componentName": "Button",
"props": {
"type": "normal",
"style": {
"margin": "0 5px 0 5px"
},
"htmlType": "reset"
},
"children": "重置"
}]
}
}
]
},
{ {
"componentName": "Divider", "componentName": "Divider",
"title": "分隔符", "title": "分隔符",
@ -12559,6 +12939,28 @@
} }
} }
] ]
},{
"componentName": "Breadcrumb.Item",
"title": "面包屑 Item",
"icon": "",
"package": "@alife/next",
"library": "Next",
"snippets": [
{
"title": "面包屑",
"screenshot": "https://alifd.oss-cn-hangzhou.aliyuncs.com/fusion-cool/icons/icon-light/ic_light_breadcrumb.png",
"schema": {
"componentName": "Breadcrumb.Item",
"props": {
"prefix": "next-"
},
"children": [
"222",
"222111"
]
}
}
]
}, },
{ {
"componentName": "MCBreadcrumb", "componentName": "MCBreadcrumb",
@ -12763,17 +13165,23 @@
}, },
{ {
"componentName": "Form.Item", "componentName": "Form.Item",
"title": "表单辅助工具", "title": "Form.Item",
"icon": "", "icon": "",
"package": "@alife/next", "package": "@alife/next",
"library": "Next", "library": "Next",
"snippets": [ "snippets": [
{ {
"title": "表单辅助工具", "title": "Form.Item",
"screenshot": "", "screenshot": "",
"schema": { "schema": {
"componentName": "Form.Item", "componentName": "Form.Item",
"props": {} "props": {
"style":{
"margin-bottom": "0",
"min-width": "200px",
"min-height": "28px"
}
}
} }
} }
] ]

View File

@ -1,138 +1,420 @@
{ {
"componentName": "Page", "componentName": "Page",
"id": "node_dockcviv8fo1",
"props": {
"ref": "outterView",
"autoLoading": true,
"style": {
"padding": "0 5px 0 5px"
}
},
"fileName": "test", "fileName": "test",
"dataSource": { "dataSource": {
"list": [] "list": []
}, },
"state": { "state": {
"text": "outter" "text": "outter",
"isShowDialog": false
}, },
"css": "body {font-size: 12px;} .botton{width:100px;color:#ff00ff}", "css": "body {font-size: 12px;} .botton{width:100px;color:#ff00ff}",
"lifeCycles": { "lifeCycles": {
"componentDidMount": { "componentDidMount": {
"type": "JSExpression", "type": "JSFunction",
"value": "function() {\n \t\tconsole.log('did mount');\n\t}" "value": "function() {\n console.log('did mount');\n }"
}, },
"componentWillUnmount": { "componentWillUnmount": {
"type": "JSExpression", "type": "JSFunction",
"value": "function() {\n \t\tconsole.log('will umount');\n\t}" "value": "function() {\n console.log('will umount');\n }"
} }
}, },
"methods": { "methods": {
"testFunc": { "testFunc": {
"type": "JSFunction", "type": "JSFunction",
"value": "function() {console.log('test func');}" "value": "function() {\n console.log('test func');\n }"
} },
}, "onClick": {
"type": "JSFunction",
"props": { "value": "function(){\n this.setState({\n isShowDialog:true\n })\n\t}"
"ref": "outterView",
"autoLoading": true,
"style": {
"padding": 20
} }
}, },
"children": [{ "children": [{
"componentName": "Form", "componentName": "Box",
"id": "node_dockcy8n9xed",
"props": { "props": {
"labelCol": 3, "style": {
"style": {}, "backgroundColor": "rgba(31,56,88,0.1)",
"ref": "testForm" "padding": "12px 12px 12px 12px"
}
}, },
"children": [{ "children": [{
"componentName": "Form.Item", "componentName": "Box",
"props": { "id": "node_dockcy8n9xee",
"label": "姓名:",
"name": "name",
"initValue": "李雷"
},
"children": [{
"componentName": "Input",
"props": {
"placeholder": "请输入",
"size": "medium",
"style": {
"width": 320
}
}
}]
}, {
"componentName": "Form.Item",
"props": {
"label": "年龄:",
"name": "age",
"initValue": "22"
},
"children": [{
"componentName": "NumberPicker",
"props": {
"size": "medium",
"type": "normal"
}
}]
}, {
"componentName": "Form.Item",
"props": {
"label": "职业:",
"name": "profession"
},
"children": [{
"componentName": "Select",
"props": {
"dataSource": [{
"label": "教师",
"value": "t"
}, {
"label": "医生",
"value": "d"
}, {
"label": "歌手",
"value": "s"
}]
}
}]
}, {
"componentName": "Form.Item",
"props": { "props": {
"style": { "style": {
"textAlign": "center" "padding": "12px 12px 12px 12px",
"backgroundColor": "#ffffff"
} }
}, },
"children": [{ "children": [{
"componentName": "Button.Group", "componentName": "Breadcrumb",
"props": {}, "id": "node_dockcy8n9xef",
"props": {
"prefix": "next-",
"maxNode": 100,
"component": "nav"
},
"children": [{ "children": [{
"componentName": "Button", "componentName": "Breadcrumb.Item",
"id": "node_dockcy8n9xeg",
"props": { "props": {
"type": "primary", "prefix": "next-"
"style": {
"margin": "0 5px 0 5px"
},
"htmlType": "submit"
}, },
"children": [ "children": ["首页"]
{ }, {
"componentName": "Breadcrumb.Item",
"id": "node_dockcy8n9xei",
"props": {
"prefix": "next-"
},
"children": ["品质中台"]
}, {
"componentName": "Breadcrumb.Item",
"id": "node_dockcy8n9xek",
"props": {
"prefix": "next-"
},
"children": ["商家品质页面管理"]
}, {
"componentName": "Breadcrumb.Item",
"id": "node_dockcy8n9xem",
"props": {
"prefix": "next-"
},
"children": ["质检知识条配置"]
}]
}]
}, {
"componentName": "Box",
"id": "node_dockcy8n9xeo",
"props": {
"style": {
"marginTop": "12px",
"backgroundColor": "#ffffff"
}
},
"children": [{
"componentName": "Form",
"id": "node_dockcy8n9xep",
"props": {
"inline": true,
"style": {
"marginTop": "12px",
"marginRight": "12px",
"marginLeft": "12px"
},
"__events": []
},
"children": [{
"componentName": "Form.Item",
"id": "node_dockcy8n9xeq",
"props": {
"style": {
"marginBottom": "0"
},
"label": "类目名:"
},
"children": [{
"componentName": "Select",
"id": "node_dockcy8n9xer",
"props": {
"mode": "single",
"hasArrow": true,
"cacheValue": true,
"style": {
"width": "150px"
}
}
}]
}, {
"componentName": "Form.Item",
"id": "node_dockcy8n9xes",
"props": {
"style": {
"marginBottom": "0"
},
"label": "项目类型:"
},
"children": [{
"componentName": "Select",
"id": "node_dockcy8n9xet",
"props": {
"mode": "single",
"hasArrow": true,
"cacheValue": true,
"style": {
"width": "200px"
}
}
}]
}, {
"componentName": "Form.Item",
"id": "node_dockcy8n9xeu",
"props": {
"style": {
"marginBottom": "0"
},
"label": "项目 ID"
},
"children": [{
"componentName": "Input",
"id": "node_dockcy8n9xev",
"props": {
"hasBorder": true,
"size": "medium",
"autoComplete": "off",
"style": {
"width": "200px"
}
}
}]
}, {
"componentName": "Button.Group",
"id": "node_dockcy8n9xew",
"props": {},
"children": [{
"componentName": "Button",
"id": "node_dockcy8n9xex",
"props": {
"type": "primary",
"style": {
"margin": "0 5px 0 5px"
},
"htmlType": "submit"
},
"children": [{
"componentName": "Icon", "componentName": "Icon",
"id": "node_dockcy8n9xey",
"props": { "props": {
"type": "success" "type": "success"
} }
}, "搜索"]
}, {
"componentName": "Button",
"id": "node_dockcy8n9xe10",
"props": {
"type": "normal",
"style": {
"margin": "0 5px 0 5px"
},
"htmlType": "reset"
}, },
"提交" "children": ["清空"]
] }]
}, {
"componentName": "Button",
"props": {
"type": "normal",
"style": {
"margin": "0 5px 0 5px"
},
"htmlType": "reset"
},
"children": "重置"
}] }]
}] }]
}, {
"componentName": "Box",
"id": "node_dockcy8n9xe12",
"props": {
"style": {
"justifyContent": "flex-end",
"display": "flex",
"backgroundColor": "#ffffff",
"flexDirection": "row",
"paddingRight": "24px"
}
},
"children": [{
"componentName": "Button",
"id": "node_dockcy8n9xe13",
"props": {
"prefix": "next-",
"type": "primary",
"size": "medium",
"htmlType": "button",
"component": "button",
"style": {
"width": "100px"
},
"events": {
"onClick": {
"type": "JSFunction",
"value": "function(){ this.onClick() }",
"__eventData": {
"type": "componentEvent",
"name": "onClick",
"relatedEventName": "onClick"
}
}
},
"__events": [{
"type": "componentEvent",
"name": "onClick",
"relatedEventName": "onClick"
}],
"onClick": {
"type": "JSFunction",
"value": "function(){ this.onClick() }"
}
},
"children": ["新建配置"]
}]
}, {
"componentName": "Box",
"id": "node_dockcy8n9xe15",
"props": {
"style": {
"backgroundColor": "#ffffff"
}
},
"children": [{
"componentName": "Table",
"id": "node_dockcy8n9xe16",
"props": {
"dataSource": [{
"firstCategory": "其他",
"secondCategory": "新品预览",
"leafCategory": "",
"projectType": "标识判断",
"projectId": "",
"title": "其他类目->新品预览类目类型知识库",
"url": "其他",
"operation": "编辑"
}, {
"firstCategory": "其他",
"secondCategory": "新品预览",
"leafCategory": "",
"projectType": "",
"projectId": "1",
"title": "其他类目->新品预览项目Id知识库",
"url": "其他",
"operation": "编辑"
}],
"size": "medium",
"prefix": "next-",
"hasBorder": true,
"hasHeader": true,
"isZebra": false,
"loading": false,
"expandedIndexSimulate": false,
"primaryKey": "id",
"locale": "zhCN.Table",
"crossline": false,
"style": {
"margin": "24px 12px 24px 12px"
}
},
"children": [{
"componentName": "Table.Column",
"id": "node_dockcy8n9xe17",
"props": {
"title": "一级类目",
"dataIndex": "firstCategory"
}
}, {
"componentName": "Table.Column",
"id": "node_dockcy8n9xe18",
"props": {
"title": "二级类目",
"dataIndex": "secondCategory"
}
}, {
"componentName": "Table.Column",
"id": "node_dockcy8n9xe19",
"props": {
"title": "叶子类目",
"dataIndex": "leafCategory"
}
}, {
"componentName": "Table.Column",
"id": "node_dockcy8n9xe1a",
"props": {
"title": "项目类型",
"dataIndex": "projectType"
}
}, {
"componentName": "Table.Column",
"id": "node_dockcy8n9xe1b",
"props": {
"title": "项目 ID",
"dataIndex": "projectId"
}
}, {
"componentName": "Table.Column",
"id": "node_dockcy8n9xe1c",
"props": {
"title": "知识条标题",
"dataIndex": "title"
}
}, {
"componentName": "Table.Column",
"id": "node_dockcy8n9xe1d",
"props": {
"title": "知识条链接",
"dataIndex": "url"
}
}, {
"componentName": "Table.Column",
"id": "node_dockcy8n9xe1e",
"props": {
"title": "操作",
"dataIndex": "operation"
}
}]
}]
}, {
"componentName": "Box",
"id": "node_dockcy8n9xe1f",
"props": {
"style": {
"backgroundColor": "#ffffff",
"paddingBottom": "24px"
}
},
"children": [{
"componentName": "Pagination",
"id": "node_dockcy8n9xe1g",
"props": {
"prefix": "next-",
"type": "normal",
"shape": "normal",
"size": "medium",
"defaultCurrent": 1,
"total": 100,
"pageShowCount": 5,
"pageSize": 10,
"pageSizePosition": "start",
"showJump": true,
"style": {
"display": "flex",
"justifyContent": "flex-end"
}
}
}]
}] }]
}, {
"componentName": "Dialog",
"id": "node_dockcy8n9xe1h",
"props": {
"prefix": "next-",
"footerAlign": "right",
"footerActions": ["ok", "cancel"],
"closeable": "esc,close",
"hasMask": true,
"align": "cc cc",
"minMargin": 40,
"visible": {
"type": "JSExpression",
"value": "this.state.isShowDialog"
},
"children": {
"type": "JSSlot"
},
"title": "标题",
"footer": {
"type": "JSSlot"
},
"events": []
}
}] }]
} }

View File

@ -24,8 +24,8 @@ interface IModuleInfo {
function getDirFromRoot(root: IResultDir, path: string[]): IResultDir { function getDirFromRoot(root: IResultDir, path: string[]): IResultDir {
let current: IResultDir = root; let current: IResultDir = root;
path.forEach(p => { path.forEach((p) => {
const exist = current.dirs.find(d => d.name === p); const exist = current.dirs.find((d) => d.name === p);
if (exist) { if (exist) {
current = exist; current = exist;
} else { } else {
@ -57,7 +57,7 @@ export class ProjectBuilder implements IProjectBuilder {
this.postProcessors = postProcessors; this.postProcessors = postProcessors;
} }
public async generateProject(schema: IProjectSchema | string): Promise<IResultDir> { async generateProject(schema: IProjectSchema | string): Promise<IResultDir> {
// Init // Init
const schemaParser: ISchemaParser = new SchemaParser(); const schemaParser: ISchemaParser = new SchemaParser();
const builders = this.createModuleBuilders(); const builders = this.createModuleBuilders();
@ -76,7 +76,7 @@ export class ProjectBuilder implements IProjectBuilder {
// components // components
// pages // pages
const containerBuildResult: IModuleInfo[] = await Promise.all<IModuleInfo>( const containerBuildResult: IModuleInfo[] = await Promise.all<IModuleInfo>(
parseResult.containers.map(async containerInfo => { parseResult.containers.map(async (containerInfo) => {
let builder: IModuleBuilder; let builder: IModuleBuilder;
let path: string[]; let path: string[];
if (containerInfo.containerType === 'Page') { if (containerInfo.containerType === 'Page') {
@ -100,9 +100,7 @@ export class ProjectBuilder implements IProjectBuilder {
// router // router
if (parseResult.globalRouter && builders.router) { if (parseResult.globalRouter && builders.router) {
const { files } = await builders.router.generateModule( const { files } = await builders.router.generateModule(parseResult.globalRouter);
parseResult.globalRouter,
);
buildResult.push({ buildResult.push({
path: this.template.slots.router.path, path: this.template.slots.router.path,
@ -112,9 +110,7 @@ export class ProjectBuilder implements IProjectBuilder {
// entry // entry
if (parseResult.project && builders.entry) { if (parseResult.project && builders.entry) {
const { files } = await builders.entry.generateModule( const { files } = await builders.entry.generateModule(parseResult.project);
parseResult.project,
);
buildResult.push({ buildResult.push({
path: this.template.slots.entry.path, path: this.template.slots.entry.path,
@ -122,14 +118,8 @@ export class ProjectBuilder implements IProjectBuilder {
}); });
} }
// constants? // constants?
if ( if (parseResult.project && builders.constants && this.template.slots.constants) {
parseResult.project && const { files } = await builders.constants.generateModule(parseResult.project);
builders.constants &&
this.template.slots.constants
) {
const { files } = await builders.constants.generateModule(
parseResult.project,
);
buildResult.push({ buildResult.push({
path: this.template.slots.constants.path, path: this.template.slots.constants.path,
@ -137,14 +127,8 @@ export class ProjectBuilder implements IProjectBuilder {
}); });
} }
// utils? // utils?
if ( if (parseResult.globalUtils && builders.utils && this.template.slots.utils) {
parseResult.globalUtils && const { files } = await builders.utils.generateModule(parseResult.globalUtils);
builders.utils &&
this.template.slots.utils
) {
const { files } = await builders.utils.generateModule(
parseResult.globalUtils,
);
buildResult.push({ buildResult.push({
path: this.template.slots.utils.path, path: this.template.slots.utils.path,
@ -153,9 +137,7 @@ export class ProjectBuilder implements IProjectBuilder {
} }
// i18n? // i18n?
if (parseResult.globalI18n && builders.i18n && this.template.slots.i18n) { if (parseResult.globalI18n && builders.i18n && this.template.slots.i18n) {
const { files } = await builders.i18n.generateModule( const { files } = await builders.i18n.generateModule(parseResult.globalI18n);
parseResult.globalI18n,
);
buildResult.push({ buildResult.push({
path: this.template.slots.i18n.path, path: this.template.slots.i18n.path,
@ -164,9 +146,7 @@ export class ProjectBuilder implements IProjectBuilder {
} }
// globalStyle // globalStyle
if (parseResult.project && builders.globalStyle) { if (parseResult.project && builders.globalStyle) {
const { files } = await builders.globalStyle.generateModule( const { files } = await builders.globalStyle.generateModule(parseResult.project);
parseResult.project,
);
buildResult.push({ buildResult.push({
path: this.template.slots.globalStyle.path, path: this.template.slots.globalStyle.path,
@ -175,9 +155,7 @@ export class ProjectBuilder implements IProjectBuilder {
} }
// htmlEntry // htmlEntry
if (parseResult.project && builders.htmlEntry) { if (parseResult.project && builders.htmlEntry) {
const { files } = await builders.htmlEntry.generateModule( const { files } = await builders.htmlEntry.generateModule(parseResult.project);
parseResult.project,
);
buildResult.push({ buildResult.push({
path: this.template.slots.htmlEntry.path, path: this.template.slots.htmlEntry.path,
@ -186,9 +164,7 @@ export class ProjectBuilder implements IProjectBuilder {
} }
// packageJSON // packageJSON
if (parseResult.project && builders.packageJSON) { if (parseResult.project && builders.packageJSON) {
const { files } = await builders.packageJSON.generateModule( const { files } = await builders.packageJSON.generateModule(parseResult.project);
parseResult.project,
);
buildResult.push({ buildResult.push({
path: this.template.slots.packageJSON.path, path: this.template.slots.packageJSON.path,
@ -199,14 +175,14 @@ export class ProjectBuilder implements IProjectBuilder {
// Post Process // Post Process
// Combine Modules // Combine Modules
buildResult.forEach(moduleInfo => { buildResult.forEach((moduleInfo) => {
let targetDir = getDirFromRoot(projectRoot, moduleInfo.path); let targetDir = getDirFromRoot(projectRoot, moduleInfo.path);
if (moduleInfo.moduleName) { if (moduleInfo.moduleName) {
const dir = new ResultDir(moduleInfo.moduleName); const dir = new ResultDir(moduleInfo.moduleName);
targetDir.addDirectory(dir); targetDir.addDirectory(dir);
targetDir = dir; targetDir = dir;
} }
moduleInfo.files.forEach(file => targetDir.addFile(file)); moduleInfo.files.forEach((file) => targetDir.addFile(file));
}); });
return projectRoot; return projectRoot;
@ -215,7 +191,7 @@ export class ProjectBuilder implements IProjectBuilder {
private createModuleBuilders(): Record<string, IModuleBuilder> { private createModuleBuilders(): Record<string, IModuleBuilder> {
const builders: Record<string, IModuleBuilder> = {}; const builders: Record<string, IModuleBuilder> = {};
Object.keys(this.plugins).forEach(pluginName => { Object.keys(this.plugins).forEach((pluginName) => {
if (this.plugins[pluginName].length > 0) { if (this.plugins[pluginName].length > 0) {
const options: { mainFileName?: string } = {}; const options: { mainFileName?: string } = {};
if (this.template.slots[pluginName] && this.template.slots[pluginName].fileName) { if (this.template.slots[pluginName] && this.template.slots[pluginName].fileName) {

View File

@ -11,11 +11,7 @@ import createRecoreProjectBuilder from './solutions/recore';
// 引入说明 // 引入说明
import { REACT_CHUNK_NAME } from './plugins/component/react/const'; import { REACT_CHUNK_NAME } from './plugins/component/react/const';
import { import { COMMON_CHUNK_NAME, CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from './const/generator';
COMMON_CHUNK_NAME,
CLASS_DEFINE_CHUNK_NAME,
DEFAULT_LINK_AFTER,
} from './const/generator';
// 引入通用插件组 // 引入通用插件组
import esmodule from './plugins/common/esmodule'; import esmodule from './plugins/common/esmodule';

View File

@ -5,7 +5,7 @@
import { SUPPORT_SCHEMA_VERSION_LIST } from '../const'; import { SUPPORT_SCHEMA_VERSION_LIST } from '../const';
import { handleChildren } from '../utils/nodeToJSX'; import { handleSubNodes } from '../utils/nodeToJSX';
import { uniqueArray } from '../utils/common'; import { uniqueArray } from '../utils/common';
import { import {
@ -198,11 +198,15 @@ class SchemaParser implements ISchemaParser {
} }
getComponentNames(children: ChildNodeType): string[] { getComponentNames(children: ChildNodeType): string[] {
return handleChildren<string>(children, { return handleSubNodes<string>(
node: (i: IComponentNodeItem) => [i.componentName], children,
}, { {
rerun: true, node: (i: IComponentNodeItem) => [i.componentName],
}); },
{
rerun: true,
},
);
} }
} }

View File

@ -15,6 +15,8 @@ import {
IWithDependency, IWithDependency,
} from '../../types'; } from '../../types';
import { isValidIdentifier } from '../../utils/validate';
function groupDepsByPack(deps: IDependency[]): Record<string, IDependency[]> { function groupDepsByPack(deps: IDependency[]): Record<string, IDependency[]> {
const depMap: Record<string, IDependency[]> = {}; const depMap: Record<string, IDependency[]> = {};
@ -25,48 +27,53 @@ function groupDepsByPack(deps: IDependency[]): Record<string, IDependency[]> {
depMap[pkg].push(dep); depMap[pkg].push(dep);
}; };
deps.forEach(dep => { // TODO: main 这个信息到底怎么用,是不是外部包不需要使用?
// deps.forEach(dep => {
// if (dep.dependencyType === DependencyType.Internal) {
// addDep(
// `${(dep as IInternalDependency).moduleName}${`/${dep.main}` || ''}`,
// dep,
// );
// } else {
// addDep(`${(dep as IExternalDependency).package}${`/${dep.main}` || ''}`, dep);
// }
// });
deps.forEach((dep) => {
if (dep.dependencyType === DependencyType.Internal) { if (dep.dependencyType === DependencyType.Internal) {
addDep( addDep(`${(dep as IInternalDependency).moduleName}`, dep);
`${(dep as IInternalDependency).moduleName}${`/${dep.main}` || ''}`,
dep,
);
} else { } else {
addDep(`${(dep as IExternalDependency).package}${`/${dep.main}` || ''}`, dep); addDep(`${(dep as IExternalDependency).package}`, dep);
} }
}); });
return depMap; return depMap;
} }
function buildPackageImport( function buildPackageImport(pkg: string, deps: IDependency[], targetFileType: string): ICodeChunk[] {
pkg: string,
deps: IDependency[],
targetFileType: string,
): ICodeChunk[] {
const chunks: ICodeChunk[] = []; const chunks: ICodeChunk[] = [];
let defaultImport: string = ''; let defaultImport = '';
let defaultImportAs: string = ''; let defaultImportAs = '';
const imports: Record<string, string> = {}; const imports: Record<string, string> = {};
deps.forEach(dep => { deps.forEach((dep) => {
const srcName = dep.exportName; const srcName = dep.exportName;
let targetName = dep.importName || dep.exportName; let targetName = dep.importName || dep.exportName;
if (dep.subName) {
return;
}
if (dep.subName) { if (dep.subName) {
chunks.push({ if (targetName !== `${srcName}.${dep.subName}`) {
type: ChunkType.STRING, if (!isValidIdentifier(targetName)) {
fileType: targetFileType, throw new CodeGeneratorError(`Invalid Identifier [${targetName}]`);
name: COMMON_CHUNK_NAME.FileVarDefine, }
content: `const ${targetName} = ${srcName}.${dep.subName};`,
linkAfter: [ chunks.push({
COMMON_CHUNK_NAME.ExternalDepsImport, type: ChunkType.STRING,
COMMON_CHUNK_NAME.InternalDepsImport, fileType: targetFileType,
], name: COMMON_CHUNK_NAME.FileVarDefine,
}); content: `const ${targetName} = ${srcName}.${dep.subName};`,
linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport, COMMON_CHUNK_NAME.InternalDepsImport],
});
}
targetName = srcName; targetName = srcName;
} }
@ -74,18 +81,14 @@ function buildPackageImport(
if (dep.destructuring) { if (dep.destructuring) {
imports[srcName] = targetName; imports[srcName] = targetName;
} else if (defaultImport) { } else if (defaultImport) {
throw new CodeGeneratorError( throw new CodeGeneratorError(`[${pkg}] has more than one default export.`);
`[${pkg}] has more than one default export.`,
);
} else { } else {
defaultImport = srcName; defaultImport = srcName;
defaultImportAs = targetName; defaultImportAs = targetName;
} }
}); });
const items = Object.keys(imports).map(src => const items = Object.keys(imports).map((src) => (src === imports[src] ? src : `${src} as ${imports[src]}`));
src === imports[src] ? src : `${src} as ${imports[src]}`,
);
const statementL = ['import']; const statementL = ['import'];
if (defaultImport) { if (defaultImport) {
@ -125,7 +128,7 @@ function buildPackageImport(
type PluginConfig = { type PluginConfig = {
fileType: string; fileType: string;
} };
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?: PluginConfig) => { const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?: PluginConfig) => {
const cfg: PluginConfig = { const cfg: PluginConfig = {
@ -143,9 +146,9 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?: Plu
if (ir && ir.deps && ir.deps.length > 0) { if (ir && ir.deps && ir.deps.length > 0) {
const packs = groupDepsByPack(ir.deps); const packs = groupDepsByPack(ir.deps);
Object.keys(packs).forEach(pkg => { Object.keys(packs).forEach((pkg) => {
const chunks = buildPackageImport(pkg, packs[pkg], cfg.fileType); const chunks = buildPackageImport(pkg, packs[pkg], cfg.fileType);
next.chunks.push.apply(next.chunks, chunks); next.chunks.push(...chunks);
}); });
} }

View File

@ -1,28 +1,23 @@
import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator'; import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator';
import { REACT_CHUNK_NAME } from './const'; import { REACT_CHUNK_NAME } from './const';
import { import { generateFunction } from '../../../utils/jsExpression';
getFuncExprBody,
transformFuncExpr2MethodMember,
} from '../../../utils/jsExpression';
import { import {
BuilderComponentPlugin, BuilderComponentPlugin,
BuilderComponentPluginFactory, BuilderComponentPluginFactory,
ChunkType, ChunkType,
CodeGeneratorError,
FileType, FileType,
ICodeChunk, ICodeChunk,
ICodeStruct, ICodeStruct,
IContainerInfo, IContainerInfo,
IJSExpression,
} from '../../../types'; } from '../../../types';
type PluginConfig = { type PluginConfig = {
fileType: string; fileType: string;
exportNameMapping: Record<string, string>; exportNameMapping: Record<string, string>;
normalizeNameMapping: Record<string, string>; normalizeNameMapping: Record<string, string>;
} };
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => { const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
const cfg: PluginConfig = { const cfg: PluginConfig = {
@ -41,7 +36,7 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
if (ir.lifeCycles) { if (ir.lifeCycles) {
const lifeCycles = ir.lifeCycles; const lifeCycles = ir.lifeCycles;
const chunks = Object.keys(lifeCycles).map<ICodeChunk>(lifeCycleName => { const chunks = Object.keys(lifeCycles).map<ICodeChunk>((lifeCycleName) => {
const normalizeName = cfg.normalizeNameMapping[lifeCycleName] || lifeCycleName; const normalizeName = cfg.normalizeNameMapping[lifeCycleName] || lifeCycleName;
const exportName = cfg.exportNameMapping[lifeCycleName] || lifeCycleName; const exportName = cfg.exportNameMapping[lifeCycleName] || lifeCycleName;
if (normalizeName === 'constructor') { if (normalizeName === 'constructor') {
@ -49,9 +44,7 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
type: ChunkType.STRING, type: ChunkType.STRING,
fileType: cfg.fileType, fileType: cfg.fileType,
name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent, name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent,
content: getFuncExprBody( content: generateFunction(lifeCycles[lifeCycleName], { isBlock: true }),
(lifeCycles[lifeCycleName] as IJSExpression).value,
),
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorStart]], linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorStart]],
}; };
} }
@ -60,9 +53,7 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
type: ChunkType.STRING, type: ChunkType.STRING,
fileType: cfg.fileType, fileType: cfg.fileType,
name: REACT_CHUNK_NAME.ClassRenderPre, name: REACT_CHUNK_NAME.ClassRenderPre,
content: getFuncExprBody( content: generateFunction(lifeCycles[lifeCycleName], { isBlock: true }),
(lifeCycles[lifeCycleName] as IJSExpression).value,
),
linkAfter: [REACT_CHUNK_NAME.ClassRenderStart], linkAfter: [REACT_CHUNK_NAME.ClassRenderStart],
}; };
} }
@ -71,15 +62,12 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
type: ChunkType.STRING, type: ChunkType.STRING,
fileType: cfg.fileType, fileType: cfg.fileType,
name: CLASS_DEFINE_CHUNK_NAME.InsMethod, name: CLASS_DEFINE_CHUNK_NAME.InsMethod,
content: transformFuncExpr2MethodMember( content: generateFunction(lifeCycles[lifeCycleName], { name: exportName, isMember: true }),
exportName,
(lifeCycles[lifeCycleName] as IJSExpression).value,
),
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]], linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]],
}; };
}); });
next.chunks.push.apply(next.chunks, chunks); next.chunks.push(...chunks);
} }
return next; return next;

View File

@ -1,6 +1,6 @@
import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator'; import { CLASS_DEFINE_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator';
import { transformFuncExpr2MethodMember } from '../../../utils/jsExpression'; import { generateFunction } from '../../../utils/jsExpression';
import { import {
BuilderComponentPlugin, BuilderComponentPlugin,
@ -10,12 +10,11 @@ import {
ICodeChunk, ICodeChunk,
ICodeStruct, ICodeStruct,
IContainerInfo, IContainerInfo,
IJSExpression,
} from '../../../types'; } from '../../../types';
type PluginConfig = { type PluginConfig = {
fileType: string; fileType: string;
} };
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => { const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
const cfg: PluginConfig = { const cfg: PluginConfig = {
@ -32,18 +31,15 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
if (ir.methods) { if (ir.methods) {
const methods = ir.methods; const methods = ir.methods;
const chunks = Object.keys(methods).map<ICodeChunk>(methodName => ({ const chunks = Object.keys(methods).map<ICodeChunk>((methodName) => ({
type: ChunkType.STRING, type: ChunkType.STRING,
fileType: cfg.fileType, fileType: cfg.fileType,
name: CLASS_DEFINE_CHUNK_NAME.InsMethod, name: CLASS_DEFINE_CHUNK_NAME.InsMethod,
content: transformFuncExpr2MethodMember( content: generateFunction(methods[methodName], { name: methodName, isMember: true }),
methodName,
(methods[methodName] as IJSExpression).value,
),
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]], linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]],
})); }));
next.chunks.push.apply(next.chunks, chunks); next.chunks.push(...chunks);
} }
return next; return next;

View File

@ -29,14 +29,11 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
const ir = next.ir as IContainerInfo; const ir = next.ir as IContainerInfo;
if (ir.dataSource) { if (ir.dataSource) {
const { dataSource } = ir; const { dataSource } = ir;
const { const { list, ...rest } = dataSource;
list,
...rest
} = dataSource;
let attrs: string[] = []; let attrs: string[] = [];
const extConfigs = Object.keys(rest).map(extConfigName => { const extConfigs = Object.keys(rest).map((extConfigName) => {
const value = (rest as Record<string, CompositeValue>)[extConfigName]; const value = (rest as Record<string, CompositeValue>)[extConfigName];
const [isString, valueStr] = generateCompositeType(value); const [isString, valueStr] = generateCompositeType(value);
return `${extConfigName}: ${isString ? `'${valueStr}'` : valueStr}`; return `${extConfigName}: ${isString ? `'${valueStr}'` : valueStr}`;
@ -44,9 +41,13 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
attrs = [...attrs, ...extConfigs]; attrs = [...attrs, ...extConfigs];
const listProp = handleStringValueDefault(generateCompositeType(list as unknown as CompositeValue, { const listProp = handleStringValueDefault(
expression: packJsExpression, generateCompositeType((list as unknown) as CompositeValue, {
})); handlers: {
expression: packJsExpression,
},
}),
);
attrs.push(`list: ${listProp}`); attrs.push(`list: ${listProp}`);

View File

@ -5,23 +5,26 @@ import {
ICodeStruct, ICodeStruct,
IContainerInfo, IContainerInfo,
IComponentNodeItem, IComponentNodeItem,
INodeGeneratorContext,
CodePiece, CodePiece,
PIECE_TYPE, PIECE_TYPE,
} from '../../../types'; } from '../../../types';
import { COMMON_CHUNK_NAME, DEFAULT_LINK_AFTER } from '../../../const/generator'; import { COMMON_CHUNK_NAME } from '../../../const/generator';
import { createNodeGenerator, generateString } from '../../../utils/nodeToJSX'; import { createNodeGenerator, generateString } from '../../../utils/nodeToJSX';
import { generateExpression } from '../../../utils/jsExpression'; import { generateExpression } from '../../../utils/jsExpression';
import { generateCompositeType, handleStringValueDefault } from '../../../utils/compositeType'; import { generateCompositeType, handleStringValueDefault } from '../../../utils/compositeType';
const generateGlobalProps = (nodeItem: IComponentNodeItem): CodePiece[] => { const generateGlobalProps = (ctx: INodeGeneratorContext, nodeItem: IComponentNodeItem): CodePiece[] => {
return [{ return [
value: `{...globalProps.${nodeItem.componentName}}`, {
type: PIECE_TYPE.ATTR, value: `{...globalProps.${nodeItem.componentName}}`,
}]; type: PIECE_TYPE.ATTR,
},
];
}; };
const generateCtrlLine = (nodeItem: IComponentNodeItem): CodePiece[] => { const generateCtrlLine = (ctx: INodeGeneratorContext, nodeItem: IComponentNodeItem): CodePiece[] => {
const pieces: CodePiece[] = []; const pieces: CodePiece[] = [];
if (nodeItem.loop && nodeItem.loopArgs) { if (nodeItem.loop && nodeItem.loopArgs) {
@ -49,13 +52,13 @@ const generateCtrlLine = (nodeItem: IComponentNodeItem): CodePiece[] => {
}; };
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => { const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
const generator = createNodeGenerator({ const generator = createNodeGenerator(
string: generateString, {
expression: (input) => [generateExpression(input)], string: generateString,
}, [ expression: (input) => [generateExpression(input)],
generateGlobalProps, },
generateCtrlLine, [generateGlobalProps, generateCtrlLine],
]); );
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => { const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
const next: ICodeStruct = { const next: ICodeStruct = {

View File

@ -26,10 +26,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
content: ` content: `
const constantConfig = ${constantStr}; const constantConfig = ${constantStr};
`, `,
linkAfter: [ linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport, COMMON_CHUNK_NAME.InternalDepsImport],
COMMON_CHUNK_NAME.ExternalDepsImport,
COMMON_CHUNK_NAME.InternalDepsImport,
],
}); });
next.chunks.push({ next.chunks.push({

View File

@ -59,6 +59,7 @@ export default function createIceJsProjectBuilder(): IProjectBuilder {
Component: 'div', Component: 'div',
Page: 'div', Page: 'div',
Block: 'div', Block: 'div',
// Box: 'div',
}, },
}), }),
css(), css(),
@ -72,6 +73,6 @@ export default function createIceJsProjectBuilder(): IProjectBuilder {
htmlEntry: [icejs.plugins.entryHtml()], htmlEntry: [icejs.plugins.entryHtml()],
packageJSON: [icejs.plugins.packageJSON()], packageJSON: [icejs.plugins.packageJSON()],
}, },
postProcessors: [prettier()], postProcessors: [prettier()], // prettier()
}); });
} }

View File

@ -53,17 +53,12 @@ export interface ICodeStruct extends IBaseCodeStruct {
chunks: ICodeChunk[]; chunks: ICodeChunk[];
} }
export type BuilderComponentPlugin = ( export type BuilderComponentPlugin = (initStruct: ICodeStruct) => Promise<ICodeStruct>;
initStruct: ICodeStruct,
) => Promise<ICodeStruct>;
export type BuilderComponentPluginFactory<T> = (config?: T) => BuilderComponentPlugin; export type BuilderComponentPluginFactory<T> = (config?: T) => BuilderComponentPlugin;
export interface IChunkBuilder { export interface IChunkBuilder {
run( run(ir: any, initialStructure?: ICodeStruct): Promise<{ chunks: ICodeChunk[][] }>;
ir: any,
initialStructure?: ICodeStruct,
): Promise<{ chunks: ICodeChunk[][] }>;
getPlugins(): BuilderComponentPlugin[]; getPlugins(): BuilderComponentPlugin[];
addPlugin(plugin: BuilderComponentPlugin): void; addPlugin(plugin: BuilderComponentPlugin): void;
} }
@ -80,10 +75,7 @@ export interface ICompiledModule {
export interface IModuleBuilder { export interface IModuleBuilder {
generateModule(input: unknown): Promise<ICompiledModule>; generateModule(input: unknown): Promise<ICompiledModule>;
generateModuleCode(schema: IBasicSchema | string): Promise<IResultDir>; generateModuleCode(schema: IBasicSchema | string): Promise<IResultDir>;
linkCodeChunks( linkCodeChunks(chunks: Record<string, ICodeChunk[]>, fileName: string): IResultFile[];
chunks: Record<string, ICodeChunk[]>,
fileName: string,
): IResultFile[];
addPlugin(plugin: BuilderComponentPlugin): void; addPlugin(plugin: BuilderComponentPlugin): void;
} }
@ -154,7 +146,7 @@ export enum PIECE_TYPE {
ATTR = 'NodeCodePieceAttr', ATTR = 'NodeCodePieceAttr',
CHILDREN = 'NodeCodePieceChildren', CHILDREN = 'NodeCodePieceChildren',
AFTER = 'NodeCodePieceAfter', AFTER = 'NodeCodePieceAfter',
}; }
export interface CodePiece { export interface CodePiece {
value: string; value: string;
@ -168,14 +160,35 @@ export interface HandlerSet<T> {
common?: (input: unknown) => T[]; common?: (input: unknown) => T[];
} }
export type ExtGeneratorPlugin = (nodeItem: IComponentNodeItem) => CodePiece[]; export type ExtGeneratorPlugin = (ctx: INodeGeneratorContext, nodeItem: IComponentNodeItem) => CodePiece[];
export interface INodeGeneratorConfig { export interface INodeGeneratorConfig {
nodeTypeMapping?: Record<string, string>; nodeTypeMapping?: Record<string, string>;
} }
export type NodeGenerator = (nodeItem: IComponentNodeItem) => string;
export interface INodeGeneratorContext {
generator: NodeGenerator;
}
// export interface InteratorScope { // export interface InteratorScope {
// [$item: string]: string; // $item 默认取值 "item" // [$item: string]: string; // $item 默认取值 "item"
// [$index: string]: string | number; // $index 默认取值 "index" // [$index: string]: string | number; // $index 默认取值 "index"
// __proto__: BlockInstance; // __proto__: BlockInstance;
// } // }
export type CompositeValueCustomHandler = (data: unknown) => string;
export interface CompositeValueCustomHandlerSet {
boolean?: CompositeValueCustomHandler;
number?: CompositeValueCustomHandler;
string?: CompositeValueCustomHandler;
array?: CompositeValueCustomHandler;
object?: CompositeValueCustomHandler;
expression?: CompositeValueCustomHandler;
}
export interface CompositeValueGeneratorOptions {
handlers?: CompositeValueCustomHandlerSet;
nodeGenerator?: NodeGenerator;
}

View File

@ -13,18 +13,37 @@ export interface IJSExpression {
[extConfigName: string]: any; [extConfigName: string]: any;
} }
/**
* -
*
* @export
* @interface IJSFunction
*/
export interface IJSFunction {
type: 'JSFunction';
value: string;
[extConfigName: string]: any;
}
/**
* -
*
* @export
* @interface IJSSlot
*/
export interface IJSSlot {
type: 'JSSlot';
value: IComponentNodeItem[];
params?: string[];
[extConfigName: string]: any;
}
// JSON 基本类型 // JSON 基本类型
export interface IJSONObject { export interface IJSONObject {
[key: string]: JSONValue; [key: string]: JSONValue;
} }
export type JSONValue = export type JSONValue = boolean | string | number | null | JSONArray | IJSONObject;
| boolean
| string
| number
| null
| JSONArray
| IJSONObject;
export type JSONArray = JSONValue[]; export type JSONArray = JSONValue[];
export type CompositeArray = CompositeValue[]; export type CompositeArray = CompositeValue[];
@ -33,11 +52,7 @@ export interface ICompositeObject {
} }
// 复合类型 // 复合类型
export type CompositeValue = export type CompositeValue = JSONValue | IJSExpression | IJSFunction | IJSSlot | CompositeArray | ICompositeObject;
| JSONValue
| IJSExpression
| CompositeArray
| ICompositeObject;
/** /**
* - * -
@ -136,8 +151,8 @@ export interface IContainerNodeItem extends IComponentNodeItem {
* componentWillUnmount() * componentWillUnmount()
* componentDidCatch(error, info) * componentDidCatch(error, info)
*/ */
lifeCycles?: Record<string, IJSExpression>; // 生命周期Hook方法 lifeCycles?: Record<string, IJSExpression | IJSFunction>; // 生命周期Hook方法
methods?: Record<string, IJSExpression>; // 自定义方法设置 methods?: Record<string, IJSExpression | IJSFunction>; // 自定义方法设置
dataSource?: { dataSource?: {
list: IDataSourceConfig[]; list: IDataSourceConfig[];
}; // 异步数据源配置 }; // 异步数据源配置
@ -154,9 +169,9 @@ export interface IDataSourceConfig {
id: string; // 数据请求ID标识 id: string; // 数据请求ID标识
isInit: boolean; // 是否为初始数据 支持表达式 值为true时将在组件初始化渲染时自动发送当前数据请求 isInit: boolean; // 是否为初始数据 支持表达式 值为true时将在组件初始化渲染时自动发送当前数据请求
type: string; // 数据请求类型 'fetch' | 'mtop' | 'jsonp' | 'custom' type: string; // 数据请求类型 'fetch' | 'mtop' | 'jsonp' | 'custom'
requestHandler?: IJSExpression; // 自定义扩展的外部请求处理器 仅type='custom'时生效 requestHandler?: IJSExpression | IJSFunction; // 自定义扩展的外部请求处理器 仅type='custom'时生效
options?: IFetchOptions; // 请求参数配置 每种请求类型对应不同参数 options?: IFetchOptions; // 请求参数配置 每种请求类型对应不同参数
dataHandler?: IJSExpression; // 数据结果处理函数,形如:(data, err) => Object dataHandler?: IJSExpression | IJSFunction; // 数据结果处理函数,形如:(data, err) => Object
} }
/** /**

View File

@ -1,38 +1,40 @@
import { CompositeArray, CompositeValue, ICompositeObject } from '../types'; import {
import { generateExpression, isJsExpression } from './jsExpression'; CompositeArray,
CompositeValue,
ICompositeObject,
CompositeValueGeneratorOptions,
CodeGeneratorError,
} from '../types';
import { generateExpression, generateFunction, isJsExpression, isJsFunction } from './jsExpression';
import { isJsSlot, generateJsSlot } from './jsSlot';
type CustomHandler = (data: unknown) => string; function generateArray(value: CompositeArray, options: CompositeValueGeneratorOptions = {}): string {
interface CustomHandlerSet { const body = value.map((v) => generateUnknownType(v, options)).join(',');
boolean?: CustomHandler;
number?: CustomHandler;
string?: CustomHandler;
array?: CustomHandler;
object?: CustomHandler;
expression?: CustomHandler;
}
function generateArray(
value: CompositeArray,
handlers: CustomHandlerSet = {},
): string {
const body = value.map(v => generateUnknownType(v, handlers)).join(',');
return `[${body}]`; return `[${body}]`;
} }
function generateObject( function generateObject(value: ICompositeObject, options: CompositeValueGeneratorOptions = {}): string {
value: ICompositeObject,
handlers: CustomHandlerSet = {},
): string {
if (isJsExpression(value)) { if (isJsExpression(value)) {
if (handlers.expression) { if (options.handlers && options.handlers.expression) {
return handlers.expression(value); return options.handlers.expression(value);
} }
return generateExpression(value); return generateExpression(value);
} }
if (isJsFunction(value)) {
return generateFunction(value, { isArrow: true });
}
if (isJsSlot(value)) {
if (options.nodeGenerator) {
return generateJsSlot(value, options.nodeGenerator);
}
throw new CodeGeneratorError("Can't find Node Generator");
}
const body = Object.keys(value) const body = Object.keys(value)
.map(key => { .map((key) => {
const v = generateUnknownType(value[key], handlers); const v = generateUnknownType(value[key], options);
return `${key}: ${v}`; return `${key}: ${v}`;
}) })
.join(',\n'); .join(',\n');
@ -40,38 +42,35 @@ function generateObject(
return `{${body}}`; return `{${body}}`;
} }
export function generateUnknownType( export function generateUnknownType(value: CompositeValue, options: CompositeValueGeneratorOptions = {}): string {
value: CompositeValue,
handlers: CustomHandlerSet = {},
): string {
if (Array.isArray(value)) { if (Array.isArray(value)) {
if (handlers.array) { if (options.handlers && options.handlers.array) {
return handlers.array(value); return options.handlers.array(value);
} }
return generateArray(value as CompositeArray, handlers); return generateArray(value as CompositeArray, options);
} else if (typeof value === 'object') { } else if (typeof value === 'object') {
if (handlers.object) { if (options.handlers && options.handlers.object) {
return handlers.object(value); return options.handlers.object(value);
} }
return generateObject(value as ICompositeObject, handlers); return generateObject(value as ICompositeObject, options);
} else if (typeof value === 'string') { } else if (typeof value === 'string') {
if (handlers.string) { if (options.handlers && options.handlers.string) {
return handlers.string(value); return options.handlers.string(value);
} }
return `'${value}'`; return `'${value}'`;
} else if (typeof value === 'number' && handlers.number) { } else if (typeof value === 'number' && options.handlers && options.handlers.number) {
return handlers.number(value); return options.handlers.number(value);
} else if (typeof value === 'boolean' && handlers.boolean) { } else if (typeof value === 'boolean' && options.handlers && options.handlers.boolean) {
return handlers.boolean(value); return options.handlers.boolean(value);
} }
return `${value}`; return `${value}`;
} }
export function generateCompositeType( export function generateCompositeType(
value: CompositeValue, value: CompositeValue,
handlers: CustomHandlerSet = {}, options: CompositeValueGeneratorOptions = {},
): [boolean, string] { ): [boolean, string] {
const result = generateUnknownType(value, handlers); const result = generateUnknownType(value, options);
if (result.substr(0, 1) === "'" && result.substr(-1, 1) === "'") { if (result.substr(0, 1) === "'" && result.substr(-1, 1) === "'") {
return [true, result.substring(1, result.length - 1)]; return [true, result.substring(1, result.length - 1)];

View File

@ -1,39 +1,6 @@
import traverse from '@babel/traverse'; import { CodeGeneratorError, IJSExpression, IJSFunction } from '../types';
import * as parser from '@babel/parser';
import { CodeGeneratorError, IJSExpression } from '../types';
let count = 0;
function test(functionBody: string) {
console.log(functionBody);
console.log('---->');
try {
const parseResult = parser.parse(functionBody);
// console.log(JSON.stringify(parseResult));
traverse(parseResult, {
enter(path) {
console.log('path: ', JSON.stringify(path));
}
});
if (count === 0) {
count++;
test('this.aaa && this.bbb');
}
} catch (error) {
// console.log('Error');
console.log(error.message);
}
console.log('=====================');
}
export function transformFuncExpr2MethodMember(
methodName: string,
functionBody: string,
): string {
// test(functionBody);
export function transformFuncExpr2MethodMember(methodName: string, functionBody: string): string {
const args = getFuncExprArguments(functionBody); const args = getFuncExprArguments(functionBody);
const body = getFuncExprBody(functionBody); const body = getFuncExprBody(functionBody);
@ -66,20 +33,60 @@ export function getFuncExprBody(functionBody: string) {
return body; return body;
} }
export function generateExpression(value: any): string { export function getArrowFunction(functionBody: string) {
if (value && (value as IJSExpression).type === 'JSExpression') { const args = getFuncExprArguments(functionBody);
// test((value as IJSExpression).value); const body = getFuncExprBody(functionBody);
return `(${args}) => { ${body} }`;
}
export function isJsExpression(value: unknown): boolean {
return value && typeof value === 'object' && (value as IJSExpression).type === 'JSExpression';
}
export function isJsFunction(value: unknown): boolean {
return value && typeof value === 'object' && (value as IJSFunction).type === 'JSFunction';
}
export function isJsCode(value: unknown): boolean {
return isJsExpression(value) || isJsFunction(value);
}
export function generateExpression(value: any): string {
if (isJsExpression(value)) {
return (value as IJSExpression).value || 'null'; return (value as IJSExpression).value || 'null';
} }
throw new CodeGeneratorError('Not a JSExpression'); throw new CodeGeneratorError('Not a JSExpression');
} }
export function isJsExpression(value: any): boolean { export function generateFunction(
return ( value: any,
value && config: {
typeof value === 'object' && name?: string;
(value as IJSExpression).type === 'JSExpression' isMember?: boolean;
); isBlock?: boolean;
isArrow?: boolean;
} = {
name: undefined,
isMember: false,
isBlock: false,
isArrow: false,
},
) {
if (isJsCode(value)) {
const functionCfg = value as IJSFunction;
if (config.isMember) {
return transformFuncExpr2MethodMember(config.name || '', functionCfg.value);
}
if (config.isBlock) {
return getFuncExprBody(functionCfg.value);
}
if (config.isArrow) {
return getArrowFunction(functionCfg.value);
}
return functionCfg.value;
}
throw new CodeGeneratorError('Not a JSFunction or JSExpression');
} }

View File

@ -0,0 +1,21 @@
import { CodeGeneratorError, NodeGenerator, IJSSlot } from '../types';
export function isJsSlot(value: unknown): boolean {
return value && typeof value === 'object' && (value as IJSSlot).type === 'JSSlot';
}
export function generateJsSlot(value: any, generator: NodeGenerator): string {
if (isJsSlot(value)) {
const slotCfg = value as IJSSlot;
if (!slotCfg.value) {
return 'null';
}
const results = slotCfg.value.map((n) => generator(n));
if (results.length === 1) {
return results[0];
}
return `[${results.join(',')}]`;
}
throw new CodeGeneratorError('Not a JSSlot');
}

View File

@ -9,9 +9,11 @@ import {
HandlerSet, HandlerSet,
ExtGeneratorPlugin, ExtGeneratorPlugin,
INodeGeneratorConfig, INodeGeneratorConfig,
INodeGeneratorContext,
NodeGenerator,
} from '../types'; } from '../types';
import { generateCompositeType } from './compositeType'; import { generateCompositeType } from './compositeType';
import { generateExpression } from './jsExpression'; import { generateExpression, isJsExpression } from './jsExpression';
// tslint:disable-next-line: no-empty // tslint:disable-next-line: no-empty
const noop = () => []; const noop = () => [];
@ -20,11 +22,11 @@ const handleChildrenDefaultOptions = {
rerun: false, rerun: false,
}; };
export function handleChildren<T>( export function handleSubNodes<T>(
children: ChildNodeType, children: ChildNodeType,
handlers: HandlerSet<T>, handlers: HandlerSet<T>,
options?: { options?: {
rerun?: boolean, rerun?: boolean;
}, },
): T[] { ): T[] {
const opt = { const opt = {
@ -34,43 +36,78 @@ export function handleChildren<T>(
if (Array.isArray(children)) { if (Array.isArray(children)) {
const list: ChildNodeItem[] = children as ChildNodeItem[]; const list: ChildNodeItem[] = children as ChildNodeItem[];
return list return list.map((child) => handleSubNodes(child, handlers, opt)).reduce((p, c) => p.concat(c), []);
.map(child => handleChildren(child, handlers, opt))
.reduce((p, c) => p.concat(c), []);
} else if (typeof children === 'string') { } else if (typeof children === 'string') {
const handler = handlers.string || handlers.common || noop; const handler = handlers.string || handlers.common || noop;
return handler(children as string); return handler(children as string);
} else if ((children as IJSExpression).type === 'JSExpression') { } else if (isJsExpression(children)) {
const handler = handlers.expression || handlers.common || noop; const handler = handlers.expression || handlers.common || noop;
return handler(children as IJSExpression); return handler(children as IJSExpression);
} else { } else {
const handler = handlers.node || handlers.common || noop; const handler = handlers.node || handlers.common || noop;
let curRes = handler(children as IComponentNodeItem); let curRes = handler(children as IComponentNodeItem);
if (opt.rerun && children.children) { if (opt.rerun && children.children) {
const childRes = handleChildren(children.children, handlers, opt); const childRes = handleSubNodes(children.children, handlers, opt);
curRes = curRes.concat(childRes || []); curRes = curRes.concat(childRes || []);
} }
return curRes; return curRes;
} }
} }
export function generateAttr(attrName: string, attrValue: any): CodePiece[] { export function handleChildren<T>(
ctx: INodeGeneratorContext,
children: ChildNodeType,
handlers: HandlerSet<T>,
options?: {
rerun?: boolean;
},
): T[] {
const opt = {
...handleChildrenDefaultOptions,
...(options || {}),
};
if (Array.isArray(children)) {
const list: ChildNodeItem[] = children as ChildNodeItem[];
return list.map((child) => handleChildren(ctx, child, handlers, opt)).reduce((p, c) => p.concat(c), []);
} else if (typeof children === 'string') {
const handler = handlers.string || handlers.common || noop;
return handler(children as string);
} else if (isJsExpression(children)) {
const handler = handlers.expression || handlers.common || noop;
return handler(children as IJSExpression);
} else {
const handler = handlers.node || handlers.common || noop;
let curRes = handler(children as IComponentNodeItem);
if (opt.rerun && children.children) {
const childRes = handleChildren(ctx, children.children, handlers, opt);
curRes = curRes.concat(childRes || []);
}
return curRes;
}
}
export function generateAttr(ctx: INodeGeneratorContext, attrName: string, attrValue: any): CodePiece[] {
if (attrName === 'initValue') { if (attrName === 'initValue') {
return []; return [];
} }
const [isString, valueStr] = generateCompositeType(attrValue); const [isString, valueStr] = generateCompositeType(attrValue, {
return [{ nodeGenerator: ctx.generator,
value: `${attrName}=${isString ? `"${valueStr}"` : `{${valueStr}}`}`, });
type: PIECE_TYPE.ATTR, return [
}]; {
value: `${attrName}=${isString ? `"${valueStr}"` : `{${valueStr}}`}`,
type: PIECE_TYPE.ATTR,
},
];
} }
export function generateAttrs(nodeItem: IComponentNodeItem): CodePiece[] { export function generateAttrs(ctx: INodeGeneratorContext, nodeItem: IComponentNodeItem): CodePiece[] {
const { props } = nodeItem; const { props } = nodeItem;
let pieces: CodePiece[] = []; let pieces: CodePiece[] = [];
Object.keys(props).forEach((propName: string) => Object.keys(props).forEach(
pieces = pieces.concat(generateAttr(propName, props[propName])), (propName: string) => (pieces = pieces.concat(generateAttr(ctx, propName, props[propName]))),
); );
return pieces; return pieces;
@ -83,7 +120,11 @@ function mapNodeName(src: string, mapping: Record<string, string>): string {
return src; return src;
} }
export function generateBasicNode(nodeItem: IComponentNodeItem, mapping: Record<string, string>): CodePiece[] { export function generateBasicNode(
ctx: INodeGeneratorContext,
nodeItem: IComponentNodeItem,
mapping: Record<string, string>,
): CodePiece[] {
const pieces: CodePiece[] = []; const pieces: CodePiece[] = [];
pieces.push({ pieces.push({
value: mapNodeName(nodeItem.componentName, mapping), value: mapNodeName(nodeItem.componentName, mapping),
@ -93,13 +134,25 @@ export function generateBasicNode(nodeItem: IComponentNodeItem, mapping: Record<
return pieces; return pieces;
} }
export function generateReactCtrlLine(nodeItem: IComponentNodeItem): CodePiece[] { // TODO: 生成文档
// 为包裹的代码片段生成子上下文,集成父级上下文,并传入子级上下文新增内容。(如果存在多级上下文怎么处理?)
// 创建新的上下文,并从作用域中取对应同名变量塞到作用域里面?
// export function createSubContext() {}
/**
* JSX React loop condition
*
* @export
* @param {IComponentNodeItem} nodeItem UI
* @returns {CodePiece[]}
*/
export function generateReactCtrlLine(ctx: INodeGeneratorContext, nodeItem: IComponentNodeItem): CodePiece[] {
const pieces: CodePiece[] = []; const pieces: CodePiece[] = [];
if (nodeItem.loop && nodeItem.loopArgs) { if (nodeItem.loop && nodeItem.loopArgs) {
let loopDataExp; let loopDataExp;
if ((nodeItem.loop as IJSExpression).type === 'JSExpression') { if (isJsExpression(nodeItem.loop)) {
loopDataExp = `(${(nodeItem.loop as IJSExpression).value})`; loopDataExp = `(${generateExpression(nodeItem.loop)})`;
} else { } else {
loopDataExp = JSON.stringify(nodeItem.loop); loopDataExp = JSON.stringify(nodeItem.loop);
} }
@ -114,7 +167,9 @@ export function generateReactCtrlLine(nodeItem: IComponentNodeItem): CodePiece[]
} }
if (nodeItem.condition) { if (nodeItem.condition) {
const [isString, value] = generateCompositeType(nodeItem.condition); const [isString, value] = generateCompositeType(nodeItem.condition, {
nodeGenerator: ctx.generator,
});
pieces.unshift({ pieces.unshift({
value: `(${isString ? `'${value}'` : value}) && (`, value: `(${isString ? `'${value}'` : value}) && (`,
@ -141,29 +196,29 @@ export function generateReactCtrlLine(nodeItem: IComponentNodeItem): CodePiece[]
} }
export function linkPieces(pieces: CodePiece[]): string { export function linkPieces(pieces: CodePiece[]): string {
if (pieces.filter(p => p.type === PIECE_TYPE.TAG).length !== 1) { if (pieces.filter((p) => p.type === PIECE_TYPE.TAG).length !== 1) {
throw new CodeGeneratorError('One node only need one tag define'); throw new CodeGeneratorError('One node only need one tag define');
} }
const tagName = pieces.filter(p => p.type === PIECE_TYPE.TAG)[0].value; const tagName = pieces.filter((p) => p.type === PIECE_TYPE.TAG)[0].value;
const beforeParts = pieces const beforeParts = pieces
.filter(p => p.type === PIECE_TYPE.BEFORE) .filter((p) => p.type === PIECE_TYPE.BEFORE)
.map(p => p.value) .map((p) => p.value)
.join(''); .join('');
const afterParts = pieces const afterParts = pieces
.filter(p => p.type === PIECE_TYPE.AFTER) .filter((p) => p.type === PIECE_TYPE.AFTER)
.map(p => p.value) .map((p) => p.value)
.join(''); .join('');
const childrenParts = pieces const childrenParts = pieces
.filter(p => p.type === PIECE_TYPE.CHILDREN) .filter((p) => p.type === PIECE_TYPE.CHILDREN)
.map(p => p.value) .map((p) => p.value)
.join(''); .join('');
let attrsParts = pieces let attrsParts = pieces
.filter(p => p.type === PIECE_TYPE.ATTR) .filter((p) => p.type === PIECE_TYPE.ATTR)
.map(p => p.value) .map((p) => p.value)
.join(' '); .join(' ');
attrsParts = !!attrsParts ? ` ${attrsParts}` : ''; attrsParts = !!attrsParts ? ` ${attrsParts}` : '';
@ -179,7 +234,7 @@ export function createNodeGenerator(
handlers: HandlerSet<string>, handlers: HandlerSet<string>,
plugins: ExtGeneratorPlugin[], plugins: ExtGeneratorPlugin[],
cfg?: INodeGeneratorConfig, cfg?: INodeGeneratorConfig,
) { ): NodeGenerator {
let nodeTypeMapping: Record<string, string> = {}; let nodeTypeMapping: Record<string, string> = {};
if (cfg && cfg.nodeTypeMapping) { if (cfg && cfg.nodeTypeMapping) {
nodeTypeMapping = cfg.nodeTypeMapping; nodeTypeMapping = cfg.nodeTypeMapping;
@ -187,17 +242,22 @@ export function createNodeGenerator(
const generateNode = (nodeItem: IComponentNodeItem): string => { const generateNode = (nodeItem: IComponentNodeItem): string => {
let pieces: CodePiece[] = []; let pieces: CodePiece[] = [];
const ctx: INodeGeneratorContext = {
generator: generateNode,
};
plugins.forEach(p => { plugins.forEach((p) => {
pieces = pieces.concat(p(nodeItem)); pieces = pieces.concat(p(ctx, nodeItem));
}); });
pieces = pieces.concat(generateBasicNode(nodeItem, nodeTypeMapping)); pieces = pieces.concat(generateBasicNode(ctx, nodeItem, nodeTypeMapping));
pieces = pieces.concat(generateAttrs(nodeItem)); pieces = pieces.concat(generateAttrs(ctx, nodeItem));
if (nodeItem.children && (nodeItem.children as unknown[]).length > 0) { if (nodeItem.children && (nodeItem.children as unknown[]).length > 0) {
pieces = pieces.concat(handleChildren<string>(nodeItem.children, handlers).map(l => ({ pieces = pieces.concat(
type: PIECE_TYPE.CHILDREN, handleChildren<string>(ctx, nodeItem.children, handlers).map((l) => ({
value: l, type: PIECE_TYPE.CHILDREN,
}))); value: l,
})),
);
} }
return linkPieces(pieces); return linkPieces(pieces);
@ -210,11 +270,13 @@ export function createNodeGenerator(
export const generateString = (input: string) => [input]; export const generateString = (input: string) => [input];
export function createReactNodeGenerator(cfg?: INodeGeneratorConfig) { export function createReactNodeGenerator(cfg?: INodeGeneratorConfig): NodeGenerator {
return createNodeGenerator({ return createNodeGenerator(
string: generateString, {
expression: (input) => [generateExpression(input)], string: generateString,
}, [ expression: (input) => [generateExpression(input)],
generateReactCtrlLine, },
], cfg); [generateReactCtrlLine],
cfg,
);
} }

View File

@ -0,0 +1,3 @@
export const isValidIdentifier = (name: string) => {
return /^[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*$/.test(name);
};

View File

@ -9,8 +9,8 @@
{ {
"title": "fusion组件库", "title": "fusion组件库",
"package": "@alifd/next", "package": "@alifd/next",
"version": "1.19.18", "version": "1.20.0",
"urls": ["https://unpkg.antfin-inc.com/@alife/next@1.19.18/dist/next.js", "https://unpkg.antfin-inc.com/@alife/next@1.19.18/dist/next.css"], "urls": ["https://unpkg.antfin-inc.com/@alifd/next@1.20.0/dist/next.js", "https://unpkg.antfin-inc.com/@alifd/next@1.20.0/dist/next.css"],
"library": "Next" "library": "Next"
}, },
{ {
@ -66,6 +66,262 @@
} }
} }
}, },
{
"componentName": "Drawer",
"title": "抽屉",
"docUrl": "",
"screenshot": "",
"npm": {
"package": "@alifd/next",
"version": "1.19.18",
"exportName": "Drawer",
"main": "src/index.js",
"destructuring": true,
"subName": ""
},
"props": [
{
"name": "prefix",
"propType": "string",
"defaultValue": "next-"
},
{
"name": "style",
"propType": "object"
},
{
"name": "pure",
"propType": "bool"
},
{
"name": "rtl",
"propType": "bool"
},
{
"name": "trigger",
"propType": {
"type": "instanceOf",
"value": "element"
},
"defaultValue": null
},
{
"name": "triggerType",
"propType": {
"type": "oneOfType",
"value": [
"string",
{
"type": "instanceOf",
"value": "array"
}
]
},
"defaultValue": "click"
},
{
"name": "width",
"propType": {
"type": "oneOfType",
"value": [
"number",
"string"
]
},
"description": "宽度,仅在 placement是 left right 的时候生效"
},
{
"name": "height",
"propType": {
"type": "oneOfType",
"value": [
"number",
"string"
]
},
"description": "高度,仅在 placement是 top bottom 的时候生效"
},
{
"name": "closeable",
"propType": {
"type": "oneOfType",
"value": [
"string",
"bool"
]
},
"description": "控制对话框关闭的方式,值可以为字符串或者布尔值,其中字符串是由以下值组成:\n**close** 表示点击关闭按钮可以关闭对话框\n**mask** 表示点击遮罩区域可以关闭对话框\n**esc** 表示按下 esc 键可以关闭对话框\n如 'close' 或 'close,esc,mask'\n如果设置为 true则以上关闭方式全部生效\n如果设置为 false则以上关闭方式全部失效",
"defaultValue": true
},
{
"name": "onClose",
"propType": "func",
"description": "对话框关闭时触发的回调函数\n@param {String} trigger 关闭触发行为的描述字符串\n@param {Object} event 关闭时事件对象"
},
{
"name": "placement",
"propType": {
"type": "oneOf",
"value": [
"top",
"right",
"bottom",
"left"
]
},
"description": "位于页面的位置",
"defaultValue": "right"
},
{
"name": "title",
"propType": {
"type": "instanceOf",
"value": "node"
},
"description": "标题"
},
{
"name": "headerStyle",
"propType": "object",
"description": "header上的样式"
},
{
"name": "bodyStyle",
"propType": "object",
"description": "body上的样式"
},
{
"name": "visible",
"propType": "bool",
"description": "是否显示"
},
{
"name": "hasMask",
"propType": "bool",
"description": "是否显示遮罩",
"defaultValue": true
},
{
"name": "onVisibleChange",
"propType": "func"
},
{
"name": "animation",
"propType": {
"type": "oneOfType",
"value": [
"object",
"bool"
]
},
"description": "显示隐藏时动画的播放方式\n@property {String} in 进场动画\n@property {String} out 出场动画"
},
{
"name": "locale",
"propType": "object"
},
{
"name": "popupContainer",
"propType": "any"
}
],"configure": {
"component": {
"isContainer": true,
"isModel": true
}
}
},
{
"componentName": "Drawer.Inner",
"title": "Drawer.Inner",
"docUrl": "",
"screenshot": "",
"npm": {
"package": "@alifd/next",
"version": "1.19.18",
"exportName": "Drawer",
"main": "src/index.js",
"destructuring": true,
"subName": "Inner"
},
"props": [
{
"name": "prefix",
"propType": "string",
"defaultValue": "next-"
},
{
"name": "className",
"propType": "string"
},
{
"name": "closeable",
"propType": "bool",
"defaultValue": true
},
{
"name": "role",
"propType": "string",
"defaultValue": "dialog"
},
{
"name": "title",
"propType": "string"
},
{
"name": "placement",
"propType": {
"type": "oneOf",
"value": [
"top",
"right",
"bottom",
"left"
]
}
},
{
"name": "rtl",
"propType": "bool"
},
{
"name": "onClose",
"propType": "func"
},
{
"name": "locale",
"propType": "object"
},
{
"name": "headerStyle",
"propType": "object"
},
{
"name": "bodyStyle",
"propType": "object"
},
{
"name": "afterClose",
"propType": "func"
},
{
"name": "beforeOpen",
"propType": "func"
},
{
"name": "beforeClose",
"propType": "func"
},
{
"name": "cache",
"propType": "bool"
},
{
"name": "shouldUpdatePosition",
"propType": "bool"
}
]
},
{ {
"componentName": "Table", "componentName": "Table",
"title": "Table", "title": "Table",
@ -333,7 +589,7 @@
"exportName": "Table", "exportName": "Table",
"main": "src/index.js", "main": "src/index.js",
"destructuring": true, "destructuring": true,
"subName": "" "subName": "Column"
}, },
"props": [ "props": [
{ {
@ -401,7 +657,7 @@
"name": "showZero", "name": "showZero",
"propType": "bool", "propType": "bool",
"description": "当count为0时是否显示count", "description": "当count为0时是否显示count",
"defaultValue": false "defaultValue": true
}, },
{ {
"name": "content", "name": "content",
@ -1091,10 +1347,8 @@
}, },
{ {
"name": "children", "name": "children",
"propType": { "description": "内容",
"type": "instanceOf", "propType": "array"
"value": "node"
}
}, },
{ {
"name": "style", "name": "style",
@ -1253,17 +1507,19 @@
}, },
{ {
"name": "children", "name": "children",
"propType": { "propType": "array"
"type": "instanceOf",
"value": "node"
}
}, },
{ {
"name": "style", "name": "style",
"propType": "object", "propType": "object",
"description": "自定义内联样式" "description": "自定义内联样式"
} }
] ],
"configure": {
"component": {
"isContainer": true
}
}
}, },
{ {
"componentName": "Button.Group", "componentName": "Button.Group",
@ -4134,8 +4390,14 @@
{ {
"name": "children", "name": "children",
"propType": { "propType": {
"type": "instanceOf", "type": "oneOfType",
"value": "node" "value": [
"bool",
{
"type": "instanceOf",
"value": "node"
}
]
}, },
"description": "内容" "description": "内容"
}, },
@ -4298,8 +4560,10 @@
} }
], ],
"configure": { "configure": {
"isContainer": true, "component": {
"isModel": true "isContainer": true,
"isModel": true
}
} }
}, },
{ {
@ -6126,7 +6390,12 @@
"name": "style", "name": "style",
"propType": "object" "propType": "object"
} }
] ],
"configure": {
"component": {
"isContainer": true
}
}
}, },
{ {
"componentName": "SubMenu", "componentName": "SubMenu",
@ -6250,7 +6519,7 @@
] ]
}, },
{ {
"componentName": "SelectableItem", "componentName": "Menu.Item",
"title": "SelectableItem", "title": "SelectableItem",
"docUrl": "", "docUrl": "",
"screenshot": "", "screenshot": "",
@ -6548,8 +6817,8 @@
] ]
}, },
{ {
"componentName": "Group", "componentName": "Menu.Group",
"title": "Group", "title": "Menu.Group",
"docUrl": "", "docUrl": "",
"screenshot": "", "screenshot": "",
"npm": { "npm": {
@ -7852,7 +8121,7 @@
}, },
{ {
"name": "backgroundColor", "name": "backgroundColor",
"propType": "string", "propType": "color",
"description": "背景色" "description": "背景色"
}, },
{ {
@ -8242,6 +8511,11 @@
"name": "renderPreview", "name": "renderPreview",
"propType": "func", "propType": "func",
"description": "预览态模式下渲染的内容\n@param {number} value 评分值" "description": "预览态模式下渲染的内容\n@param {number} value 评分值"
},
{
"name": "value",
"propType": "number",
"description": "分值"
} }
] ]
}, },
@ -9972,6 +10246,73 @@
} }
] ]
}, },
{
"componentName": "Tag",
"title": "Tag",
"docUrl": "",
"screenshot": "",
"npm": {
"package": "@alifd/next",
"version": "1.19.18",
"exportName": "Tag",
"main": "src/index.js",
"destructuring": true
},
"props": [
{
"name": "prefix",
"propType": "string",
"defaultValue": "next-"
},
{
"name": "type",
"propType": {
"type": "oneOf",
"value": [
"normal",
"primary"
]
},
"description": "标签的类型"
},
{
"name": "size",
"propType": {
"type": "oneOf",
"value": [
"small",
"medium",
"large"
]
},
"description": "标签的尺寸large 尺寸为兼容表单场景 large = medium"
},
{
"name": "closeArea",
"propType": {
"type": "oneOf",
"value": [
"tag",
"tail"
]
}
},
{
"name": "color",
"propType": "string",
"description": "标签颜色, 目前支持blue、 green、 orange、red、 turquoise、 yellow 和 hex 颜色值 `color keywords`作为 Tag 组件的保留字,请勿直接使用 , `1.19.0` 以上版本生效"
},
{
"name": "children",
"propType": "array"
}
],
"configure": {
"component": {
"isContainer": true
}
}
},
{ {
"componentName": "TimePicker", "componentName": "TimePicker",
"title": "TimePicker", "title": "TimePicker",
@ -10266,7 +10607,12 @@
"name": "style", "name": "style",
"propType": "object" "propType": "object"
} }
] ],
"configure": {
"component": {
"isContainer": true
}
}
}, },
{ {
"componentName": "TimelineItem", "componentName": "TimelineItem",
@ -10524,11 +10870,24 @@
"propType": "func", "propType": "func",
"description": "接收 children 自定义渲染列表" "description": "接收 children 自定义渲染列表"
}, },
{
"name": "dataSource",
"propType": "array"
},
{ {
"name": "style", "name": "style",
"propType": "object" "propType": "object"
} }
] ],
"configure": {
"props": {
"isExtends": true,
"override": [{
"name": "dataSource",
"setter": "JsonSetter"
}]
}
}
}, },
{ {
"componentName": "Tree", "componentName": "Tree",
@ -10776,7 +11135,12 @@
"name": "style", "name": "style",
"propType": "object" "propType": "object"
} }
] ],
"configure": {
"component": {
"isContainer": true
}
}
}, },
{ {
"componentName": "TreeNode", "componentName": "TreeNode",
@ -11950,11 +12314,16 @@
"name": "style", "name": "style",
"propType": "object" "propType": "object"
} }
] ],
"configure": {
"component": {
"isContainer": true
}
}
}, },
{ {
"componentName": "Cell", "componentName": "ResponsiveGrid.Cell",
"title": "Cell", "title": "ResponsiveGrid.Cell",
"docUrl": "", "docUrl": "",
"screenshot": "", "screenshot": "",
"npm": { "npm": {
@ -12007,7 +12376,12 @@
"name": "style", "name": "style",
"propType": "object" "propType": "object"
} }
] ],
"configure": {
"component": {
"isContainer": true
}
}
}, },
{ {
"componentName": "Box", "componentName": "Box",
@ -12163,12 +12537,37 @@
"componentName": "Badge", "componentName": "Badge",
"props": { "props": {
"prefix": "next-", "prefix": "next-",
"overflowCount": 99 "showZero": true
} }
} }
} }
] ]
},{ },
{
"componentName": "Drawer",
"title": "抽屉",
"icon": "",
"package": "@alife/next",
"library": "Next",
"snippets": [
{
"title": "抽屉",
"screenshot": "https://img.alicdn.com/tfs/TB1RiM3lgHqK1RjSZFEXXcGMXXa-404-422.png",
"schema": {
"componentName": "Drawer",
"props": {
"prefix": "next-",
"triggerType": "click",
"closeable": true,
"placement": "right",
"hasMask": true,
"visible": true
}
}
}
]
},
{
"componentName": "Table", "componentName": "Table",
"title": "表格", "title": "表格",
"icon": "https://alifd.oss-cn-hangzhou.aliyuncs.com/fusion-cool/icons/icon-light/ic_light_table.png", "icon": "https://alifd.oss-cn-hangzhou.aliyuncs.com/fusion-cool/icons/icon-light/ic_light_table.png",
@ -12412,6 +12811,30 @@
} }
] ]
}, },
{
"componentName": "Menu.Item",
"title": "菜单项",
"icon": "",
"package": "@alife/next",
"library": "Next",
"snippets": [
{
"title": "菜单项",
"screenshot": "https://alifd.oss-cn-hangzhou.aliyuncs.com/fusion-cool/icons/icon-light/ic_light_menu.png",
"schema": {
"componentName": "Menu.Item",
"props": {
"parentMode": "inline",
"type": "item",
"component": "",
"disabled": true,
"className": "",
"needIndent": ""
}
}
}
]
},
{ {
"componentName": "Progress", "componentName": "Progress",
"title": "进度指示器", "title": "进度指示器",
@ -12506,6 +12929,46 @@
"screenshot": "https://alifd.oss-cn-hangzhou.aliyuncs.com/fusion-cool/icons/icon-light/ic_light_timeline.png", "screenshot": "https://alifd.oss-cn-hangzhou.aliyuncs.com/fusion-cool/icons/icon-light/ic_light_timeline.png",
"schema": { "schema": {
"componentName": "Timeline", "componentName": "Timeline",
"props": {
"prefix": "next-",
"fold": [],
"animation": true
},"children": [
{
"componentName": "TimelineItem",
"props": {
"state": "process",
"title": "12344"
}
},
{
"componentName": "TimelineItem",
"props": {
"title": "Ship"
}
},
{
"componentName": "TimelineItem",
"props": {
"title": "Order"
}
}
]
}
}
]
},{
"componentName": "TimelineItem",
"title": "时间轴 Item",
"icon": "",
"package": "@alife/next",
"library": "Next",
"snippets": [
{
"title": "时间轴 Item",
"screenshot": "https://alifd.oss-cn-hangzhou.aliyuncs.com/fusion-cool/icons/icon-light/ic_light_timeline.png",
"schema": {
"componentName": "TimelineItem",
"props": { "props": {
"prefix": "next-", "prefix": "next-",
"fold": [], "fold": [],
@ -12648,23 +13111,6 @@
} }
} }
] ]
},
{
"componentName": "Notification",
"title": "通知",
"icon": "",
"package": "@alife/next",
"library": "Next",
"snippets": [
{
"title": "通知",
"screenshot": "",
"schema": {
"componentName": "Notification",
"props": {}
}
}
]
} }
], ],
"icon": "" "icon": ""
@ -12720,9 +13166,9 @@
"type": "primary", "type": "primary",
"size": "large", "size": "large",
"htmlType": "button", "htmlType": "button",
"component": "button" "component": "button",
}, "children": ["提交"]
"children": "提交" }
} }
} }
] ]
@ -12825,7 +13271,9 @@
"screenshot": "", "screenshot": "",
"schema": { "schema": {
"componentName": "Icon", "componentName": "Icon",
"props": {} "props": {
"type": "smile"
}
} }
} }
] ]
@ -12870,17 +13318,17 @@
] ]
}, },
{ {
"componentName": "Shell", "componentName": "ResponsiveGrid.Cell",
"title": "框架", "title": "栅格布局 Cell",
"icon": "", "icon": "",
"package": "@alife/next", "package": "@alife/next",
"library": "Next", "library": "Next",
"snippets": [ "snippets": [
{ {
"title": "框架", "title": "栅格布局 Cell",
"screenshot": "", "screenshot": "",
"schema": { "schema": {
"componentName": "Shell", "componentName": "ResponsiveGrid.Cell",
"props": {} "props": {}
} }
} }
@ -12966,12 +13414,12 @@
"schema": { "schema": {
"componentName": "Breadcrumb.Item", "componentName": "Breadcrumb.Item",
"props": { "props": {
"prefix": "next-" "prefix": "next-",
}, "children": [
"children": [ "222",
"222", "222111"
"222111" ]
] }
} }
} }
] ]

View File

@ -72,37 +72,37 @@
"componentName":"Breadcrumb.Item", "componentName":"Breadcrumb.Item",
"id":"node_dockcy8n9xeg", "id":"node_dockcy8n9xeg",
"props":{ "props":{
"prefix":"next-" "prefix":"next-",
}, "children":[
"children":[ "首页"]
"首页"] }
}, },
{ {
"componentName":"Breadcrumb.Item", "componentName":"Breadcrumb.Item",
"id":"node_dockcy8n9xei", "id":"node_dockcy8n9xei",
"props":{ "props":{
"prefix":"next-" "prefix":"next-",
}, "children":[
"children":[ "品质中台"]
"品质中台"] }
}, },
{ {
"componentName":"Breadcrumb.Item", "componentName":"Breadcrumb.Item",
"id":"node_dockcy8n9xek", "id":"node_dockcy8n9xek",
"props":{ "props":{
"prefix":"next-" "prefix":"next-",
}, "children":[
"children":[ "商家品质页面管理"]
"商家品质页面管理"] }
}, },
{ {
"componentName":"Breadcrumb.Item", "componentName":"Breadcrumb.Item",
"id":"node_dockcy8n9xem", "id":"node_dockcy8n9xem",
"props":{ "props":{
"prefix":"next-" "prefix":"next-",
}, "children":[
"children":[ "质检知识条配置"]
"质检知识条配置"] }
}] }]
}] }]
}, },
@ -135,7 +135,7 @@
"id":"node_dockcy8n9xeq", "id":"node_dockcy8n9xeq",
"props":{ "props":{
"style":{ "style":{
"margin-bottom":"0" "marginBottom":"0"
}, },
"label":"类目名:" "label":"类目名:"
}, },
@ -158,7 +158,7 @@
"id":"node_dockcy8n9xes", "id":"node_dockcy8n9xes",
"props":{ "props":{
"style":{ "style":{
"margin-bottom":"0" "marginBottom":"0"
}, },
"label":"项目类型:" "label":"项目类型:"
}, },
@ -181,7 +181,7 @@
"id":"node_dockcy8n9xeu", "id":"node_dockcy8n9xeu",
"props":{ "props":{
"style":{ "style":{
"margin-bottom":"0" "marginBottom":"0"
}, },
"label":"项目 ID" "label":"项目 ID"
}, },
@ -213,17 +213,17 @@
"style":{ "style":{
"margin":"0 5px 0 5px" "margin":"0 5px 0 5px"
}, },
"htmlType":"submit" "htmlType":"submit",
}, "children":[
"children":[ {
{
"componentName":"Icon", "componentName":"Icon",
"id":"node_dockcy8n9xey", "id":"node_dockcy8n9xey",
"props":{ "props":{
"type":"success" "type":"success"
} }
}, },
"搜索"] "搜索"]
}
}, },
{ {
"componentName":"Button", "componentName":"Button",
@ -233,10 +233,10 @@
"style":{ "style":{
"margin":"0 5px 0 5px" "margin":"0 5px 0 5px"
}, },
"htmlType":"reset" "htmlType":"reset",
}, "children":[
"children":[ "清空"]
"清空"] }
}] }]
}] }]
}] }]
@ -266,6 +266,7 @@
"style":{ "style":{
"width":"100px" "width":"100px"
}, },
"children":["新建配置"],
"events":{ "events":{
"onClick":{ "onClick":{
"type":"JSFunction", "type":"JSFunction",
@ -287,9 +288,7 @@
"type":"JSFunction", "type":"JSFunction",
"value":"function(){ this.onClick() }" "value":"function(){ this.onClick() }"
} }
}, }
"children":[
"新建配置"]
}] }]
}, },
{ {
@ -456,13 +455,9 @@
"type":"JSExpression", "type":"JSExpression",
"value":"this.state.isShowDialog" "value":"this.state.isShowDialog"
}, },
"children":{
"type":"JSSlot"
},
"title":"标题", "title":"标题",
"footer":{
"type":"JSSlot"
},
"events":[ "events":[
] ]
} }

View File

@ -9,6 +9,7 @@ import variableBindDialog from '@ali/lowcode-plugin-variable-bind-dialog';
import sourceEditor from '@ali/lowcode-plugin-source-editor'; import sourceEditor from '@ali/lowcode-plugin-source-editor';
import codeout from './plugins/codeout'; import codeout from './plugins/codeout';
import saveload from './plugins/saveload';
export default { export default {
logo, logo,
@ -21,4 +22,5 @@ export default {
variableBindDialog, variableBindDialog,
sourceEditor, sourceEditor,
codeout, codeout,
saveload,
}; };

View File

@ -45,6 +45,14 @@ export default {
width: 64, width: 64,
}, },
}, },
{
pluginKey: 'saveload',
type: 'Custom',
props: {
align: 'right',
width: 128,
},
},
], ],
leftArea: [ leftArea: [
{ {

View File

@ -0,0 +1,4 @@
.lowcode-plugin-saveload {
padding: 10px 4px;
display: inline-block;
}

View File

@ -0,0 +1,68 @@
/* eslint-disable @typescript-eslint/no-empty-function */
/* eslint-disable @typescript-eslint/no-empty-interface */
import React from 'react';
import { Button } from '@alifd/next';
import { PluginProps, NpmInfo } from '@ali/lowcode-types';
import { Designer } from '@ali/lowcode-designer';
import './saveload.scss';
interface BasicSection {
componentName: string;
title: string;
description?: string;
docUrl?: string;
screenshot?: string;
icon?: string;
tags?: string[];
devMode?: 'proCode' | 'lowCode';
npm: NpmInfo;
[k: string]: any;
}
const Codeout = ({ editor }: PluginProps) => {
const handleSaveClick = () => {
const designer = editor.get(Designer);
if (designer) {
const schema = designer.schema.componentsTree[0]; // editor.get('schema');
const schemaStr = JSON.stringify(schema);
window.localStorage.setItem('schema_data', schemaStr);
console.info('save schema:', schemaStr);
alert('保存成功');
}
};
const handleLoadClick = () => {
const designer = editor.get(Designer);
if (designer) {
const tmp = window.localStorage.getItem('schema_data');
if (tmp) {
try {
const schema = JSON.parse(tmp);
editor.set('schema', schema);
console.info('load schema:', schema);
alert('加载成功');
} catch (error) {
console.log('Invalid Schema', error);
}
}
}
};
return (
<React.Fragment>
<div className="lowcode-plugin-saveload">
<Button type="primary" onClick={handleSaveClick}>
</Button>
</div>
<div className="lowcode-plugin-saveload">
<Button type="primary" onClick={handleLoadClick}>
</Button>
</div>
</React.Fragment>
);
};
export default Codeout;

View File

@ -211,6 +211,7 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp
) { ) {
if (component.isContainer !== false) { if (component.isContainer !== false) {
component.isContainer = true; component.isContainer = true;
props.push(propConfigToFieldConfig(prop));
return; return;
} }
} }

View File

@ -108,9 +108,17 @@ class Renderer extends Component<{ renderer: SimulatorRenderer }> {
const leaf = host.document.getNode(__id); const leaf = host.document.getNode(__id);
viewProps._leaf = leaf; viewProps._leaf = leaf;
viewProps._componentName = leaf?.componentName; viewProps._componentName = leaf?.componentName;
let _children = leaf?.isContainer() ? (children == null ? [] : Array.isArray(children) ? children : [children]) : children;
if (props.children && props.children.length) {
if (Array.isArray(props.children)) {
_children = Array.isArray(_children) ? _children.concat(props.children) : props.children.unshift(_children);
} else {
Array.isArray(_children) && _children.push(props.children) || (_children = [_children].push(props.children));
}
}
// 如果是容器 && 无children && 高宽为空 增加一个占位容器,方便拖动 // 如果是容器 && 无children && 高宽为空 增加一个占位容器,方便拖动
if (leaf?.isContainer() && children == null && (!viewProps.style || Object.keys(viewProps.style).length == 0)){ if (leaf?.isContainer() && (_children == null || !_children.length) && (!viewProps.style || Object.keys(viewProps.style).length == 0)){
children = <div style={{ _children = <div style={{
height:'66px', height:'66px',
backgroundColor:'#f0f0f0', backgroundColor:'#f0f0f0',
borderColor:'#a7b1bd', borderColor:'#a7b1bd',
@ -142,10 +150,11 @@ class Renderer extends Component<{ renderer: SimulatorRenderer }> {
}); });
console.info('menuprops', viewProps); console.info('menuprops', viewProps);
} }
return createElement( return createElement(
getDeviceView(Component, device, designMode), getDeviceView(Component, device, designMode),
viewProps, viewProps,
leaf?.isContainer() ? (children == null ? [] : Array.isArray(children) ? children : [children]) : children, _children,
); );
}} }}
onCompGetRef={(schema: any, ref: ReactInstance | null) => { onCompGetRef={(schema: any, ref: ReactInstance | null) => {