@cloudbase/framework-plugin-low-code 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/template/html/index.html.ejs +1 -1
- package/template/mp/app/weapps-api.js +3 -1
- package/template/mp/common/util.js +46 -0
- package/template/mp/common/weapp-page.js +14 -1
- package/template/mp/package.json +2 -2
- package/template/mp/page/index.js +3 -1
- package/template/package.json +2 -2
- package/template/src/app/global-api.js +5 -2
- package/template/src/handlers/FieldMiddleware/renderer.jsx +411 -321
- package/template/src/handlers/render.jsx +114 -97
- package/template/src/handlers/utils/common.js +1 -1
- package/template/src/pages/app.tpl +26 -25
- package/template/src/utils/formatEnum.js +42 -0
|
@@ -1,17 +1,117 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { useRef } from 'react';
|
|
3
2
|
import * as _ from 'lodash';
|
|
4
|
-
import {
|
|
3
|
+
import { ForContext, getComponentRenderList } from './FieldMiddleware/renderer';
|
|
5
4
|
import { isScopeSlot } from '../utils/index';
|
|
5
|
+
import { observer } from 'mobx-react-lite';
|
|
6
6
|
|
|
7
|
-
function getComponentChildren(component) {
|
|
7
|
+
export function getComponentChildren(component, context = {}) {
|
|
8
8
|
const { properties } = component;
|
|
9
9
|
if (!properties) {
|
|
10
10
|
return [];
|
|
11
11
|
}
|
|
12
|
-
|
|
12
|
+
const list = Object.values(properties).sort(
|
|
13
13
|
(a, b) => (a['x-index'] || 0) - (b['x-index'] || 0)
|
|
14
14
|
);
|
|
15
|
+
const {
|
|
16
|
+
virtualFields,
|
|
17
|
+
codeContext,
|
|
18
|
+
scopeContext,
|
|
19
|
+
forContext,
|
|
20
|
+
injectContext = {},
|
|
21
|
+
dataContext,
|
|
22
|
+
updateContext,
|
|
23
|
+
} = context;
|
|
24
|
+
|
|
25
|
+
return list.map((schema) => {
|
|
26
|
+
return getRenderList({
|
|
27
|
+
key: schema.key,
|
|
28
|
+
componentSchema: schema,
|
|
29
|
+
rootNode: false,
|
|
30
|
+
renderSlot: false,
|
|
31
|
+
virtualFields,
|
|
32
|
+
codeContext,
|
|
33
|
+
scopeContext,
|
|
34
|
+
forContext,
|
|
35
|
+
injectContext,
|
|
36
|
+
context: dataContext,
|
|
37
|
+
updateContext,
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function getRenderList(props) {
|
|
43
|
+
const {
|
|
44
|
+
key = '',
|
|
45
|
+
className,
|
|
46
|
+
virtualFields,
|
|
47
|
+
componentSchema,
|
|
48
|
+
renderSlot,
|
|
49
|
+
rootNode = true,
|
|
50
|
+
codeContext,
|
|
51
|
+
scopeContext = {},
|
|
52
|
+
context = {},
|
|
53
|
+
updateContext,
|
|
54
|
+
forContext = {},
|
|
55
|
+
} = props;
|
|
56
|
+
|
|
57
|
+
const { 'x-props': xProps, properties = {} } = componentSchema;
|
|
58
|
+
|
|
59
|
+
// 判断是否为 slot
|
|
60
|
+
const isSlot = !xProps;
|
|
61
|
+
if (isSlot && !(renderSlot || rootNode)) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// const preClassName = useRef();
|
|
66
|
+
|
|
67
|
+
// wrapperClass
|
|
68
|
+
const containerEl = Object.values(properties)[0];
|
|
69
|
+
if (containerEl && containerEl['x-props'] && className) {
|
|
70
|
+
let { classNameList = [] } = containerEl['x-props'];
|
|
71
|
+
|
|
72
|
+
// 先替换掉先前计算出来的className部分
|
|
73
|
+
// if (preClassName.current) {
|
|
74
|
+
// if (preClassName.current !== className) {
|
|
75
|
+
// classNameList = classNameList.filter(
|
|
76
|
+
// (clsName) => clsName !== preClassName.current
|
|
77
|
+
// );
|
|
78
|
+
// preClassName.current = className;
|
|
79
|
+
// }
|
|
80
|
+
// } else {
|
|
81
|
+
// preClassName.current = className;
|
|
82
|
+
// }
|
|
83
|
+
|
|
84
|
+
containerEl['x-props'].classNameList = Array.from(
|
|
85
|
+
new Set([className, ...classNameList])
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (xProps && xProps.sourceKey) {
|
|
90
|
+
const { sourceKey } = xProps;
|
|
91
|
+
const Field = virtualFields[sourceKey];
|
|
92
|
+
if (!Field) {
|
|
93
|
+
return (
|
|
94
|
+
<div style={{ color: 'red' }}>
|
|
95
|
+
组件<em>{sourceKey}</em>未找到
|
|
96
|
+
</div>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return getComponentRenderList({
|
|
102
|
+
key,
|
|
103
|
+
componentSchema,
|
|
104
|
+
id: componentSchema.key,
|
|
105
|
+
xProps,
|
|
106
|
+
emitEvents: componentSchema.emitEvents || [],
|
|
107
|
+
virtualFields,
|
|
108
|
+
renderSlot,
|
|
109
|
+
codeContext,
|
|
110
|
+
scopeContext,
|
|
111
|
+
forContext,
|
|
112
|
+
context,
|
|
113
|
+
updateContext,
|
|
114
|
+
});
|
|
15
115
|
}
|
|
16
116
|
|
|
17
117
|
export function generateSlotMetaMap(componentSchema, context, options = {}) {
|
|
@@ -36,14 +136,10 @@ export function generateSlotMetaMap(componentSchema, context, options = {}) {
|
|
|
36
136
|
node: isHOC
|
|
37
137
|
? (props) => {
|
|
38
138
|
let clonedScopeContext = _.cloneDeep(scopeContext);
|
|
39
|
-
_.set(
|
|
40
|
-
clonedScopeContext,
|
|
41
|
-
`${componentSchema.key}.${child.key}`,
|
|
42
|
-
props
|
|
43
|
-
);
|
|
139
|
+
_.set(clonedScopeContext, `${componentSchema.key}.${key}`, props);
|
|
44
140
|
return (
|
|
45
141
|
<AppRender
|
|
46
|
-
key={
|
|
142
|
+
key={key}
|
|
47
143
|
componentSchema={child}
|
|
48
144
|
renderSlot={options?.renderSlot}
|
|
49
145
|
virtualFields={virtualFields}
|
|
@@ -58,7 +154,7 @@ export function generateSlotMetaMap(componentSchema, context, options = {}) {
|
|
|
58
154
|
return (
|
|
59
155
|
<ForContext.Provider value={forContext}>
|
|
60
156
|
<AppRender
|
|
61
|
-
key={
|
|
157
|
+
key={key}
|
|
62
158
|
componentSchema={child}
|
|
63
159
|
renderSlot={options?.renderSlot}
|
|
64
160
|
virtualFields={virtualFields}
|
|
@@ -76,89 +172,10 @@ export function generateSlotMetaMap(componentSchema, context, options = {}) {
|
|
|
76
172
|
return slots;
|
|
77
173
|
}
|
|
78
174
|
|
|
79
|
-
export
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
codeContext,
|
|
87
|
-
scopeContext = {},
|
|
88
|
-
context = {},
|
|
89
|
-
updateContext,
|
|
90
|
-
} = props;
|
|
91
|
-
|
|
92
|
-
const { 'x-props': xProps, properties = {} } = componentSchema;
|
|
93
|
-
|
|
94
|
-
// 判断是否为 slot
|
|
95
|
-
const isSlot = !xProps;
|
|
96
|
-
if (isSlot && !(renderSlot || rootNode)) {
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const preClassName = useRef();
|
|
101
|
-
|
|
102
|
-
// wrapperClass
|
|
103
|
-
const containerEl = Object.values(properties)[0];
|
|
104
|
-
if (containerEl && containerEl['x-props'] && className) {
|
|
105
|
-
let { classNameList = [] } = containerEl['x-props'];
|
|
106
|
-
|
|
107
|
-
// 先替换掉先前计算出来的className部分
|
|
108
|
-
if (preClassName.current) {
|
|
109
|
-
if (preClassName.current !== className) {
|
|
110
|
-
classNameList = classNameList.filter(
|
|
111
|
-
(clsName) => clsName !== preClassName.current
|
|
112
|
-
);
|
|
113
|
-
preClassName.current = className;
|
|
114
|
-
}
|
|
115
|
-
} else {
|
|
116
|
-
preClassName.current = className;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
containerEl['x-props'].classNameList = [className, ...classNameList];
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (xProps && xProps.sourceKey) {
|
|
123
|
-
const { sourceKey } = xProps;
|
|
124
|
-
const Field = virtualFields[sourceKey];
|
|
125
|
-
if (!Field) {
|
|
126
|
-
return (
|
|
127
|
-
<div style={{ color: 'red' }}>
|
|
128
|
-
组件<em>{sourceKey}</em>未找到
|
|
129
|
-
</div>
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const children = getComponentChildren(componentSchema);
|
|
135
|
-
|
|
136
|
-
return (
|
|
137
|
-
<CompRenderer
|
|
138
|
-
id={componentSchema.key}
|
|
139
|
-
xProps={xProps}
|
|
140
|
-
emitEvents={componentSchema.emitEvents || []}
|
|
141
|
-
componentSchema={componentSchema}
|
|
142
|
-
virtualFields={virtualFields}
|
|
143
|
-
renderSlot={renderSlot}
|
|
144
|
-
codeContext={codeContext}
|
|
145
|
-
scopeContext={scopeContext}
|
|
146
|
-
context={context}
|
|
147
|
-
updateContext={updateContext}
|
|
148
|
-
>
|
|
149
|
-
{children.map((comp) => (
|
|
150
|
-
<AppRender
|
|
151
|
-
key={comp.key}
|
|
152
|
-
componentSchema={comp}
|
|
153
|
-
rootNode={false}
|
|
154
|
-
renderSlot={false}
|
|
155
|
-
virtualFields={virtualFields}
|
|
156
|
-
codeContext={codeContext}
|
|
157
|
-
scopeContext={scopeContext}
|
|
158
|
-
context={context}
|
|
159
|
-
updateContext={updateContext}
|
|
160
|
-
/>
|
|
161
|
-
))}
|
|
162
|
-
</CompRenderer>
|
|
163
|
-
);
|
|
164
|
-
}
|
|
175
|
+
export const AppRender = observer(function (props) {
|
|
176
|
+
return getRenderList({
|
|
177
|
+
...props,
|
|
178
|
+
forContext: React.useContext(ForContext),
|
|
179
|
+
injectContext: {},
|
|
180
|
+
});
|
|
181
|
+
});
|
|
@@ -84,7 +84,7 @@ export function resolveComponentProps(props, isPlainProps) {
|
|
|
84
84
|
...props,
|
|
85
85
|
};
|
|
86
86
|
}
|
|
87
|
-
const { data = {}, events = [], ...restProps } = props;
|
|
87
|
+
const { data = {}, events = [], $node, ...restProps } = props;
|
|
88
88
|
const customProps = { ...data };
|
|
89
89
|
const builtinProps = [
|
|
90
90
|
// react 保留字
|
|
@@ -78,37 +78,19 @@ initLifeCycle({
|
|
|
78
78
|
export default function App() {
|
|
79
79
|
// 检查权限
|
|
80
80
|
const [weDaHasLogin, setWeDaHasLogin] = React.useState(false);
|
|
81
|
-
const
|
|
81
|
+
const dataContextRef = React.useRef(observable({}))
|
|
82
|
+
const context = dataContextRef.current;
|
|
82
83
|
const containerRef = React.useRef(null);
|
|
83
84
|
const microApp = React.useRef(null);
|
|
84
85
|
const pureSrc = '<%= pageSource %>';
|
|
85
86
|
const isPure = !!pureSrc;
|
|
86
87
|
|
|
87
|
-
/**
|
|
88
|
-
* 更新数据容器的上下文的方法
|
|
89
|
-
* 会传递到事件emit的地方,将从组件获取到的数据data赋值给上下文
|
|
90
|
-
* 当组件卸载时,传过来的data为undefined即可
|
|
91
|
-
* {
|
|
92
|
-
* id1: [{...}],
|
|
93
|
-
* id2: {...},
|
|
94
|
-
* id3: undefined,
|
|
95
|
-
* id4: null,
|
|
96
|
-
* ...
|
|
97
|
-
* }
|
|
98
|
-
* @param id
|
|
99
|
-
* @param data
|
|
100
|
-
*/
|
|
101
|
-
const updateContext = (id, data) => {
|
|
102
|
-
if (id) {
|
|
103
|
-
context[id] = { data };
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
88
|
React.useEffect(() => {
|
|
108
89
|
Object.assign($page, {
|
|
109
90
|
id: '<%= pageName %>',
|
|
110
91
|
state: observable(initPageState),
|
|
111
92
|
computed: createComputed(computed),
|
|
93
|
+
// _context: context,
|
|
112
94
|
handler,
|
|
113
95
|
});
|
|
114
96
|
|
|
@@ -134,10 +116,10 @@ export default function App() {
|
|
|
134
116
|
}, []);
|
|
135
117
|
|
|
136
118
|
React.useEffect(() => {
|
|
137
|
-
$page.widgets = createWidgets(widgetsContext, dataBinds, {},
|
|
119
|
+
$page.widgets = createWidgets(widgetsContext, dataBinds, {}, dataContextRef.current);
|
|
138
120
|
// widgets 内的 dataBinds 可能需要关联 widgets,需要重新执行 dataBinds
|
|
139
121
|
retryDataBinds();
|
|
140
|
-
}, [
|
|
122
|
+
}, [dataContextRef.current]);
|
|
141
123
|
|
|
142
124
|
// Web 环境页面级别生命周期
|
|
143
125
|
if (!process.env.isMiniprogram) {
|
|
@@ -179,8 +161,27 @@ export default function App() {
|
|
|
179
161
|
<AppRender pageListenerInstances={pageListenerInstances}
|
|
180
162
|
virtualFields={virtualFields}
|
|
181
163
|
componentSchema={componentSchema}
|
|
182
|
-
context={
|
|
183
|
-
|
|
164
|
+
context={dataContextRef.current}
|
|
165
|
+
/**
|
|
166
|
+
* 更新数据容器的上下文的方法
|
|
167
|
+
* 会传递到事件emit的地方,将从组件获取到的数据data赋值给上下文
|
|
168
|
+
* 当组件卸载时,传过来的data为undefined即可
|
|
169
|
+
* {
|
|
170
|
+
* id1: [{...}],
|
|
171
|
+
* id2: {...},
|
|
172
|
+
* id3: undefined,
|
|
173
|
+
* id4: null,
|
|
174
|
+
* ...
|
|
175
|
+
* }
|
|
176
|
+
* @param id
|
|
177
|
+
* @param data
|
|
178
|
+
*/
|
|
179
|
+
updateContext={(id, data) => {
|
|
180
|
+
if (id) {
|
|
181
|
+
dataContextRef.current[id] = { data };
|
|
182
|
+
// console.log('111', context[id])
|
|
183
|
+
}
|
|
184
|
+
}}
|
|
184
185
|
/>
|
|
185
186
|
)}
|
|
186
187
|
</div>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { observable } from 'mobx';
|
|
2
|
+
let loading = {};
|
|
3
|
+
export let enumOptions = observable({});
|
|
4
|
+
export function formatEnum(path, optionname) {
|
|
5
|
+
// 判断是单选还是多选
|
|
6
|
+
let isSingle = Array.isArray(path);
|
|
7
|
+
// 获取到options
|
|
8
|
+
let parseOptions = getEnumOptions(optionname);
|
|
9
|
+
if (parseOptions === '') {
|
|
10
|
+
return !isSingle ? path : path.join(',');
|
|
11
|
+
}
|
|
12
|
+
let multiTmp = [];
|
|
13
|
+
let value = !isSingle
|
|
14
|
+
? JSON.parse(parseOptions)?.find((item) => item?.key === path)?.value
|
|
15
|
+
: JSON.parse(parseOptions)
|
|
16
|
+
?.filter((item) => path.some((pathValue) => item?.key === pathValue))
|
|
17
|
+
.map((item) => multiTmp.push(item?.value));
|
|
18
|
+
// 对多选或者单选有不同处理
|
|
19
|
+
return !isSingle ? value : multiTmp?.join(',');
|
|
20
|
+
}
|
|
21
|
+
function getEnumOptions(optionName) {
|
|
22
|
+
if (enumOptions[optionName]) {
|
|
23
|
+
return enumOptions[optionName];
|
|
24
|
+
}
|
|
25
|
+
if (!loading[optionName]) {
|
|
26
|
+
loading[optionName] = true;
|
|
27
|
+
getGeneralOptions(optionName).then((data) => {
|
|
28
|
+
enumOptions[optionName] = data?.Items[0]?.Config;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return '';
|
|
32
|
+
}
|
|
33
|
+
export async function getGeneralOptions(optionName) {
|
|
34
|
+
return app.cloud.callWedaApi({
|
|
35
|
+
action: 'DescribeGeneralOptionsDetailList',
|
|
36
|
+
data: {
|
|
37
|
+
PageSize: 1,
|
|
38
|
+
PageIndex: 1,
|
|
39
|
+
LikeNameOrTitle: optionName,
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
}
|