@lark-apaas/fullstack-rspack-preset 1.0.7 → 1.0.8-alpha.log.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/lib/overlay/components.d.ts +2 -9
- package/lib/overlay/components.js +23 -103
- package/lib/overlay/index.js +69 -85
- package/package.json +1 -1
|
@@ -2,14 +2,7 @@
|
|
|
2
2
|
* 错误容器组件
|
|
3
3
|
* @param {*} document
|
|
4
4
|
* @param {*} root
|
|
5
|
-
* @param {
|
|
6
|
-
* @param {string} props.errorMessage - 错误信息
|
|
7
|
-
* @param {function} props.onRepairClick - 修复按钮点击事件
|
|
8
|
-
* @param {function} props.onCopyClick - 复制按钮点击事件
|
|
5
|
+
* @param {string} errorTitle 错误标题
|
|
9
6
|
*/
|
|
10
|
-
export function ErrorContainer(document: any, root: any,
|
|
11
|
-
errorMessage: string;
|
|
12
|
-
onRepairClick: Function;
|
|
13
|
-
onCopyClick: Function;
|
|
14
|
-
}): void;
|
|
7
|
+
export function ErrorContainer(document: any, root: any, errorTitle: string): void;
|
|
15
8
|
export function RootStyle(document: any, root: any): void;
|
|
@@ -3,57 +3,31 @@
|
|
|
3
3
|
* 错误容器组件
|
|
4
4
|
* @param {*} document
|
|
5
5
|
* @param {*} root
|
|
6
|
-
* @param {
|
|
7
|
-
* @param {string} props.errorMessage - 错误信息
|
|
8
|
-
* @param {function} props.onRepairClick - 修复按钮点击事件
|
|
9
|
-
* @param {function} props.onCopyClick - 复制按钮点击事件
|
|
6
|
+
* @param {string} errorTitle 错误标题
|
|
10
7
|
*/
|
|
11
|
-
function ErrorContainer(document, root,
|
|
8
|
+
function ErrorContainer(document, root, errorTitle) {
|
|
12
9
|
// 创建容器元素
|
|
13
10
|
const container = document.createElement('div');
|
|
14
|
-
container.className = 'container';
|
|
11
|
+
container.className = 'overlay-container';
|
|
15
12
|
// 创建内容元素
|
|
16
13
|
const content = document.createElement('div');
|
|
17
|
-
content.className = 'content';
|
|
14
|
+
content.className = 'overlay-content';
|
|
18
15
|
container.appendChild(content);
|
|
19
16
|
// 创建图片元素
|
|
20
17
|
const img = document.createElement('img');
|
|
21
18
|
img.src =
|
|
22
19
|
'https://lf3-static.bytednsdoc.com/obj/eden-cn/ylcylz_fsph_ryhs/ljhwZthlaukjlkulzlp/feisuda/template/render_error.svg';
|
|
23
|
-
img.alt = '
|
|
20
|
+
img.alt = 'Error';
|
|
24
21
|
// 图片占位
|
|
25
|
-
img.width =
|
|
26
|
-
img.height =
|
|
27
|
-
img.className = 'error-image';
|
|
22
|
+
img.width = 200;
|
|
23
|
+
img.height = 200;
|
|
24
|
+
img.className = 'overlay-error-image';
|
|
28
25
|
content.appendChild(img);
|
|
29
26
|
// 创建标题元素
|
|
30
27
|
const title = document.createElement('p');
|
|
31
|
-
title.className = 'title';
|
|
32
|
-
title.textContent =
|
|
28
|
+
title.className = 'overlay-title';
|
|
29
|
+
title.textContent = errorTitle;
|
|
33
30
|
content.appendChild(title);
|
|
34
|
-
// 创建描述元素
|
|
35
|
-
const description = document.createElement('p');
|
|
36
|
-
description.className = 'description';
|
|
37
|
-
description.textContent = '可复制错误信息,或告诉妙搭进行修复。';
|
|
38
|
-
content.appendChild(description);
|
|
39
|
-
// 创建按钮组元素
|
|
40
|
-
const buttonGroup = document.createElement('div');
|
|
41
|
-
buttonGroup.className = 'button-group';
|
|
42
|
-
content.appendChild(buttonGroup);
|
|
43
|
-
// 创建复制按钮
|
|
44
|
-
const copyBtn = document.createElement('button');
|
|
45
|
-
copyBtn.className = 'button button-copy';
|
|
46
|
-
copyBtn.id = 'copyBtn';
|
|
47
|
-
copyBtn.textContent = '复制错误信息';
|
|
48
|
-
copyBtn.addEventListener('click', props.onCopyClick);
|
|
49
|
-
buttonGroup.appendChild(copyBtn);
|
|
50
|
-
// 创建修复按钮
|
|
51
|
-
const repairBtn = document.createElement('button');
|
|
52
|
-
repairBtn.className = 'button button-repair';
|
|
53
|
-
repairBtn.id = 'repairBtn';
|
|
54
|
-
repairBtn.textContent = '告诉妙搭修复';
|
|
55
|
-
repairBtn.addEventListener('click', props.onRepairClick);
|
|
56
|
-
buttonGroup.appendChild(repairBtn);
|
|
57
31
|
// 添加到根元素
|
|
58
32
|
root.appendChild(container);
|
|
59
33
|
}
|
|
@@ -68,22 +42,22 @@ function RootStyle(document, root) {
|
|
|
68
42
|
}
|
|
69
43
|
|
|
70
44
|
body {
|
|
71
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
45
|
+
font-family: "PingFang SC", -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
72
46
|
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
73
47
|
sans-serif;
|
|
74
48
|
-webkit-font-smoothing: antialiased;
|
|
75
49
|
-moz-osx-font-smoothing: grayscale;
|
|
76
50
|
}
|
|
77
51
|
|
|
78
|
-
.container {
|
|
52
|
+
.overlay-container {
|
|
79
53
|
min-height: 100vh;
|
|
80
54
|
display: flex;
|
|
81
55
|
align-items: center;
|
|
82
56
|
justify-content: center;
|
|
83
|
-
background-color: #
|
|
57
|
+
background-color: #fff;
|
|
84
58
|
}
|
|
85
59
|
|
|
86
|
-
.content {
|
|
60
|
+
.overlay-content {
|
|
87
61
|
display: flex;
|
|
88
62
|
flex-direction: column;
|
|
89
63
|
justify-content: center;
|
|
@@ -91,75 +65,21 @@ function RootStyle(document, root) {
|
|
|
91
65
|
text-align: center;
|
|
92
66
|
}
|
|
93
67
|
|
|
94
|
-
.error-image {
|
|
95
|
-
margin-bottom:
|
|
96
|
-
width:
|
|
68
|
+
.overlay-error-image {
|
|
69
|
+
margin-bottom: 12px; /* mb-3 */
|
|
70
|
+
width: 200px; /* w-[200px] */
|
|
97
71
|
height: auto;
|
|
98
72
|
}
|
|
99
73
|
|
|
100
|
-
.title {
|
|
101
|
-
font-size: 18px; /* text-l (推测为 text-lg) */
|
|
102
|
-
line-height: 22px;
|
|
74
|
+
.overlay-title {
|
|
103
75
|
color: #1F2329;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
font-size: 14px; /* text-sm */
|
|
110
|
-
line-height: 22px;
|
|
111
|
-
color: #646A73;
|
|
112
|
-
font-weight: 400; /* font-normal */
|
|
113
|
-
margin-bottom: 8px; /* mb-2 */
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
.button-group {
|
|
117
|
-
display: flex;
|
|
118
|
-
gap: 16px; /* space-x-4 */
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
.button {
|
|
122
|
-
height: 32px; /* h-[32px] */
|
|
123
|
-
padding: 0 16px;
|
|
124
|
-
border-radius: 6px; /* rounded-[6px] */
|
|
125
|
-
font-size: 14px; /* text-sm */
|
|
126
|
-
font-weight: 400; /* font-[400] */
|
|
127
|
-
cursor: pointer;
|
|
128
|
-
transition: all 0.2s;
|
|
129
|
-
outline: none; /* focus:outline-hidden */
|
|
130
|
-
border: 1px solid;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
.button-copy {
|
|
134
|
-
background-color: white; /* bg-white */
|
|
135
|
-
color: #4B5563; /* text-gray-600 */
|
|
136
|
-
border-color: #D0D3D6; /* border-[#D0D3D6] */
|
|
137
|
-
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); /* shadow-xs */
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
.button-copy:hover {
|
|
141
|
-
background-color: #F3F4F6; /* hover:bg-gray-100 */
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
.button-copy:active {
|
|
145
|
-
background-color: #E5E7EB; /* active:bg-gray-200 */
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
.button-repair {
|
|
149
|
-
background-color: #2563EB; /* bg-blue-600 */
|
|
150
|
-
color: white; /* text-white */
|
|
151
|
-
border-color: transparent; /* border-transparent */
|
|
152
|
-
font-weight: 500; /* font-medium */
|
|
153
|
-
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); /* shadow-xs */
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
.button-repair:hover {
|
|
157
|
-
background-color: #2563EB; /* hover:bg-blue-600 (保持不变) */
|
|
76
|
+
text-align: center;
|
|
77
|
+
font-size: 14px;
|
|
78
|
+
font-style: normal;
|
|
79
|
+
font-weight: 500;
|
|
80
|
+
line-height: 22px;
|
|
158
81
|
}
|
|
159
82
|
|
|
160
|
-
.button-repair:active {
|
|
161
|
-
background-color: #1E40AF; /* active:bg-blue-700 */
|
|
162
|
-
}
|
|
163
83
|
`;
|
|
164
84
|
root.appendChild(style);
|
|
165
85
|
}
|
package/lib/overlay/index.js
CHANGED
|
@@ -64,9 +64,14 @@ function IframeRoot(document, root, props) {
|
|
|
64
64
|
iframe.style.width = '100vw';
|
|
65
65
|
iframe.style.zIndex = '2147483647';
|
|
66
66
|
iframe.addEventListener('load', function onLoad() {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
try {
|
|
68
|
+
// Reset margin of iframe body
|
|
69
|
+
iframe.contentDocument.body.style.margin = '0';
|
|
70
|
+
props.onIframeLoad();
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
console.error('Error during iframe load:', error);
|
|
74
|
+
}
|
|
70
75
|
});
|
|
71
76
|
// We skip mounting and returns as we need to ensure
|
|
72
77
|
// the load event is fired after we setup the global variable
|
|
@@ -124,52 +129,6 @@ function removeAllChildren(element, skip) {
|
|
|
124
129
|
element.removeChild(childList[i]);
|
|
125
130
|
}
|
|
126
131
|
}
|
|
127
|
-
/**
|
|
128
|
-
* 降级复制方案(兼容旧浏览器)
|
|
129
|
-
* @param text 要复制的文本
|
|
130
|
-
* @returns boolean 复制是否成功
|
|
131
|
-
*/
|
|
132
|
-
function fallbackCopyToClipboard(text) {
|
|
133
|
-
try {
|
|
134
|
-
// 创建临时的 textarea 元素
|
|
135
|
-
const textArea = document.createElement('textarea');
|
|
136
|
-
textArea.value = text;
|
|
137
|
-
// 设置样式,使其不可见
|
|
138
|
-
textArea.style.position = 'fixed';
|
|
139
|
-
textArea.style.left = '-999999px';
|
|
140
|
-
textArea.style.top = '-999999px';
|
|
141
|
-
textArea.setAttribute('readonly', '');
|
|
142
|
-
// 添加到 DOM
|
|
143
|
-
document.body.appendChild(textArea);
|
|
144
|
-
// 选中文本
|
|
145
|
-
textArea.focus();
|
|
146
|
-
textArea.select();
|
|
147
|
-
// 执行复制命令
|
|
148
|
-
const successful = document.execCommand('copy');
|
|
149
|
-
// 清理:移除临时元素
|
|
150
|
-
document.body.removeChild(textArea);
|
|
151
|
-
return successful;
|
|
152
|
-
}
|
|
153
|
-
catch (error) {
|
|
154
|
-
console.error('降级复制方案失败:', error);
|
|
155
|
-
return false;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
async function copyToClipboard(text) {
|
|
159
|
-
try {
|
|
160
|
-
// 优先使用现代的 Clipboard API
|
|
161
|
-
if (navigator.clipboard && window.isSecureContext) {
|
|
162
|
-
await navigator.clipboard.writeText(text);
|
|
163
|
-
return true;
|
|
164
|
-
}
|
|
165
|
-
// 降级方案:使用传统的 execCommand 方法
|
|
166
|
-
return fallbackCopyToClipboard(text);
|
|
167
|
-
}
|
|
168
|
-
catch (error) {
|
|
169
|
-
// 执行navigator.clipboard.writeText失败时,降级方案
|
|
170
|
-
return fallbackCopyToClipboard(text);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
132
|
// 获取父窗口 origin
|
|
174
133
|
function getPreviewParentOrigin() {
|
|
175
134
|
const { origin } = window.location;
|
|
@@ -186,6 +145,56 @@ function getPreviewParentOrigin() {
|
|
|
186
145
|
// BOE 环境
|
|
187
146
|
return 'https://miaoda.feishu-boe.cn';
|
|
188
147
|
}
|
|
148
|
+
function sendPostMessage(message, targetOrigin) {
|
|
149
|
+
try {
|
|
150
|
+
const origin = targetOrigin || getPreviewParentOrigin();
|
|
151
|
+
window.parent.postMessage(message, origin);
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
console.error('ReactRefreshPlugin overlay发送 postMessage 失败:', error);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* 上报错误信息
|
|
159
|
+
* @param {(string | Error)[]} messages 日志信息
|
|
160
|
+
* @param {boolean} noStacktrace 是否移除堆栈信息
|
|
161
|
+
*/
|
|
162
|
+
function logError(messages, noStacktrace = false) {
|
|
163
|
+
try {
|
|
164
|
+
// 优先使用暴露的 __RUNTIME_LOGGER__ 上报错误
|
|
165
|
+
// 运行时错误出现时,window已经挂载
|
|
166
|
+
if (window.__RUNTIME_LOGGER__) {
|
|
167
|
+
window.__RUNTIME_LOGGER__.get().log({
|
|
168
|
+
level: 'error',
|
|
169
|
+
args: messages,
|
|
170
|
+
meta: {
|
|
171
|
+
noStacktrace,
|
|
172
|
+
stacktrace: noStacktrace ? [] : undefined,
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
// 首次执行编译报错会走此处逻辑;
|
|
178
|
+
const logJSON = {
|
|
179
|
+
id: 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
180
|
+
const r = Math.random() * 16 | 0;
|
|
181
|
+
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
|
182
|
+
return v.toString(16);
|
|
183
|
+
}),
|
|
184
|
+
type: 'typedLogV2',
|
|
185
|
+
level: 'error',
|
|
186
|
+
args: messages.map(item => item instanceof Error ? `${item.message}\n${item.stack}\n` : item),
|
|
187
|
+
meta: {
|
|
188
|
+
noStacktrace,
|
|
189
|
+
stacktrace: noStacktrace ? [] : undefined,
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
sendPostMessage({ type: 'SELECTED_LOG', payload: logJSON });
|
|
193
|
+
}
|
|
194
|
+
catch (e) {
|
|
195
|
+
console.log('上报错误信息失败', e);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
189
198
|
/**
|
|
190
199
|
* Creates the main `div` element for the overlay to render.
|
|
191
200
|
* @returns {void}
|
|
@@ -193,57 +202,32 @@ function getPreviewParentOrigin() {
|
|
|
193
202
|
function render() {
|
|
194
203
|
ensureRootExists(function () {
|
|
195
204
|
removeAllChildren(root);
|
|
196
|
-
// 发送 postMessage
|
|
197
|
-
const sendPostMessage = (message, targetOrigin) => {
|
|
198
|
-
const origin = targetOrigin || getPreviewParentOrigin();
|
|
199
|
-
window.parent.postMessage(message, origin);
|
|
200
|
-
};
|
|
201
205
|
// 通知前端,渲染错误页面已准备就绪
|
|
202
206
|
sendPostMessage({
|
|
203
|
-
type: 'PreviewReady'
|
|
207
|
+
type: 'PreviewReady',
|
|
204
208
|
});
|
|
205
209
|
// 通知主应用存在自定义 overlay
|
|
206
210
|
sendPostMessage({
|
|
207
211
|
type: 'app-features',
|
|
208
|
-
payload: [
|
|
212
|
+
payload: [
|
|
213
|
+
{
|
|
209
214
|
feature: 'error-overlay',
|
|
210
215
|
enable: true,
|
|
211
|
-
}
|
|
216
|
+
},
|
|
217
|
+
],
|
|
212
218
|
});
|
|
213
219
|
if (currentCompileErrorMessage) {
|
|
214
220
|
currentMode = 'compileError';
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
sendPostMessage({
|
|
219
|
-
type: 'RenderErrorRepair',
|
|
220
|
-
data: currentCompileErrorMessage,
|
|
221
|
-
});
|
|
222
|
-
},
|
|
223
|
-
onCopyClick: function onCopyClick() {
|
|
224
|
-
copyToClipboard(currentCompileErrorMessage);
|
|
225
|
-
},
|
|
226
|
-
});
|
|
221
|
+
// 发送编译错误
|
|
222
|
+
logError(['Compile Error', currentCompileErrorMessage], true);
|
|
223
|
+
ErrorContainer(rootDocument, root, '编译出错');
|
|
227
224
|
}
|
|
228
225
|
else if (currentRuntimeErrors.length) {
|
|
229
226
|
currentMode = 'runtimeError';
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
errors += `${error.message}\n${error.stack}\n`;
|
|
233
|
-
});
|
|
227
|
+
// 发送运行错误
|
|
228
|
+
logError(['Uncaught Render Error', currentRuntimeErrors]);
|
|
234
229
|
// 叠加全部报错,将报错信息发送到妙搭
|
|
235
|
-
ErrorContainer(rootDocument, root,
|
|
236
|
-
errorMessage: errors,
|
|
237
|
-
onRepairClick: function onRepairClick() {
|
|
238
|
-
sendPostMessage({
|
|
239
|
-
type: 'RenderErrorRepair',
|
|
240
|
-
data: errors,
|
|
241
|
-
});
|
|
242
|
-
},
|
|
243
|
-
onCopyClick: function onCopyClick() {
|
|
244
|
-
copyToClipboard(errors);
|
|
245
|
-
},
|
|
246
|
-
});
|
|
230
|
+
ErrorContainer(rootDocument, root, '哎呀,出错了');
|
|
247
231
|
}
|
|
248
232
|
});
|
|
249
233
|
}
|