上文我们已经识别出了组件,组件文案。接下来就可以通过这些数据生成前端代码了。

这里沿用阿里DSL的格式,先将识别内容生成通用scheme,再把scheme根据不同的DSL转换为相应语言、框架的代码。这样做一方面提高通用性,另一方面,可以把scheme复制到编辑器中进行可视化编辑。

编辑器demo:

https://blog.dappwind.com/crm-editor/#/zh-CN/

以这个图片为例

表单项 自动生成 英文驼峰命名

根据元素前面的文字,调用有道翻译的api,翻译出英语,然后再转为驼峰法命名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# 翻译 获取英文驼峰命名
import json
import requests
import re

# 下划线转驼峰
def str2Hump(text):
arr = filter(None, text.lower().split(' '))
res = ''
j = 0
for i in arr:
if j == 0:
res = i
else:
res = res + i[0].upper() + i[1:]
j += 1
return res

# 翻译函数,word 需要翻译的内容
def translate(word):
word = re.sub(r'[^\w\s]','', word or '默认值')
# 有道词典 api
url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=null'
# 传输的参数,其中 i 为需要翻译的内容
key = {
'type': "AUTO",
'i': word,
"doctype": "json",
"version": "2.1",
"keyfrom": "fanyi.web",
"ue": "UTF-8",
"action": "FY_BY_CLICKBUTTON",
"typoResult": "true"
}
# key 这个字典为发送给有道词典服务器的内容
response = requests.post(url, data=key)
# 判断服务器是否相应成功
if response.status_code == 200:
# 然后相应的结果
result = json.loads(response.text)
text = result['translateResult'][0][0]['tgt']
return str2Hump(text)
else:
print("有道词典调用失败")
# 相应失败就返回空
return None

结果打印如下

1
2
3
4
5
6
表单项: 活动名称 ———— 驼峰命名:theNameOfTheEvent
表单项:位置———— 驼峰命名:location
表单项:可配置标题———— 驼峰命名:configurableTitle
表单项: 图片链接 ———— 驼峰命名:imageLinks
表单项:图片跳转链接———— 驼峰命名:picturesJumpLinks
表单项: 基金代码 ———— 驼峰命名:theFundCode

python数据导出

1
2
3
4
5
6
7
8
9
# 将预测结果传入之前的数组
for index in range(len(boxes_batch)):
boxes_batch[index]['predict'] = predicted_name[index]

# 按照纵坐标排序,排序前是 nparray, 排序后已经是list了
boxes_batch = sorted(boxes_batch, key= lambda item: item['position'][0][1])

print(boxes_batch)
return boxes_batch

结果

1
[[[[663,170],[200,170],[200,123],[663,123]],"请输入活动名称","* 活动名称 :","Input"],[[[197,497],[197,449],[666,449],[666,497]],"必填","*图片跳转链接","Input"],[[[201,79],[201,31],[660,31],[660,79]],"请输入基金代码","* 基金代码 :","Input"],[[[197,427],[197,380],[665,380],[665,427]],"非必填,不配置不展示","可配置标题","Input"],[[[197,358],[197,307],[666,307],[666,358]],"","位置","Select"],[[[663,266],[200,266],[200,219],[663,219]],"请输入图片链接","* 图片链接 :","Input"]]

每个数组代表一个组件,里面有组件的位置,文案等

后续都放在js中处理,方便些。

生成schema

按照schema格式生成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
const path = require('path');
const fs = require('fs');

const data = require('./colab_data');

const scheme = {
"componentName": "Page",
"props": {},
"children": [{
"componentName": "Form",
"props": {
},
"children": [],
}],
}

data.map(item => {
scheme.children[0].children.push({
"componentName": "FormItem",
"props": {
"label": item[2],
"name": "",
"style": {}
},
"children": [{
"componentName": item[3],
"props": {
"placeholder": item[1],
"hasBorder": true
}
}]
})
})

fs.writeFileSync(path.join(__dirname,'../test/data_out.js'), `module.exports = ${JSON.stringify(scheme)}`);

生成的scheme如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
{
"componentName": "Page",
"props": {},
"children": [
{
"componentName": "Form",
"props": {},
"children": [
{
"componentName": "FormItem",
"props": {
"label": "* 基金代码 :",
"name": "",
"style": {}
},
"children": [
{
"componentName": "Input",
"props": {
"placeholder": "请输入基金代码",
"hasBorder": true
}
}
]
},
{
"componentName": "FormItem",
"props": {
"label": "* 活动名称 :",
"name": "",
"style": {}
},
"children": [
{
"componentName": "Input",
"props": {
"placeholder": "请输入活动名称",
"hasBorder": true
}
}
]
},
{
"componentName": "FormItem",
"props": {
"label": "* 图片链接 :",
"name": "",
"style": {}
},
"children": [
{
"componentName": "Input",
"props": {
"placeholder": "请输入图片链接",
"hasBorder": true
}
}
]
},
{
"componentName": "FormItem",
"props": {
"label": "位置",
"name": "",
"style": {}
},
"children": [
{
"componentName": "Select",
"props": {
"placeholder": "",
"hasBorder": true
}
}
]
},
{
"componentName": "FormItem",
"props": {
"label": "可配置标题",
"name": "",
"style": {}
},
"children": [
{
"componentName": "Input",
"props": {
"placeholder": "非必填,不配置不展示",
"hasBorder": true
}
}
]
},
{
"componentName": "FormItem",
"props": {
"label": "*图片跳转链接",
"name": "",
"style": {}
},
"children": [
{
"componentName": "Input",
"props": {
"placeholder": "必填",
"hasBorder": true
}
}
]
}
]
}
]
}

随后调用scheme转前端代码的DSL,我们使用的是antd, 目前还没有好用的DSL,所以在Fusion Design上二次开发,最后生成代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
'use strict';

import React, { Component } from 'react';
import { Input } from 'antd';
import { Form } from 'antd';
import { Select } from 'antd';
import styles from './style.js';
const print = function(value) {
console.log(value);
};
const FormItem = Form.Item;
class Page_0 extends Component {
render() {
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 4 }
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 }
}
};
return (
<div>
<Form>
<FormItem label={'* 基金代码 :'} name={''} {...formItemLayout}>
<Input placeholder={'请输入基金代码'} hasBorder={true} />
</FormItem>
<FormItem label={'* 活动名称 :'} name={''} {...formItemLayout}>
<Input placeholder={'请输入活动名称'} hasBorder={true} />
</FormItem>
<FormItem label={'* 图片链接 :'} name={''} {...formItemLayout}>
<Input placeholder={'请输入图片链接'} hasBorder={true} />
</FormItem>
<FormItem label={'位置'} name={''} {...formItemLayout}>
<Select placeholder={''} hasBorder={true} />
</FormItem>
<FormItem label={'可配置标题'} name={''} {...formItemLayout}>
<Input placeholder={'非必填,不配置不展示'} hasBorder={true} />
</FormItem>
<FormItem label={'*图片跳转链接'} name={''} {...formItemLayout}>
<Input placeholder={'必填'} hasBorder={true} />
</FormItem>
</Form>
</div>
);
}
}
export default Page_0;

原始原型图如下

智能生成页面渲染如下