@4399ywkf/cli 1.0.7 → 1.0.8
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/dist/templates/HarmonyOS_Sans_Bold.woff2 +0 -0
- package/dist/templates/HarmonyOS_Sans_Medium.woff2 +0 -0
- package/dist/templates/HarmonyOS_Sans_Regular.woff2 +0 -0
- package/dist/templates/Locale.tsx +14 -18
- package/dist/templates/MainContentWrap.tsx +11 -15
- package/dist/templates/ThemeContext.tsx +27 -24
- package/dist/templates/app/config/env/.env.public.tpl +2 -19
- package/dist/templates/app/config/jwt/index.ts +4 -4
- package/dist/templates/app/config/request/error-handler.ts +67 -0
- package/dist/templates/app/config/request/index.ts +127 -129
- package/dist/templates/app/config/request/interceptors.ts +118 -0
- package/dist/templates/app/config/request/token-manager.ts +23 -0
- package/dist/templates/app/config/request/types.ts +63 -0
- package/dist/templates/app/config/rspack/rspack.config.mjs +62 -61
- package/dist/templates/app/config/rspack/rspack.prod.mjs +41 -62
- package/dist/templates/app/locales/zh-CN/common.json +3 -0
- package/dist/templates/app/package.json.tpl +1 -10
- package/dist/templates/app/public/fonts/HarmonyOS_Sans_Bold.woff2 +0 -0
- package/dist/templates/app/public/fonts/HarmonyOS_Sans_Medium.woff2 +0 -0
- package/dist/templates/app/public/fonts/HarmonyOS_Sans_Regular.woff2 +0 -0
- package/dist/templates/app/react-app-env.d.ts +13 -8
- package/dist/templates/app/src/bootstrap/index.ts +34 -0
- package/dist/templates/app/src/config/env.ts +84 -0
- package/dist/templates/app/src/index.tsx +17 -51
- package/dist/templates/app/src/layout/Locale.tsx +14 -18
- package/dist/templates/app/src/layout/MainContentWrap.tsx +11 -15
- package/dist/templates/app/src/layout/ThemeContext.tsx +27 -24
- package/dist/templates/app/src/locales/default/common.ts +3 -1
- package/dist/templates/app/src/micro/garfish.ts +53 -0
- package/dist/templates/app/src/pages/base/index.tsx +189 -25
- package/dist/templates/app/src/routes.tsx +21 -12
- package/dist/templates/app/src/types/global.d.ts +19 -0
- package/dist/templates/app/src/utils/index.ts +3 -1
- package/dist/templates/app/store/middleware/createDevtools.ts +7 -7
- package/dist/templates/base/index.tsx +189 -25
- package/dist/templates/bootstrap/index.ts +34 -0
- package/dist/templates/common.json +3 -0
- package/dist/templates/common.ts +3 -1
- package/dist/templates/config/env/.env.public.tpl +2 -19
- package/dist/templates/config/env.ts +84 -0
- package/dist/templates/config/jwt/index.ts +4 -4
- package/dist/templates/config/request/error-handler.ts +67 -0
- package/dist/templates/config/request/index.ts +127 -129
- package/dist/templates/config/request/interceptors.ts +118 -0
- package/dist/templates/config/request/token-manager.ts +23 -0
- package/dist/templates/config/request/types.ts +63 -0
- package/dist/templates/config/rspack/rspack.config.mjs +62 -61
- package/dist/templates/config/rspack/rspack.prod.mjs +41 -62
- package/dist/templates/createDevtools.ts +7 -7
- package/dist/templates/default/common.ts +3 -1
- package/dist/templates/env/.env.public.tpl +2 -19
- package/dist/templates/env.ts +83 -2
- package/dist/templates/error-handler.ts +67 -0
- package/dist/templates/fonts/HarmonyOS_Sans_Bold.woff2 +0 -0
- package/dist/templates/fonts/HarmonyOS_Sans_Medium.woff2 +0 -0
- package/dist/templates/fonts/HarmonyOS_Sans_Regular.woff2 +0 -0
- package/dist/templates/garfish.ts +53 -0
- package/dist/templates/global.d.ts +19 -0
- package/dist/templates/index.tsx +189 -25
- package/dist/templates/interceptors.ts +118 -0
- package/dist/templates/jwt/index.ts +4 -4
- package/dist/templates/layout/Locale.tsx +14 -18
- package/dist/templates/layout/MainContentWrap.tsx +11 -15
- package/dist/templates/layout/ThemeContext.tsx +27 -24
- package/dist/templates/locales/default/common.ts +3 -1
- package/dist/templates/locales/zh-CN/common.json +3 -0
- package/dist/templates/micro/garfish.ts +53 -0
- package/dist/templates/middleware/createDevtools.ts +7 -7
- package/dist/templates/package.json.tpl +1 -10
- package/dist/templates/page.tsx +21 -19
- package/dist/templates/pages/base/index.tsx +189 -25
- package/dist/templates/public/fonts/HarmonyOS_Sans_Bold.woff2 +0 -0
- package/dist/templates/public/fonts/HarmonyOS_Sans_Medium.woff2 +0 -0
- package/dist/templates/public/fonts/HarmonyOS_Sans_Regular.woff2 +0 -0
- package/dist/templates/react-app-env.d.ts +13 -8
- package/dist/templates/request/error-handler.ts +67 -0
- package/dist/templates/request/index.ts +127 -129
- package/dist/templates/request/interceptors.ts +118 -0
- package/dist/templates/request/token-manager.ts +23 -0
- package/dist/templates/request/types.ts +63 -0
- package/dist/templates/routes.tsx +21 -12
- package/dist/templates/rspack/rspack.config.mjs +62 -61
- package/dist/templates/rspack/rspack.prod.mjs +41 -62
- package/dist/templates/rspack.config.mjs +62 -61
- package/dist/templates/rspack.prod.mjs +41 -62
- package/dist/templates/src/bootstrap/index.ts +34 -0
- package/dist/templates/src/config/env.ts +84 -0
- package/dist/templates/src/index.tsx +17 -51
- package/dist/templates/src/layout/Locale.tsx +14 -18
- package/dist/templates/src/layout/MainContentWrap.tsx +11 -15
- package/dist/templates/src/layout/ThemeContext.tsx +27 -24
- package/dist/templates/src/locales/default/common.ts +3 -1
- package/dist/templates/src/micro/garfish.ts +53 -0
- package/dist/templates/src/pages/base/index.tsx +189 -25
- package/dist/templates/src/routes.tsx +21 -12
- package/dist/templates/src/types/global.d.ts +19 -0
- package/dist/templates/src/utils/index.ts +3 -1
- package/dist/templates/store/middleware/createDevtools.ts +7 -7
- package/dist/templates/token-manager.ts +23 -0
- package/dist/templates/types/global.d.ts +19 -0
- package/dist/templates/utils/index.ts +3 -1
- package/dist/templates/zh-CN/common.json +3 -0
- package/package.json +1 -1
- package/dist/templates/app/config/sentry/sentry.config.ts +0 -188
- package/dist/templates/app/src/hooks/useRouteTitle.tsx +0 -36
- package/dist/templates/app/src/hooks/useSentry.ts +0 -92
- package/dist/templates/app/src/pages/base/layout.tsx +0 -6
- package/dist/templates/app/src/pages/base/page.tsx +0 -25
- package/dist/templates/app/src/utils/env.ts +0 -3
- package/dist/templates/app/src/utils/format.ts +0 -21
- package/dist/templates/app/src/utils/getMicroApp.ts +0 -39
- package/dist/templates/app/src/utils/sentry.ts +0 -187
- package/dist/templates/app/src/utils/sentryDecorators.ts +0 -34
- package/dist/templates/app/src/utils/updateVersion.ts +0 -186
- package/dist/templates/base/layout.tsx +0 -6
- package/dist/templates/base/page.tsx +0 -25
- package/dist/templates/config/public/404.png +0 -0
- package/dist/templates/config/public/favicon.ico +0 -0
- package/dist/templates/config/public/images/banner_market_modal.webp +0 -0
- package/dist/templates/config/public/images/chatmode_chat_dark.webp +0 -0
- package/dist/templates/config/public/images/chatmode_chat_light.webp +0 -0
- package/dist/templates/config/public/images/chatmode_docs_dark.webp +0 -0
- package/dist/templates/config/public/images/chatmode_docs_light.webp +0 -0
- package/dist/templates/config/public/images/empty_topic_dark.webp +0 -0
- package/dist/templates/config/public/images/empty_topic_light.webp +0 -0
- package/dist/templates/config/public/images/screenshot_background.webp +0 -0
- package/dist/templates/config/public/images/theme_auto.webp +0 -0
- package/dist/templates/config/public/images/theme_dark.webp +0 -0
- package/dist/templates/config/public/images/theme_light.webp +0 -0
- package/dist/templates/config/public/index.html +0 -29
- package/dist/templates/config/sentry/sentry.config.ts +0 -188
- package/dist/templates/format.ts +0 -21
- package/dist/templates/getMicroApp.ts +0 -39
- package/dist/templates/hooks/useRouteTitle.tsx +0 -36
- package/dist/templates/hooks/useSentry.ts +0 -92
- package/dist/templates/layout.tsx +0 -6
- package/dist/templates/pages/base/layout.tsx +0 -6
- package/dist/templates/pages/base/page.tsx +0 -25
- package/dist/templates/sentry/sentry.config.ts +0 -188
- package/dist/templates/sentry.config.ts +0 -188
- package/dist/templates/sentry.ts +0 -187
- package/dist/templates/sentryDecorators.ts +0 -34
- package/dist/templates/src/hooks/useRouteTitle.tsx +0 -36
- package/dist/templates/src/hooks/useSentry.ts +0 -92
- package/dist/templates/src/pages/base/layout.tsx +0 -6
- package/dist/templates/src/pages/base/page.tsx +0 -25
- package/dist/templates/src/utils/env.ts +0 -3
- package/dist/templates/src/utils/format.ts +0 -21
- package/dist/templates/src/utils/getMicroApp.ts +0 -39
- package/dist/templates/src/utils/sentry.ts +0 -187
- package/dist/templates/src/utils/sentryDecorators.ts +0 -34
- package/dist/templates/src/utils/updateVersion.ts +0 -186
- package/dist/templates/updateVersion.ts +0 -186
- package/dist/templates/useRouteTitle.tsx +0 -36
- package/dist/templates/useSentry.ts +0 -92
- package/dist/templates/utils/env.ts +0 -3
- package/dist/templates/utils/format.ts +0 -21
- package/dist/templates/utils/getMicroApp.ts +0 -39
- package/dist/templates/utils/sentry.ts +0 -187
- package/dist/templates/utils/sentryDecorators.ts +0 -34
- package/dist/templates/utils/updateVersion.ts +0 -186
- /package/dist/templates/app/{config/public → public}/404.png +0 -0
- /package/dist/templates/app/{config/public → public}/favicon.ico +0 -0
- /package/dist/templates/app/{config/public → public}/images/banner_market_modal.webp +0 -0
- /package/dist/templates/app/{config/public → public}/images/chatmode_chat_dark.webp +0 -0
- /package/dist/templates/app/{config/public → public}/images/chatmode_chat_light.webp +0 -0
- /package/dist/templates/app/{config/public → public}/images/chatmode_docs_dark.webp +0 -0
- /package/dist/templates/app/{config/public → public}/images/chatmode_docs_light.webp +0 -0
- /package/dist/templates/app/{config/public → public}/images/empty_topic_dark.webp +0 -0
- /package/dist/templates/app/{config/public → public}/images/empty_topic_light.webp +0 -0
- /package/dist/templates/app/{config/public → public}/images/screenshot_background.webp +0 -0
- /package/dist/templates/app/{config/public → public}/images/theme_auto.webp +0 -0
- /package/dist/templates/app/{config/public → public}/images/theme_dark.webp +0 -0
- /package/dist/templates/app/{config/public → public}/images/theme_light.webp +0 -0
- /package/dist/templates/app/{config/public → public}/index.html +0 -0
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
import { message, notification } from 'antd';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
|
|
4
|
-
const APP_NAME = process.env.APP_NAME;
|
|
5
|
-
interface IVersionRecord {
|
|
6
|
-
action: '' | 'refreshedByClick';
|
|
7
|
-
stack: string[];
|
|
8
|
-
}
|
|
9
|
-
// 对应的数组的key
|
|
10
|
-
const RECORD_KEY = `${APP_NAME}_version_record`;
|
|
11
|
-
|
|
12
|
-
// 当前版本号
|
|
13
|
-
let CUR_VERSION = '';
|
|
14
|
-
// 页面是否有通知
|
|
15
|
-
let CUR_STATE = false;
|
|
16
|
-
// 是否通过点击通知触发刷新
|
|
17
|
-
let REFRESHED_BY_CLICK = false;
|
|
18
|
-
|
|
19
|
-
window.addEventListener('beforeunload', () => {
|
|
20
|
-
if (!REFRESHED_BY_CLICK) {
|
|
21
|
-
const recordStr = localStorage.getItem(RECORD_KEY);
|
|
22
|
-
if (recordStr === null) return;
|
|
23
|
-
const record: IVersionRecord = JSON.parse(recordStr);
|
|
24
|
-
if (record.action !== '') {
|
|
25
|
-
record.action = '';
|
|
26
|
-
localStorage.setItem(RECORD_KEY, JSON.stringify(record));
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
const Interval = {
|
|
32
|
-
clearInterval: function () {
|
|
33
|
-
cancelAnimationFrame(this.timer);
|
|
34
|
-
},
|
|
35
|
-
setInterval: function (callback: any, interval: any) {
|
|
36
|
-
let startTime = new Date().valueOf();
|
|
37
|
-
let endTime = new Date().valueOf();
|
|
38
|
-
const self: any = this; // eslint-disable-line
|
|
39
|
-
const loop = () => {
|
|
40
|
-
self.timer = requestAnimationFrame(loop);
|
|
41
|
-
endTime = new Date().valueOf();
|
|
42
|
-
if (endTime - startTime >= interval) {
|
|
43
|
-
endTime = startTime = new Date().valueOf();
|
|
44
|
-
callback?.(); // eslint-disable-line
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
this.timer = requestAnimationFrame(loop);
|
|
48
|
-
return this.timer;
|
|
49
|
-
},
|
|
50
|
-
timer: 0,
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* 读取到更新的json文件版本内容
|
|
55
|
-
*/
|
|
56
|
-
const fetchUpdateVersionFile = () => {
|
|
57
|
-
return new Promise((resolve, reject) => {
|
|
58
|
-
fetch('/update_version.json')
|
|
59
|
-
.then(res => {
|
|
60
|
-
return res.body;
|
|
61
|
-
})
|
|
62
|
-
.then(body => {
|
|
63
|
-
const reader = body?.getReader();
|
|
64
|
-
if (reader) {
|
|
65
|
-
reader
|
|
66
|
-
.read()
|
|
67
|
-
.then(val => {
|
|
68
|
-
let str = '';
|
|
69
|
-
if (val.value) {
|
|
70
|
-
for (let i = 0; i < val.value.length; i++) {
|
|
71
|
-
str += String.fromCharCode(val.value[i]);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return JSON.parse(str);
|
|
75
|
-
})
|
|
76
|
-
.then(json => {
|
|
77
|
-
resolve(json);
|
|
78
|
-
})
|
|
79
|
-
.catch(err => {
|
|
80
|
-
reject(err);
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
})
|
|
84
|
-
.catch(err => {
|
|
85
|
-
reject(err);
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
const ENV = process.env.NODE_ENV;
|
|
91
|
-
|
|
92
|
-
const notifyUserUpdate = () => {
|
|
93
|
-
const handleClick = () => {
|
|
94
|
-
REFRESHED_BY_CLICK = true;
|
|
95
|
-
const recordStr = localStorage.getItem(RECORD_KEY);
|
|
96
|
-
if (recordStr === null) return;
|
|
97
|
-
const record: IVersionRecord = JSON.parse(recordStr);
|
|
98
|
-
record.action = 'refreshedByClick';
|
|
99
|
-
localStorage.setItem(RECORD_KEY, JSON.stringify(record));
|
|
100
|
-
window.location.reload();
|
|
101
|
-
};
|
|
102
|
-
const handleClose = () => {
|
|
103
|
-
Interval.clearInterval();
|
|
104
|
-
message.open({
|
|
105
|
-
content: '页面将不会提示更新',
|
|
106
|
-
type: 'warning',
|
|
107
|
-
});
|
|
108
|
-
};
|
|
109
|
-
const openNotification = () => {
|
|
110
|
-
const element = React.createElement(
|
|
111
|
-
'div', // 类型
|
|
112
|
-
{
|
|
113
|
-
onClick: handleClick,
|
|
114
|
-
style: { color: '#1677ff', cursor: 'pointer' },
|
|
115
|
-
}, // 属性
|
|
116
|
-
'页面已更新,请点击此处刷新页面!', // 子元素
|
|
117
|
-
);
|
|
118
|
-
notification.warning({
|
|
119
|
-
description: element,
|
|
120
|
-
duration: null,
|
|
121
|
-
message: '温馨提示',
|
|
122
|
-
onClose: handleClose,
|
|
123
|
-
placement: 'bottomRight',
|
|
124
|
-
});
|
|
125
|
-
};
|
|
126
|
-
openNotification();
|
|
127
|
-
CUR_STATE = true;
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
const handleMain = (version: string, handleCb: any, fetchDelay: number) => {
|
|
131
|
-
// 记录当前版本号
|
|
132
|
-
CUR_VERSION = version;
|
|
133
|
-
// 从本地获取历史记录
|
|
134
|
-
const oldVersionRecordStr = localStorage.getItem(RECORD_KEY);
|
|
135
|
-
// 继承历史记录中的action、stack
|
|
136
|
-
let oldAction: IVersionRecord['action'] = '';
|
|
137
|
-
const oldStack: IVersionRecord['stack'] = [version];
|
|
138
|
-
if (oldVersionRecordStr !== null) {
|
|
139
|
-
const record: IVersionRecord = JSON.parse(oldVersionRecordStr);
|
|
140
|
-
oldAction = record.action;
|
|
141
|
-
}
|
|
142
|
-
// 创建变量记录版本、操作
|
|
143
|
-
const curVersionRecord: IVersionRecord = {
|
|
144
|
-
action: oldAction,
|
|
145
|
-
stack: oldStack,
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
localStorage.setItem(RECORD_KEY, JSON.stringify(curVersionRecord));
|
|
149
|
-
|
|
150
|
-
Interval.setInterval(() => {
|
|
151
|
-
fetchUpdateVersionFile().then((res: any) => {
|
|
152
|
-
// 读取版本记录
|
|
153
|
-
const versionRecordStr = localStorage.getItem(RECORD_KEY);
|
|
154
|
-
if (typeof versionRecordStr === 'string') {
|
|
155
|
-
const versionRecord: IVersionRecord = JSON.parse(versionRecordStr);
|
|
156
|
-
// 读取对应栈
|
|
157
|
-
const lastVersion = versionRecord.stack[0];
|
|
158
|
-
localStorage.setItem(RECORD_KEY, JSON.stringify(versionRecord));
|
|
159
|
-
// 在服务器的版本与当前版本不一致
|
|
160
|
-
if (res.version !== CUR_VERSION) {
|
|
161
|
-
if (CUR_STATE === false) {
|
|
162
|
-
// 发起通知
|
|
163
|
-
handleCb();
|
|
164
|
-
} else if (
|
|
165
|
-
versionRecord.action === 'refreshedByClick' &&
|
|
166
|
-
lastVersion !== CUR_VERSION
|
|
167
|
-
) {
|
|
168
|
-
// 上一个标签页更新过,且当前标签页未更新
|
|
169
|
-
REFRESHED_BY_CLICK = true;
|
|
170
|
-
window.location.reload();
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
}, fetchDelay);
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
export const openUpdateVersionNotify = (fetchDelay: number) => {
|
|
179
|
-
// 开发环境没有必要开启版本检测功能
|
|
180
|
-
if (ENV === 'development') {
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
fetchUpdateVersionFile().then((res: any) => {
|
|
184
|
-
handleMain(res.version, notifyUserUpdate, fetchDelay);
|
|
185
|
-
});
|
|
186
|
-
};
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { useThemeStore } from '@store/theme';
|
|
2
|
-
import { Button } from 'antd';
|
|
3
|
-
import React from 'react';
|
|
4
|
-
|
|
5
|
-
export default function BasePage() {
|
|
6
|
-
const theme = useThemeStore(state => state.theme);
|
|
7
|
-
const setTheme = useThemeStore(state => state.setTheme);
|
|
8
|
-
|
|
9
|
-
return (
|
|
10
|
-
<>
|
|
11
|
-
<Button type="primary">antd按钮</Button>
|
|
12
|
-
<button
|
|
13
|
-
type="button"
|
|
14
|
-
className={
|
|
15
|
-
' dark:text-red-600 dark:bg-[var(--tailwindssantd-color-primary)] bg-[var(--tailwindssantd-color-primary)]'
|
|
16
|
-
}
|
|
17
|
-
>
|
|
18
|
-
tailwind按钮
|
|
19
|
-
</button>
|
|
20
|
-
<button type="button" onClick={() => setTheme('dark')}>
|
|
21
|
-
切换主题({theme})
|
|
22
|
-
</button>
|
|
23
|
-
</>
|
|
24
|
-
);
|
|
25
|
-
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html style="height: 100%">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8" />
|
|
5
|
-
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
6
|
-
<meta name="renderer" content="webkit" />
|
|
7
|
-
<meta
|
|
8
|
-
name="viewport"
|
|
9
|
-
content="width=device-width,initial-scale=1.0,user-scalable=no"
|
|
10
|
-
/>
|
|
11
|
-
<title><%= title %></title>
|
|
12
|
-
</head>
|
|
13
|
-
<body style="height: 100%">
|
|
14
|
-
<!--[if lt IE 9]>
|
|
15
|
-
<p class="browsehappy">
|
|
16
|
-
You are using an <strong>outdated</strong> browser. Please
|
|
17
|
-
<a href="http://browsehappy.com/">upgrade your browser</a> to improve
|
|
18
|
-
your experience.
|
|
19
|
-
</p>
|
|
20
|
-
<![endif]-->
|
|
21
|
-
<div id="<%= mountRoot %>" style="height: 100%; width: 100%"></div>
|
|
22
|
-
<div id="notificationContainer"></div>
|
|
23
|
-
<script>
|
|
24
|
-
function push(subapp) {
|
|
25
|
-
history.pushState(null, subapp, subapp);
|
|
26
|
-
}
|
|
27
|
-
</script>
|
|
28
|
-
</body>
|
|
29
|
-
</html>
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
import * as Sentry from '@sentry/react';
|
|
2
|
-
|
|
3
|
-
// Sentry 配置接口
|
|
4
|
-
export interface SentryConfig {
|
|
5
|
-
dsn: string;
|
|
6
|
-
environment: string;
|
|
7
|
-
release?: string;
|
|
8
|
-
sampleRate: number;
|
|
9
|
-
tracesSampleRate: number;
|
|
10
|
-
enabled: boolean;
|
|
11
|
-
sessionSampleRate: number;
|
|
12
|
-
beforeSend?: (event: Sentry.ErrorEvent, hint: Sentry.EventHint) => Sentry.ErrorEvent | null;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// 开发环境配置
|
|
16
|
-
const developmentConfig: Partial<SentryConfig> = {
|
|
17
|
-
enabled: true, // 开发环境可以选择关闭
|
|
18
|
-
sampleRate: 1.0,
|
|
19
|
-
tracesSampleRate: 1.0,
|
|
20
|
-
sessionSampleRate: 1.0, // 开发环境记录所有会话
|
|
21
|
-
beforeSend: (event, hint) => {
|
|
22
|
-
console.group('🐛 Sentry Event (Development)');
|
|
23
|
-
console.log('Event:', event);
|
|
24
|
-
console.log('Hint:', hint);
|
|
25
|
-
console.log('Event:', event);
|
|
26
|
-
console.groupEnd();
|
|
27
|
-
|
|
28
|
-
return event;
|
|
29
|
-
},
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
// 生产环境配置
|
|
33
|
-
const productionConfig: Partial<SentryConfig> = {
|
|
34
|
-
enabled: true,
|
|
35
|
-
sampleRate: 1.0, // 临时设置为100%以排查问题,后续可调整
|
|
36
|
-
tracesSampleRate: 0.1, // 提高到10%性能采样
|
|
37
|
-
sessionSampleRate: 1.0, // 记录所有会话以获得准确的健康度数据
|
|
38
|
-
beforeSend: (event, hint) => {
|
|
39
|
-
// 生产环境也打印日志以便调试
|
|
40
|
-
console.log('🐛 Sentry Event (Production):', event);
|
|
41
|
-
|
|
42
|
-
// 过滤敏感信息
|
|
43
|
-
if (event.exception) {
|
|
44
|
-
const error = event.exception.values?.[0];
|
|
45
|
-
if (error?.value?.includes('密码') || error?.value?.includes('token')) {
|
|
46
|
-
return null; // 不发送包含敏感信息的错误
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
return event;
|
|
50
|
-
},
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
// 获取环境配置
|
|
54
|
-
const getEnvironmentConfig = (): Partial<SentryConfig> => {
|
|
55
|
-
const env = process.env.NODE_ENV || 'development';
|
|
56
|
-
console.log(env, 'env');
|
|
57
|
-
switch (env) {
|
|
58
|
-
case 'development':
|
|
59
|
-
return developmentConfig;
|
|
60
|
-
case 'production':
|
|
61
|
-
return productionConfig;
|
|
62
|
-
default:
|
|
63
|
-
return developmentConfig;
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
// 基础配置
|
|
68
|
-
const baseConfig: SentryConfig = {
|
|
69
|
-
dsn: process.env.REACT_APP_SENTRY_DSN || '',
|
|
70
|
-
environment: process.env.SENTRY_ENV || 'development',
|
|
71
|
-
enabled: true,
|
|
72
|
-
sampleRate: 1.0,
|
|
73
|
-
tracesSampleRate: 1.0,
|
|
74
|
-
sessionSampleRate: 1.0, // 默认记录所有会话
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
// 合并配置
|
|
78
|
-
export const sentryConfig: SentryConfig = {
|
|
79
|
-
...baseConfig,
|
|
80
|
-
...getEnvironmentConfig(),
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
// 安全的会话重放集成初始化
|
|
84
|
-
const getSafeReplayIntegration = () => {
|
|
85
|
-
try {
|
|
86
|
-
return Sentry.replayIntegration({
|
|
87
|
-
maskAllText: false,
|
|
88
|
-
maskAllInputs: false,
|
|
89
|
-
blockAllMedia: true,
|
|
90
|
-
networkDetailAllowUrls: [window.location.origin],
|
|
91
|
-
}) as any; // 添加类型断言
|
|
92
|
-
} catch (error) {
|
|
93
|
-
console.warn('会话重放初始化失败:', error);
|
|
94
|
-
return null;
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
// 初始化 Sentry
|
|
99
|
-
export const initSentry = () => {
|
|
100
|
-
// 修复 fetch 上下文问题
|
|
101
|
-
if (typeof window !== 'undefined' && window.fetch) {
|
|
102
|
-
window.fetch = window.fetch.bind(window);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (!sentryConfig.enabled || !sentryConfig.dsn) {
|
|
106
|
-
console.warn('❌ Sentry not enabled or DSN not provided');
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const integrations = [Sentry.browserTracingIntegration()];
|
|
111
|
-
|
|
112
|
-
// 安全地添加会话重放集成
|
|
113
|
-
const replayIntegration = getSafeReplayIntegration();
|
|
114
|
-
if (replayIntegration && !window.__GARFISH__) {
|
|
115
|
-
// 目前微服务无法使用会话重放
|
|
116
|
-
integrations.push(replayIntegration);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
Sentry.init({
|
|
120
|
-
dsn: sentryConfig.dsn,
|
|
121
|
-
environment: sentryConfig.environment,
|
|
122
|
-
sampleRate: sentryConfig.sampleRate,
|
|
123
|
-
tracesSampleRate: sentryConfig.tracesSampleRate,
|
|
124
|
-
beforeSend: sentryConfig.beforeSend,
|
|
125
|
-
|
|
126
|
-
// 使用自定义传输层,确保fetch上下文正确
|
|
127
|
-
transport: Sentry.makeBrowserOfflineTransport((options) => Sentry.makeFetchTransport(options, window.fetch.bind(window))),
|
|
128
|
-
|
|
129
|
-
// 设置追踪的 URL 匹配规则
|
|
130
|
-
tracePropagationTargets: ['localhost', /^https:\/\/yourapi\.domain\.com\/api/],
|
|
131
|
-
|
|
132
|
-
// 使用安全的集成配置
|
|
133
|
-
integrations,
|
|
134
|
-
|
|
135
|
-
// 错误过滤
|
|
136
|
-
ignoreErrors: [
|
|
137
|
-
// 忽略常见的无害错误
|
|
138
|
-
'Non-Error promise rejection captured',
|
|
139
|
-
'ResizeObserver loop limit exceeded',
|
|
140
|
-
'Script error.',
|
|
141
|
-
'Network Error',
|
|
142
|
-
'Loading chunk',
|
|
143
|
-
'Loading CSS chunk',
|
|
144
|
-
],
|
|
145
|
-
|
|
146
|
-
// URL 过滤
|
|
147
|
-
denyUrls: [
|
|
148
|
-
// 忽略浏览器扩展
|
|
149
|
-
/extensions\//i,
|
|
150
|
-
/^chrome:\/\//i,
|
|
151
|
-
/^moz-extension:\/\//i,
|
|
152
|
-
],
|
|
153
|
-
|
|
154
|
-
// 只在会话重放可用时设置这些选项
|
|
155
|
-
...(replayIntegration && {
|
|
156
|
-
replaysSessionSampleRate: 0.1,
|
|
157
|
-
replaysOnErrorSampleRate: 1.0,
|
|
158
|
-
}),
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
// 设置应用上下文
|
|
162
|
-
Sentry.setContext('app', {
|
|
163
|
-
name: process.env.APP_NAME || 'React App',
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
// ✨ 手动开始会话(确保会话被正确追踪)
|
|
167
|
-
Sentry.startSession();
|
|
168
|
-
|
|
169
|
-
console.log('✅ Sentry initialized successfully with session tracking');
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
// ✨ 新增:会话管理工具
|
|
173
|
-
export const sentrySession = {
|
|
174
|
-
// 开始新会话
|
|
175
|
-
startSession: () => {
|
|
176
|
-
Sentry.startSession();
|
|
177
|
-
},
|
|
178
|
-
|
|
179
|
-
// 结束当前会话
|
|
180
|
-
endSession: () => {
|
|
181
|
-
Sentry.endSession();
|
|
182
|
-
},
|
|
183
|
-
|
|
184
|
-
// 标记会话为崩溃
|
|
185
|
-
captureSession: (crashed: boolean = false) => {
|
|
186
|
-
Sentry.captureSession(crashed);
|
|
187
|
-
},
|
|
188
|
-
};
|
package/dist/templates/format.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 字节转换函数
|
|
3
|
-
* @param kb
|
|
4
|
-
* @returns
|
|
5
|
-
*/
|
|
6
|
-
interface FormatSizeUnitsProps {
|
|
7
|
-
kb: number;
|
|
8
|
-
units?: string[];
|
|
9
|
-
}
|
|
10
|
-
export function formatSizeUnits(props: FormatSizeUnitsProps) {
|
|
11
|
-
const { kb, units = ['KB', 'MB', 'GB', 'TB', 'PB'] } = props;
|
|
12
|
-
let newKb = kb;
|
|
13
|
-
let unitIndex = 0;
|
|
14
|
-
|
|
15
|
-
while (kb >= 1024 && unitIndex < units.length - 1) {
|
|
16
|
-
newKb = newKb / 1024;
|
|
17
|
-
unitIndex++;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return `${kb.toFixed(2)} ${units[unitIndex]}`;
|
|
21
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
// 创建一个空数组来存储匹配的对象
|
|
2
|
-
let matchedObjects: any[] = [];
|
|
3
|
-
|
|
4
|
-
// 定义一个递归函数来遍历子路由对象
|
|
5
|
-
function traverseRoutes(routes) {
|
|
6
|
-
for (const route of routes) {
|
|
7
|
-
// 检查当前子路由对象是否具有"microApp"属性
|
|
8
|
-
if (Object.prototype.hasOwnProperty.call(route, 'microApp')) {
|
|
9
|
-
// 如果有,将该子路由对象添加到结果数组中
|
|
10
|
-
matchedObjects.push(route);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// 检查当前子路由对象是否还有更深层级的子路由
|
|
14
|
-
if (Object.prototype.hasOwnProperty.call(route, 'routes')) {
|
|
15
|
-
// 递归调用自身来遍历更深层级的子路由对象
|
|
16
|
-
traverseRoutes(route.routes);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export const getMicroApp = (a: any[]) => {
|
|
22
|
-
matchedObjects = [];
|
|
23
|
-
// 遍历变量a中的每个对象
|
|
24
|
-
for (const obj of a) {
|
|
25
|
-
// 检查当前对象是否具有"microApp"属性
|
|
26
|
-
if (Object.prototype.hasOwnProperty.call(obj, 'microApp')) {
|
|
27
|
-
// 如果有,将该对象添加到结果数组中
|
|
28
|
-
matchedObjects.push(obj);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// 检查当前对象是否具有"routes"属性
|
|
32
|
-
if (Object.prototype.hasOwnProperty.call(obj, 'routes')) {
|
|
33
|
-
// 调用递归函数来遍历子路由对象
|
|
34
|
-
traverseRoutes(obj.routes);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return matchedObjects;
|
|
39
|
-
};
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
2
|
-
import { useLocation, matchRoutes } from 'react-router';
|
|
3
|
-
import { useAppData } from '@config/router/appContext';
|
|
4
|
-
|
|
5
|
-
const APP_NAME = process.env.APP_NAME!;
|
|
6
|
-
|
|
7
|
-
export const useRouteTitle = () => {
|
|
8
|
-
const location = useLocation();
|
|
9
|
-
const { routes } = useAppData();
|
|
10
|
-
|
|
11
|
-
useEffect(() => {
|
|
12
|
-
// 将路由配置转换为适合 matchRoutes 的格式
|
|
13
|
-
const routesList = Object.keys(routes).map((key) => {
|
|
14
|
-
const route = routes[key];
|
|
15
|
-
return {
|
|
16
|
-
path: route.absPath,
|
|
17
|
-
meta: route.props,
|
|
18
|
-
id: key,
|
|
19
|
-
};
|
|
20
|
-
});
|
|
21
|
-
// 匹配当前路径的路由
|
|
22
|
-
const matchedRoutes = matchRoutes(routesList, location);
|
|
23
|
-
|
|
24
|
-
if (matchedRoutes && matchedRoutes.length > 0) {
|
|
25
|
-
// 找到最后一个匹配的路由(叶子路由)
|
|
26
|
-
const leafRoute = matchedRoutes[matchedRoutes.length - 1];
|
|
27
|
-
const title = leafRoute.route.meta?.title;
|
|
28
|
-
|
|
29
|
-
if (title) {
|
|
30
|
-
document.title = title;
|
|
31
|
-
} else {
|
|
32
|
-
document.title = APP_NAME;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}, [location.pathname, routes]);
|
|
36
|
-
};
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
2
|
-
import { useLocation } from 'react-router';
|
|
3
|
-
import { sentryPerformance, sentryContext, sentryError, sentrySession } from '@/utils/sentry';
|
|
4
|
-
|
|
5
|
-
// 页面性能监控 Hook
|
|
6
|
-
export const useSentryPageTracking = (pageName: string) => {
|
|
7
|
-
const location = useLocation();
|
|
8
|
-
|
|
9
|
-
useEffect(() => {
|
|
10
|
-
// ✨ 记录页面访问(保持会话活跃)
|
|
11
|
-
sentrySession.recordPageView(pageName, `${location.pathname}${location.search}`);
|
|
12
|
-
|
|
13
|
-
const cleanup = sentryPerformance.withSpan(`Page: ${pageName}`, 'navigation', () => {
|
|
14
|
-
sentryContext.setContext('page', {
|
|
15
|
-
name: pageName,
|
|
16
|
-
path: location.pathname,
|
|
17
|
-
search: location.search,
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
sentryPerformance.addBreadcrumb(`Navigation to ${pageName}`, 'navigation', 'info');
|
|
21
|
-
|
|
22
|
-
return () => {
|
|
23
|
-
// 清理函数
|
|
24
|
-
};
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
return cleanup;
|
|
28
|
-
}, [pageName, location]);
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
// 组件性能监控 Hook
|
|
32
|
-
export const useSentryComponentTracking = (componentName: string) => {
|
|
33
|
-
useEffect(() => {
|
|
34
|
-
return sentryPerformance.withSpan(`Component: ${componentName}`, 'ui.react.mount', () => {
|
|
35
|
-
sentryPerformance.addBreadcrumb(`Component ${componentName} mounted`, 'ui', 'info');
|
|
36
|
-
|
|
37
|
-
return () => {
|
|
38
|
-
sentryPerformance.addBreadcrumb(`Component ${componentName} unmounted`, 'ui', 'info');
|
|
39
|
-
};
|
|
40
|
-
});
|
|
41
|
-
}, [componentName]);
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
// 错误处理 Hook
|
|
45
|
-
export const useSentryErrorHandler = () => {
|
|
46
|
-
return {
|
|
47
|
-
captureError: (error: Error, context?: Record<string, any>) => {
|
|
48
|
-
sentryError.captureException(error, context);
|
|
49
|
-
},
|
|
50
|
-
captureMessage: (message: string, level?: 'info' | 'warning' | 'error') => {
|
|
51
|
-
sentryError.captureMessage(message, level);
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
// 点击事件追踪 Hook
|
|
57
|
-
export const useSentryClickTracking = () => {
|
|
58
|
-
return {
|
|
59
|
-
trackClick: (
|
|
60
|
-
buttonName: string,
|
|
61
|
-
context?: {
|
|
62
|
-
buttonId?: string;
|
|
63
|
-
location?: string;
|
|
64
|
-
extraData?: Record<string, any>;
|
|
65
|
-
},
|
|
66
|
-
) => {
|
|
67
|
-
const clickData = {
|
|
68
|
-
buttonName,
|
|
69
|
-
buttonId: context?.buttonId,
|
|
70
|
-
location: context?.location || window.location.pathname,
|
|
71
|
-
clickTime: new Date().toISOString(),
|
|
72
|
-
timestamp: Date.now(),
|
|
73
|
-
...context?.extraData,
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
// ✨ 主动发送点击事件到 Sentry(这会立即发送)
|
|
77
|
-
sentryError.captureMessage(`Button Click: ${buttonName}`, 'info');
|
|
78
|
-
|
|
79
|
-
// 设置点击上下文(会包含在上面的消息中)
|
|
80
|
-
sentryContext.setContext('clickData', clickData);
|
|
81
|
-
|
|
82
|
-
// 记录用户操作(用于埋点统计)
|
|
83
|
-
sentrySession.recordUserAction(`Button Click: ${buttonName}`, clickData);
|
|
84
|
-
|
|
85
|
-
// 添加面包屑用于调试
|
|
86
|
-
sentryPerformance.addBreadcrumb(`Button clicked: ${buttonName}`, 'user.click', 'info');
|
|
87
|
-
|
|
88
|
-
// 设置点击上下文
|
|
89
|
-
sentryContext.setContext('lastClick', clickData);
|
|
90
|
-
},
|
|
91
|
-
};
|
|
92
|
-
};
|