@cloudbase/framework-plugin-low-code 0.6.67 → 0.7.0
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/lib/builder/core/generate.d.ts.map +1 -1
- package/lib/builder/core/generate.js +8 -3
- package/lib/builder/mp/index.d.ts.map +1 -1
- package/lib/builder/mp/index.js +11 -6
- package/lib/builder/service/builder/generate.d.ts.map +1 -1
- package/lib/builder/service/builder/generate.js +2 -0
- package/lib/generator/core/generate.d.ts.map +1 -1
- package/lib/generator/core/generate.js +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +13 -46
- package/lib/weapps-core/types/app.d.ts +1 -0
- package/lib/weapps-core/types/app.d.ts.map +1 -1
- package/lib/weapps-core/types/web.d.ts +1 -0
- package/lib/weapps-core/types/web.d.ts.map +1 -1
- package/package.json +1 -1
- package/template/html/index.html.ejs +2 -15
- package/template/mp/app/weapps-api.js +4 -3
- package/template/mp/app.js +69 -24
- package/template/mp/common/util.js +121 -69
- package/template/mp/common/weapp-page.js +2 -15
- package/template/mp/datasources/config.js.tpl +2 -0
- package/template/mp/package.json +10 -8
- package/template/mp/page/index.js +1 -3
- package/template/package.json +2 -2
- package/template/src/app/global-api.js +3 -3
- package/template/src/datasources/config.js.tpl +2 -0
- package/template/src/handlers/FieldMiddleware/renderer.jsx +321 -411
- package/template/src/handlers/render.jsx +97 -114
- package/template/src/handlers/utils/common.js +132 -29
- package/template/src/index.jsx +45 -1
- package/template/src/pages/app.tpl +31 -31
- package/template/src/utils/formatEnum.js +0 -42
|
@@ -1,117 +1,17 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { useRef } from 'react';
|
|
2
3
|
import * as _ from 'lodash';
|
|
3
|
-
import {
|
|
4
|
+
import { CompRenderer, ForContext } from './FieldMiddleware/renderer';
|
|
4
5
|
import { isScopeSlot } from '../utils/index';
|
|
5
|
-
import { observer } from 'mobx-react-lite';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
function getComponentChildren(component) {
|
|
8
8
|
const { properties } = component;
|
|
9
9
|
if (!properties) {
|
|
10
10
|
return [];
|
|
11
11
|
}
|
|
12
|
-
|
|
12
|
+
return 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
|
-
});
|
|
115
15
|
}
|
|
116
16
|
|
|
117
17
|
export function generateSlotMetaMap(componentSchema, context, options = {}) {
|
|
@@ -136,10 +36,14 @@ export function generateSlotMetaMap(componentSchema, context, options = {}) {
|
|
|
136
36
|
node: isHOC
|
|
137
37
|
? (props) => {
|
|
138
38
|
let clonedScopeContext = _.cloneDeep(scopeContext);
|
|
139
|
-
_.set(
|
|
39
|
+
_.set(
|
|
40
|
+
clonedScopeContext,
|
|
41
|
+
`${componentSchema.key}.${child.key}`,
|
|
42
|
+
props
|
|
43
|
+
);
|
|
140
44
|
return (
|
|
141
45
|
<AppRender
|
|
142
|
-
key={key}
|
|
46
|
+
key={child.key}
|
|
143
47
|
componentSchema={child}
|
|
144
48
|
renderSlot={options?.renderSlot}
|
|
145
49
|
virtualFields={virtualFields}
|
|
@@ -154,7 +58,7 @@ export function generateSlotMetaMap(componentSchema, context, options = {}) {
|
|
|
154
58
|
return (
|
|
155
59
|
<ForContext.Provider value={forContext}>
|
|
156
60
|
<AppRender
|
|
157
|
-
key={key}
|
|
61
|
+
key={child.key}
|
|
158
62
|
componentSchema={child}
|
|
159
63
|
renderSlot={options?.renderSlot}
|
|
160
64
|
virtualFields={virtualFields}
|
|
@@ -172,10 +76,89 @@ export function generateSlotMetaMap(componentSchema, context, options = {}) {
|
|
|
172
76
|
return slots;
|
|
173
77
|
}
|
|
174
78
|
|
|
175
|
-
export
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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
|
+
}
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import config from '../../datasources/config'
|
|
2
|
+
import { getTcbInstance, getAccessToken } from '@cloudbase/weda-cloud-sdk/dist/h5';
|
|
3
|
+
|
|
4
|
+
async function loginScope() {
|
|
5
|
+
const { auth } = await getTcbInstance();
|
|
6
|
+
return auth.loginScope();
|
|
7
|
+
}
|
|
8
|
+
|
|
2
9
|
export function getComponentId(key) {
|
|
3
10
|
return `__weapps-component-wrapper-${key}`;
|
|
4
11
|
}
|
|
@@ -77,7 +84,7 @@ export function resolveComponentProps(props, isPlainProps) {
|
|
|
77
84
|
...props,
|
|
78
85
|
};
|
|
79
86
|
}
|
|
80
|
-
const { data = {}, events = [],
|
|
87
|
+
const { data = {}, events = [], ...restProps } = props;
|
|
81
88
|
const customProps = { ...data };
|
|
82
89
|
const builtinProps = [
|
|
83
90
|
// react 保留字
|
|
@@ -141,63 +148,159 @@ export function getStaticResourceAttribute(staticUrl) {
|
|
|
141
148
|
}
|
|
142
149
|
return staticUrl;
|
|
143
150
|
}
|
|
151
|
+
|
|
152
|
+
export function findLoginPage(app = window.app) {
|
|
153
|
+
const { pages = [] } = app.utils._getConfig();
|
|
154
|
+
return pages.find(item => item.type === 'login');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
let _AUTH_CONFIG_CACHE = null;
|
|
158
|
+
async function getAuthConfig(app = window.app) {
|
|
159
|
+
if (_AUTH_CONFIG_CACHE) {
|
|
160
|
+
return _AUTH_CONFIG_CACHE;
|
|
161
|
+
}
|
|
162
|
+
try {
|
|
163
|
+
const res = await app.cloud.callWedaApi({
|
|
164
|
+
action: "DescribeRuntimeResourceStrategy",
|
|
165
|
+
data: {
|
|
166
|
+
ResourceType: `<%= isAdminPortal? 'modelApp' : 'app'%>`,
|
|
167
|
+
ResourceId: app.id,
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
const settingData = {};
|
|
171
|
+
// 云api不支持map只能传字符串,需要转换
|
|
172
|
+
res.forEach((item) => {
|
|
173
|
+
settingData[item.Key] = ['AllowRegister', 'NeedLogin'].includes(item.Key) ? item.Value === '1' : item.Value;
|
|
174
|
+
});
|
|
175
|
+
_AUTH_CONFIG_CACHE = settingData;
|
|
176
|
+
return _AUTH_CONFIG_CACHE;
|
|
177
|
+
} catch (e) {
|
|
178
|
+
return {
|
|
179
|
+
NeedLogin: false,
|
|
180
|
+
RejectStrategy: "show_warning",
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
let _AUTH_CACHE_MAP = {}
|
|
186
|
+
async function getAccessPermission(app, appId, pageId) {
|
|
187
|
+
const cacheKey = `${appId}-${pageId}`
|
|
188
|
+
if (_AUTH_CACHE_MAP[cacheKey] !== undefined) {
|
|
189
|
+
return _AUTH_CACHE_MAP[cacheKey];
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
let isAccess = false;
|
|
193
|
+
try {
|
|
194
|
+
const res = await app.cloud.callWedaApi({
|
|
195
|
+
action: 'DescribeResourcesPermission',
|
|
196
|
+
data: {
|
|
197
|
+
ResourceType: `<%= isAdminPortal? 'modelApp' : 'app'%>`,
|
|
198
|
+
ResourceIdList: [cacheKey],
|
|
199
|
+
AppResourceId: appId,
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
if (Array.isArray(res) && res.length > 0) {
|
|
203
|
+
isAccess = !!res[0].IsAccess;
|
|
204
|
+
}
|
|
205
|
+
_AUTH_CACHE_MAP[cacheKey] = isAccess;
|
|
206
|
+
} catch (e) {
|
|
207
|
+
console.warn('getAccessPermission', e);
|
|
208
|
+
}
|
|
209
|
+
return isAccess
|
|
210
|
+
}
|
|
211
|
+
|
|
144
212
|
/**
|
|
145
213
|
* 检查页面权限
|
|
146
214
|
**/
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
return _AUTH_CACHE_MAP[cacheKey]
|
|
215
|
+
export async function checkAuth(app, appId, $page) {
|
|
216
|
+
<% if (isAdminPortal || isXPage) { %>return true;<% } %>
|
|
217
|
+
const loginPage = findLoginPage(app);
|
|
218
|
+
if (loginPage?.id === $page.id) {
|
|
219
|
+
return true
|
|
153
220
|
}
|
|
154
221
|
app.showNavigationBarLoading();
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
ResourceIdList: [cacheKey],
|
|
160
|
-
},
|
|
161
|
-
});
|
|
162
|
-
let isLogin = false;
|
|
163
|
-
if (Array.isArray(checkAuthResult) && checkAuthResult.length > 0) {
|
|
164
|
-
isLogin = checkAuthResult[0]?.IsAccess ?? false;
|
|
222
|
+
const requestList = [getAccessPermission(app, appId, $page.id)];
|
|
223
|
+
// 暂时先认为有登录页则自定义登录功能开启且生效
|
|
224
|
+
if (loginPage) {
|
|
225
|
+
requestList.push(getAuthConfig(app));
|
|
165
226
|
}
|
|
227
|
+
const [isAccess, authConfig] = await Promise.all(requestList);
|
|
166
228
|
app.hideNavigationBarLoading();
|
|
167
229
|
|
|
168
|
-
if (!
|
|
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);
|
|
248
|
+
redirectToLogin($page);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return isAccess;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export function redirectToLogin(currentPage) {
|
|
255
|
+
// 去登录则清空权限缓存。
|
|
256
|
+
_AUTH_CACHE_MAP = {};
|
|
257
|
+
const app = window.app;
|
|
258
|
+
const loginPage = findLoginPage(app);
|
|
259
|
+
if (!currentPage) {
|
|
260
|
+
currentPage = app.utils.getCurrentPage() || {};
|
|
261
|
+
}
|
|
262
|
+
if (loginPage?.id === currentPage.id) {
|
|
263
|
+
return true
|
|
264
|
+
}
|
|
265
|
+
if (loginPage) {
|
|
266
|
+
app.redirectTo({
|
|
267
|
+
pageId: loginPage.id,
|
|
268
|
+
params: {
|
|
269
|
+
sourcePageId: currentPage.id,
|
|
270
|
+
sourcePageParams: currentPage.dataset.params
|
|
271
|
+
}
|
|
272
|
+
})
|
|
273
|
+
} else {
|
|
169
274
|
app.showToast({
|
|
170
|
-
title: '
|
|
275
|
+
title: '用户未登录',
|
|
171
276
|
icon: 'error',
|
|
172
277
|
});
|
|
173
278
|
}
|
|
174
|
-
_AUTH_CACHE_MAP[cacheKey] = isLogin
|
|
175
|
-
return isLogin;
|
|
176
279
|
}
|
|
177
280
|
|
|
178
281
|
const _REPORTED = {}
|
|
179
|
-
export function reportTime(tag, time, only=false){
|
|
180
|
-
if(!window._aegis || !tag){
|
|
282
|
+
export function reportTime(tag, time, only = false) {
|
|
283
|
+
if (!window._aegis || !tag) {
|
|
181
284
|
return;
|
|
182
285
|
}
|
|
183
|
-
if(window['_WedaHostConfig'] && !window['_WedaHostConfig']['_REPORTED']) {
|
|
286
|
+
if (window['_WedaHostConfig'] && !window['_WedaHostConfig']['_REPORTED']) {
|
|
184
287
|
window['_WedaHostConfig']['_REPORTED'] = _REPORTED
|
|
185
288
|
}
|
|
186
289
|
|
|
187
290
|
const CACHE_MAP = window['_WedaHostConfig']?.['_REPORTED'] || _REPORTED
|
|
188
291
|
|
|
189
|
-
if(only && CACHE_MAP[tag]){
|
|
190
|
-
return
|
|
292
|
+
if (only && CACHE_MAP[tag]) {
|
|
293
|
+
return;
|
|
191
294
|
}
|
|
192
295
|
CACHE_MAP[tag] = true
|
|
193
296
|
try {
|
|
194
|
-
let t = time === undefined? (performance?.now?.() || Date.now() - window['_aegis_inited']) :time;
|
|
297
|
+
let t = time === undefined ? (performance?.now?.() || Date.now() - window['_aegis_inited']) : time;
|
|
195
298
|
window._aegis.reportTime({
|
|
196
299
|
name: tag,
|
|
197
300
|
duration: t,
|
|
198
|
-
ext2: config.isProd? 'production' : 'preview',
|
|
301
|
+
ext2: config.isProd ? 'production' : 'preview',
|
|
199
302
|
})
|
|
200
|
-
}catch(e){
|
|
303
|
+
} catch (e) {
|
|
201
304
|
console.log(e)
|
|
202
305
|
}
|
|
203
306
|
}
|
package/template/src/index.jsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
2
|
import * as ReactDOM from 'react-dom'
|
|
3
|
-
import { setConfig } from '@cloudbase/weda-cloud-sdk/dist/h5'
|
|
3
|
+
import { setConfig, getAccessToken, initTcb } from '@cloudbase/weda-cloud-sdk/dist/h5'
|
|
4
4
|
import App from './router'
|
|
5
5
|
import './utils/monitor-jssdk.min'
|
|
6
6
|
import './index.less'
|
|
@@ -12,6 +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
16
|
// app 中注册配置页面以及app的全局配置miniprogram.config,h5里分app以及web页分别处理,使用process.env.isApp 区分判断
|
|
16
17
|
if (process.env.isApp) {
|
|
17
18
|
initWebConfig(app, AppConfig);
|
|
@@ -23,12 +24,55 @@ setConfig({
|
|
|
23
24
|
if (!cfg.options || !cfg.options.showLoading) return
|
|
24
25
|
app.showLoading()
|
|
25
26
|
},
|
|
27
|
+
beforeCallFunction: async (params) => {
|
|
28
|
+
try{
|
|
29
|
+
const loginPage = findLoginPage();
|
|
30
|
+
|
|
31
|
+
let skip = false;
|
|
32
|
+
switch (params?.data?.methodName) {
|
|
33
|
+
case 'callWedaApi': {
|
|
34
|
+
if(['GetMiniProgramUserTicket', 'DescribeRuntimeResourceStrategy'].includes(params?.data?.params.action)){
|
|
35
|
+
skip = true;
|
|
36
|
+
}
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// 后续做过滤处理
|
|
42
|
+
if (!loginPage || (params?.data?.mode === 'c' && skip)) {
|
|
43
|
+
return params;
|
|
44
|
+
}
|
|
45
|
+
const { accessToken } = await getAccessToken();
|
|
46
|
+
if (accessToken) {
|
|
47
|
+
params.data.accessToken = accessToken;
|
|
48
|
+
}
|
|
49
|
+
} catch (e) {
|
|
50
|
+
console.error('beforeCallFunction error', e);
|
|
51
|
+
}
|
|
52
|
+
return params;
|
|
53
|
+
},
|
|
26
54
|
afterDSRequest: (cfg, error, result) => {
|
|
27
55
|
if (!cfg.options) return
|
|
28
56
|
if (cfg.options.showLoading) app.hideLoading()
|
|
29
57
|
if (!cfg.options.showToast) return
|
|
30
58
|
const isSuccess = !error && result && !result.code
|
|
31
59
|
app.showToast({icon: isSuccess ? 'success' : 'error'})
|
|
60
|
+
},
|
|
61
|
+
async afterCallFunction(params, error, res) {
|
|
62
|
+
if(params?.data?.params?.action != 'DescribeRuntimeResourceStrategy' && ['InnerError.AuthFailure','InvalidAccessToken'].includes(res?.result?.code)) {
|
|
63
|
+
const loginPage = findLoginPage();
|
|
64
|
+
if (loginPage) {
|
|
65
|
+
const authConfig = await getAuthConfig();
|
|
66
|
+
if (authConfig.NeedLogin || authConfig.RejectStrategy == 'to_login') {
|
|
67
|
+
redirectToLogin();
|
|
68
|
+
} else if (authConfig.RejectStrategy == 'show_warning') {
|
|
69
|
+
app.showToast({
|
|
70
|
+
title: '接口无访问权限',
|
|
71
|
+
icon: 'error',
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
32
76
|
}
|
|
33
77
|
})
|
|
34
78
|
// window.app.yyptReport = window.yyptReport
|
|
@@ -78,24 +78,37 @@ initLifeCycle({
|
|
|
78
78
|
export default function App() {
|
|
79
79
|
// 检查权限
|
|
80
80
|
const [weDaHasLogin, setWeDaHasLogin] = React.useState(false);
|
|
81
|
-
const
|
|
82
|
-
const context = dataContextRef.current;
|
|
81
|
+
const context = React.useRef(observable({})).current;
|
|
83
82
|
const containerRef = React.useRef(null);
|
|
84
83
|
const microApp = React.useRef(null);
|
|
85
84
|
const pureSrc = '<%= pageSource %>';
|
|
86
85
|
const isPure = !!pureSrc;
|
|
87
86
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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
|
+
}
|
|
93
106
|
|
|
107
|
+
React.useEffect(() => {
|
|
94
108
|
Object.assign($page, {
|
|
95
109
|
id: '<%= pageName %>',
|
|
96
110
|
state: observable(initPageState),
|
|
97
111
|
computed: createComputed(computed),
|
|
98
|
-
// _context: context,
|
|
99
112
|
handler,
|
|
100
113
|
});
|
|
101
114
|
|
|
@@ -107,6 +120,12 @@ export default function App() {
|
|
|
107
120
|
app.utils.set($page.dataset.state, keyPath, userSetState[keyPath]);
|
|
108
121
|
});
|
|
109
122
|
};
|
|
123
|
+
|
|
124
|
+
checkAuth(app, app.id, $page).then((checkAuthResult) => {
|
|
125
|
+
setWeDaHasLogin(checkAuthResult)
|
|
126
|
+
reportTime('FIRST_PAGE_CONTENT_RENDERED', undefined, true)
|
|
127
|
+
});
|
|
128
|
+
|
|
110
129
|
return () => {
|
|
111
130
|
if (microApp.current) {
|
|
112
131
|
microApp.current.unmount();
|
|
@@ -115,10 +134,10 @@ export default function App() {
|
|
|
115
134
|
}, []);
|
|
116
135
|
|
|
117
136
|
React.useEffect(() => {
|
|
118
|
-
$page.widgets = createWidgets(widgetsContext, dataBinds, {},
|
|
137
|
+
$page.widgets = createWidgets(widgetsContext, dataBinds, {}, context);
|
|
119
138
|
// widgets 内的 dataBinds 可能需要关联 widgets,需要重新执行 dataBinds
|
|
120
139
|
retryDataBinds();
|
|
121
|
-
}, [
|
|
140
|
+
}, [context]);
|
|
122
141
|
|
|
123
142
|
// Web 环境页面级别生命周期
|
|
124
143
|
if (!process.env.isMiniprogram) {
|
|
@@ -160,27 +179,8 @@ export default function App() {
|
|
|
160
179
|
<AppRender pageListenerInstances={pageListenerInstances}
|
|
161
180
|
virtualFields={virtualFields}
|
|
162
181
|
componentSchema={componentSchema}
|
|
163
|
-
context={
|
|
164
|
-
|
|
165
|
-
* 更新数据容器的上下文的方法
|
|
166
|
-
* 会传递到事件emit的地方,将从组件获取到的数据data赋值给上下文
|
|
167
|
-
* 当组件卸载时,传过来的data为undefined即可
|
|
168
|
-
* {
|
|
169
|
-
* id1: [{...}],
|
|
170
|
-
* id2: {...},
|
|
171
|
-
* id3: undefined,
|
|
172
|
-
* id4: null,
|
|
173
|
-
* ...
|
|
174
|
-
* }
|
|
175
|
-
* @param id
|
|
176
|
-
* @param data
|
|
177
|
-
*/
|
|
178
|
-
updateContext={(id, data) => {
|
|
179
|
-
if (id) {
|
|
180
|
-
dataContextRef.current[id] = { data };
|
|
181
|
-
// console.log('111', context[id])
|
|
182
|
-
}
|
|
183
|
-
}}
|
|
182
|
+
context={context}
|
|
183
|
+
updateContext={updateContext}
|
|
184
184
|
/>
|
|
185
185
|
)}
|
|
186
186
|
</div>
|
|
@@ -1,42 +0,0 @@
|
|
|
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
|
-
}
|