@cloudbase/framework-plugin-low-code 0.7.0 → 0.7.2-beta.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.
Files changed (76) hide show
  1. package/lib/builder/config/common.js +1 -1
  2. package/lib/builder/config/index.js +2 -2
  3. package/lib/builder/config/mp.js +1 -1
  4. package/lib/builder/core/copy.js +3 -3
  5. package/lib/builder/core/generate.js +11 -11
  6. package/lib/builder/core/index.js +13 -13
  7. package/lib/builder/core/material.js +6 -6
  8. package/lib/builder/core/plugin.js +3 -3
  9. package/lib/builder/core/prepare.js +2 -2
  10. package/lib/builder/core/webpack.js +5 -5
  11. package/lib/builder/mp/index.d.ts.map +1 -1
  12. package/lib/builder/mp/index.js +50 -49
  13. package/lib/builder/mp/lowcode.js +4 -4
  14. package/lib/builder/mp/materials.js +16 -16
  15. package/lib/builder/mp/mixMode.js +12 -12
  16. package/lib/builder/mp/mp_config.js +11 -11
  17. package/lib/builder/mp/util.js +6 -6
  18. package/lib/builder/mp/wxml.js +4 -4
  19. package/lib/builder/service/builder/copy.js +11 -11
  20. package/lib/builder/service/builder/generate.js +56 -52
  21. package/lib/builder/service/builder/index.js +2 -2
  22. package/lib/builder/service/builder/plugin.js +2 -2
  23. package/lib/builder/service/builder/webpack.js +24 -23
  24. package/lib/builder/types/common.js +1 -0
  25. package/lib/builder/util/common.d.ts.map +1 -1
  26. package/lib/builder/util/common.js +8 -6
  27. package/lib/builder/util/console.js +1 -1
  28. package/lib/builder/util/generateFiles.js +2 -2
  29. package/lib/builder/util/index.js +1 -1
  30. package/lib/builder/util/junk.js +4 -2
  31. package/lib/builder/util/mp.js +1 -1
  32. package/lib/builder/util/net.js +1 -1
  33. package/lib/builder/util/style.js +1 -1
  34. package/lib/builder/util/weapp.js +1 -1
  35. package/lib/generate.js +2 -2
  36. package/lib/generator/config/index.js +2 -2
  37. package/lib/generator/core/generate.js +36 -34
  38. package/lib/generator/core/index.js +4 -4
  39. package/lib/generator/core/material.js +14 -14
  40. package/lib/generator/types/common.js +6 -3
  41. package/lib/generator/util/common.d.ts.map +1 -1
  42. package/lib/generator/util/common.js +1 -1
  43. package/lib/generator/util/index.js +1 -1
  44. package/lib/generator/util/style.js +2 -2
  45. package/lib/index.d.ts.map +1 -1
  46. package/lib/index.js +104 -66
  47. package/lib/utils/common.d.ts +1 -1
  48. package/lib/utils/common.d.ts.map +1 -1
  49. package/lib/utils/common.js +2 -2
  50. package/lib/utils/dataSource.js +2 -2
  51. package/lib/utils/index.js +1 -1
  52. package/lib/utils/postProcess.js +3 -3
  53. package/lib/weapps-core/config/index.js +1 -1
  54. package/lib/weapps-core/index.js +2 -2
  55. package/lib/weapps-core/types/index.js +1 -1
  56. package/lib/weapps-core/utils/appbuild.js +6 -3
  57. package/lib/weapps-core/utils/common.js +3 -2
  58. package/lib/weapps-core/utils/formily.js +37 -37
  59. package/lib/weapps-core/utils/index.js +1 -1
  60. package/lib/weapps-core/utils/style.js +15 -15
  61. package/package.json +1 -1
  62. package/template/html/index.html.ejs +1 -1
  63. package/template/mp/app/weapps-api.js +16 -6
  64. package/template/mp/app.js +59 -48
  65. package/template/mp/common/util.js +52 -4
  66. package/template/mp/common/weapp-page.js +16 -3
  67. package/template/mp/package.json +2 -2
  68. package/template/mp/page/index.js +3 -1
  69. package/template/package.json +2 -2
  70. package/template/src/app/global-api.js +20 -5
  71. package/template/src/handlers/FieldMiddleware/renderer.jsx +411 -321
  72. package/template/src/handlers/render.jsx +114 -97
  73. package/template/src/handlers/utils/common.js +28 -22
  74. package/template/src/index.jsx +3 -2
  75. package/template/src/pages/app.tpl +26 -25
  76. 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 { CompRenderer, ForContext } from './FieldMiddleware/renderer';
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
- return Object.values(properties).sort(
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={child.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={child.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 function AppRender(props) {
80
- const {
81
- className,
82
- virtualFields,
83
- componentSchema,
84
- renderSlot,
85
- rootNode = true,
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 保留字
@@ -150,12 +150,12 @@ export function getStaticResourceAttribute(staticUrl) {
150
150
  }
151
151
 
152
152
  export function findLoginPage(app = window.app) {
153
- const { pages = [] } = app.utils._getConfig();
153
+ const { pages = [] } = app.__internal__.getConfig();
154
154
  return pages.find(item => item.type === 'login');
155
155
  }
156
156
 
157
157
  let _AUTH_CONFIG_CACHE = null;
158
- async function getAuthConfig(app = window.app) {
158
+ export async function getAuthConfig(app = window.app) {
159
159
  if (_AUTH_CONFIG_CACHE) {
160
160
  return _AUTH_CONFIG_CACHE;
161
161
  }
@@ -209,6 +209,19 @@ async function getAccessPermission(app, appId, pageId) {
209
209
  return isAccess
210
210
  }
211
211
 
212
+ export async function checkAnonymous() {
213
+ // 用户是否非匿名登录前端判断条件:有accessToken且scope不为anonymous
214
+ // 此分支逻辑本不应该前端判断是否登录,历史原因后端短期内搞不定,后续后端优化后删除
215
+ let isAnonymous = true;
216
+ try {
217
+ const [scope, { accessToken }] = await Promise.all([loginScope(), getAccessToken()]);
218
+ if (accessToken && scope !== 'anonymous') {
219
+ isAnonymous = false;
220
+ }
221
+ } catch (e) { }
222
+ return isAnonymous;
223
+ }
224
+
212
225
  /**
213
226
  * 检查页面权限
214
227
  **/
@@ -223,31 +236,24 @@ export async function checkAuth(app, appId, $page) {
223
236
  // 暂时先认为有登录页则自定义登录功能开启且生效
224
237
  if (loginPage) {
225
238
  requestList.push(getAuthConfig(app));
239
+ requestList.push(checkAnonymous());
226
240
  }
227
- const [isAccess, authConfig] = await Promise.all(requestList);
241
+ const [isAccess, authConfig, isAnonymous] = await Promise.all(requestList);
228
242
  app.hideNavigationBarLoading();
229
243
 
230
- if (!isAccess) {
231
- if (loginPage && (authConfig.NeedLogin || authConfig.RejectStrategy == 'to_login')) {
232
- redirectToLogin($page);
233
- } else {
234
- app.showToast({
235
- title: '页面无访问权限',
236
- icon: 'error',
237
- });
238
- }
239
- } else if (loginPage && authConfig.NeedLogin) {
240
- // 此分支逻辑本不应该前端判断是否登录,历史原因后端短期内搞不定,后续后端优化后删除
241
- try {
242
- const [scope, { accessToken }] = await Promise.all([loginScope(), getAccessToken()]);
243
- if (!accessToken || scope === 'anonymous') {
244
- redirectToLogin($page);
245
- }
246
- } catch (e) {
247
- console.error('获取身份失败', e);
244
+ if (loginPage && isAnonymous) {
245
+ if (authConfig.NeedLogin || (!isAccess && authConfig.RejectStrategy === 'to_login')) {
248
246
  redirectToLogin($page);
247
+ return isAccess;
249
248
  }
250
249
  }
250
+
251
+ if (!isAccess) {
252
+ app.showToast({
253
+ title: '页面无访问权限',
254
+ icon: 'error',
255
+ });
256
+ }
251
257
  return isAccess;
252
258
  }
253
259
 
@@ -12,7 +12,7 @@ import attachFastClick from 'fastclick'
12
12
  import { initWebConfig } from 'handlers/lifecycle'
13
13
  const AppConfig = require('../webpack/miniprogram.config')
14
14
  import { app } from './app/global-api'
15
- import { redirectToLogin, findLoginPage, getAuthConfig } from './handlers/utils'
15
+ import { redirectToLogin, findLoginPage, getAuthConfig, checkAnonymous } from './handlers/utils'
16
16
  // app 中注册配置页面以及app的全局配置miniprogram.config,h5里分app以及web页分别处理,使用process.env.isApp 区分判断
17
17
  if (process.env.isApp) {
18
18
  initWebConfig(app, AppConfig);
@@ -63,7 +63,8 @@ setConfig({
63
63
  const loginPage = findLoginPage();
64
64
  if (loginPage) {
65
65
  const authConfig = await getAuthConfig();
66
- if (authConfig.NeedLogin || authConfig.RejectStrategy == 'to_login') {
66
+ const isAnonymous = await checkAnonymous();
67
+ if (isAnonymous && authConfig.RejectStrategy == 'to_login') {
67
68
  redirectToLogin();
68
69
  } else if (authConfig.RejectStrategy == 'show_warning') {
69
70
  app.showToast({
@@ -78,37 +78,19 @@ initLifeCycle({
78
78
  export default function App() {
79
79
  // 检查权限
80
80
  const [weDaHasLogin, setWeDaHasLogin] = React.useState(false);
81
- const context = React.useRef(observable({})).current;
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, {}, context);
119
+ $page.widgets = createWidgets(widgetsContext, dataBinds, {}, dataContextRef.current);
138
120
  // widgets 内的 dataBinds 可能需要关联 widgets,需要重新执行 dataBinds
139
121
  retryDataBinds();
140
- }, [context]);
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={context}
183
- updateContext={updateContext}
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
+ }