@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.
Files changed (175) hide show
  1. package/dist/templates/HarmonyOS_Sans_Bold.woff2 +0 -0
  2. package/dist/templates/HarmonyOS_Sans_Medium.woff2 +0 -0
  3. package/dist/templates/HarmonyOS_Sans_Regular.woff2 +0 -0
  4. package/dist/templates/Locale.tsx +14 -18
  5. package/dist/templates/MainContentWrap.tsx +11 -15
  6. package/dist/templates/ThemeContext.tsx +27 -24
  7. package/dist/templates/app/config/env/.env.public.tpl +2 -19
  8. package/dist/templates/app/config/jwt/index.ts +4 -4
  9. package/dist/templates/app/config/request/error-handler.ts +67 -0
  10. package/dist/templates/app/config/request/index.ts +127 -129
  11. package/dist/templates/app/config/request/interceptors.ts +118 -0
  12. package/dist/templates/app/config/request/token-manager.ts +23 -0
  13. package/dist/templates/app/config/request/types.ts +63 -0
  14. package/dist/templates/app/config/rspack/rspack.config.mjs +62 -61
  15. package/dist/templates/app/config/rspack/rspack.prod.mjs +41 -62
  16. package/dist/templates/app/locales/zh-CN/common.json +3 -0
  17. package/dist/templates/app/package.json.tpl +1 -10
  18. package/dist/templates/app/public/fonts/HarmonyOS_Sans_Bold.woff2 +0 -0
  19. package/dist/templates/app/public/fonts/HarmonyOS_Sans_Medium.woff2 +0 -0
  20. package/dist/templates/app/public/fonts/HarmonyOS_Sans_Regular.woff2 +0 -0
  21. package/dist/templates/app/react-app-env.d.ts +13 -8
  22. package/dist/templates/app/src/bootstrap/index.ts +34 -0
  23. package/dist/templates/app/src/config/env.ts +84 -0
  24. package/dist/templates/app/src/index.tsx +17 -51
  25. package/dist/templates/app/src/layout/Locale.tsx +14 -18
  26. package/dist/templates/app/src/layout/MainContentWrap.tsx +11 -15
  27. package/dist/templates/app/src/layout/ThemeContext.tsx +27 -24
  28. package/dist/templates/app/src/locales/default/common.ts +3 -1
  29. package/dist/templates/app/src/micro/garfish.ts +53 -0
  30. package/dist/templates/app/src/pages/base/index.tsx +189 -25
  31. package/dist/templates/app/src/routes.tsx +21 -12
  32. package/dist/templates/app/src/types/global.d.ts +19 -0
  33. package/dist/templates/app/src/utils/index.ts +3 -1
  34. package/dist/templates/app/store/middleware/createDevtools.ts +7 -7
  35. package/dist/templates/base/index.tsx +189 -25
  36. package/dist/templates/bootstrap/index.ts +34 -0
  37. package/dist/templates/common.json +3 -0
  38. package/dist/templates/common.ts +3 -1
  39. package/dist/templates/config/env/.env.public.tpl +2 -19
  40. package/dist/templates/config/env.ts +84 -0
  41. package/dist/templates/config/jwt/index.ts +4 -4
  42. package/dist/templates/config/request/error-handler.ts +67 -0
  43. package/dist/templates/config/request/index.ts +127 -129
  44. package/dist/templates/config/request/interceptors.ts +118 -0
  45. package/dist/templates/config/request/token-manager.ts +23 -0
  46. package/dist/templates/config/request/types.ts +63 -0
  47. package/dist/templates/config/rspack/rspack.config.mjs +62 -61
  48. package/dist/templates/config/rspack/rspack.prod.mjs +41 -62
  49. package/dist/templates/createDevtools.ts +7 -7
  50. package/dist/templates/default/common.ts +3 -1
  51. package/dist/templates/env/.env.public.tpl +2 -19
  52. package/dist/templates/env.ts +83 -2
  53. package/dist/templates/error-handler.ts +67 -0
  54. package/dist/templates/fonts/HarmonyOS_Sans_Bold.woff2 +0 -0
  55. package/dist/templates/fonts/HarmonyOS_Sans_Medium.woff2 +0 -0
  56. package/dist/templates/fonts/HarmonyOS_Sans_Regular.woff2 +0 -0
  57. package/dist/templates/garfish.ts +53 -0
  58. package/dist/templates/global.d.ts +19 -0
  59. package/dist/templates/index.tsx +189 -25
  60. package/dist/templates/interceptors.ts +118 -0
  61. package/dist/templates/jwt/index.ts +4 -4
  62. package/dist/templates/layout/Locale.tsx +14 -18
  63. package/dist/templates/layout/MainContentWrap.tsx +11 -15
  64. package/dist/templates/layout/ThemeContext.tsx +27 -24
  65. package/dist/templates/locales/default/common.ts +3 -1
  66. package/dist/templates/locales/zh-CN/common.json +3 -0
  67. package/dist/templates/micro/garfish.ts +53 -0
  68. package/dist/templates/middleware/createDevtools.ts +7 -7
  69. package/dist/templates/package.json.tpl +1 -10
  70. package/dist/templates/page.tsx +21 -19
  71. package/dist/templates/pages/base/index.tsx +189 -25
  72. package/dist/templates/public/fonts/HarmonyOS_Sans_Bold.woff2 +0 -0
  73. package/dist/templates/public/fonts/HarmonyOS_Sans_Medium.woff2 +0 -0
  74. package/dist/templates/public/fonts/HarmonyOS_Sans_Regular.woff2 +0 -0
  75. package/dist/templates/react-app-env.d.ts +13 -8
  76. package/dist/templates/request/error-handler.ts +67 -0
  77. package/dist/templates/request/index.ts +127 -129
  78. package/dist/templates/request/interceptors.ts +118 -0
  79. package/dist/templates/request/token-manager.ts +23 -0
  80. package/dist/templates/request/types.ts +63 -0
  81. package/dist/templates/routes.tsx +21 -12
  82. package/dist/templates/rspack/rspack.config.mjs +62 -61
  83. package/dist/templates/rspack/rspack.prod.mjs +41 -62
  84. package/dist/templates/rspack.config.mjs +62 -61
  85. package/dist/templates/rspack.prod.mjs +41 -62
  86. package/dist/templates/src/bootstrap/index.ts +34 -0
  87. package/dist/templates/src/config/env.ts +84 -0
  88. package/dist/templates/src/index.tsx +17 -51
  89. package/dist/templates/src/layout/Locale.tsx +14 -18
  90. package/dist/templates/src/layout/MainContentWrap.tsx +11 -15
  91. package/dist/templates/src/layout/ThemeContext.tsx +27 -24
  92. package/dist/templates/src/locales/default/common.ts +3 -1
  93. package/dist/templates/src/micro/garfish.ts +53 -0
  94. package/dist/templates/src/pages/base/index.tsx +189 -25
  95. package/dist/templates/src/routes.tsx +21 -12
  96. package/dist/templates/src/types/global.d.ts +19 -0
  97. package/dist/templates/src/utils/index.ts +3 -1
  98. package/dist/templates/store/middleware/createDevtools.ts +7 -7
  99. package/dist/templates/token-manager.ts +23 -0
  100. package/dist/templates/types/global.d.ts +19 -0
  101. package/dist/templates/utils/index.ts +3 -1
  102. package/dist/templates/zh-CN/common.json +3 -0
  103. package/package.json +1 -1
  104. package/dist/templates/app/config/sentry/sentry.config.ts +0 -188
  105. package/dist/templates/app/src/hooks/useRouteTitle.tsx +0 -36
  106. package/dist/templates/app/src/hooks/useSentry.ts +0 -92
  107. package/dist/templates/app/src/pages/base/layout.tsx +0 -6
  108. package/dist/templates/app/src/pages/base/page.tsx +0 -25
  109. package/dist/templates/app/src/utils/env.ts +0 -3
  110. package/dist/templates/app/src/utils/format.ts +0 -21
  111. package/dist/templates/app/src/utils/getMicroApp.ts +0 -39
  112. package/dist/templates/app/src/utils/sentry.ts +0 -187
  113. package/dist/templates/app/src/utils/sentryDecorators.ts +0 -34
  114. package/dist/templates/app/src/utils/updateVersion.ts +0 -186
  115. package/dist/templates/base/layout.tsx +0 -6
  116. package/dist/templates/base/page.tsx +0 -25
  117. package/dist/templates/config/public/404.png +0 -0
  118. package/dist/templates/config/public/favicon.ico +0 -0
  119. package/dist/templates/config/public/images/banner_market_modal.webp +0 -0
  120. package/dist/templates/config/public/images/chatmode_chat_dark.webp +0 -0
  121. package/dist/templates/config/public/images/chatmode_chat_light.webp +0 -0
  122. package/dist/templates/config/public/images/chatmode_docs_dark.webp +0 -0
  123. package/dist/templates/config/public/images/chatmode_docs_light.webp +0 -0
  124. package/dist/templates/config/public/images/empty_topic_dark.webp +0 -0
  125. package/dist/templates/config/public/images/empty_topic_light.webp +0 -0
  126. package/dist/templates/config/public/images/screenshot_background.webp +0 -0
  127. package/dist/templates/config/public/images/theme_auto.webp +0 -0
  128. package/dist/templates/config/public/images/theme_dark.webp +0 -0
  129. package/dist/templates/config/public/images/theme_light.webp +0 -0
  130. package/dist/templates/config/public/index.html +0 -29
  131. package/dist/templates/config/sentry/sentry.config.ts +0 -188
  132. package/dist/templates/format.ts +0 -21
  133. package/dist/templates/getMicroApp.ts +0 -39
  134. package/dist/templates/hooks/useRouteTitle.tsx +0 -36
  135. package/dist/templates/hooks/useSentry.ts +0 -92
  136. package/dist/templates/layout.tsx +0 -6
  137. package/dist/templates/pages/base/layout.tsx +0 -6
  138. package/dist/templates/pages/base/page.tsx +0 -25
  139. package/dist/templates/sentry/sentry.config.ts +0 -188
  140. package/dist/templates/sentry.config.ts +0 -188
  141. package/dist/templates/sentry.ts +0 -187
  142. package/dist/templates/sentryDecorators.ts +0 -34
  143. package/dist/templates/src/hooks/useRouteTitle.tsx +0 -36
  144. package/dist/templates/src/hooks/useSentry.ts +0 -92
  145. package/dist/templates/src/pages/base/layout.tsx +0 -6
  146. package/dist/templates/src/pages/base/page.tsx +0 -25
  147. package/dist/templates/src/utils/env.ts +0 -3
  148. package/dist/templates/src/utils/format.ts +0 -21
  149. package/dist/templates/src/utils/getMicroApp.ts +0 -39
  150. package/dist/templates/src/utils/sentry.ts +0 -187
  151. package/dist/templates/src/utils/sentryDecorators.ts +0 -34
  152. package/dist/templates/src/utils/updateVersion.ts +0 -186
  153. package/dist/templates/updateVersion.ts +0 -186
  154. package/dist/templates/useRouteTitle.tsx +0 -36
  155. package/dist/templates/useSentry.ts +0 -92
  156. package/dist/templates/utils/env.ts +0 -3
  157. package/dist/templates/utils/format.ts +0 -21
  158. package/dist/templates/utils/getMicroApp.ts +0 -39
  159. package/dist/templates/utils/sentry.ts +0 -187
  160. package/dist/templates/utils/sentryDecorators.ts +0 -34
  161. package/dist/templates/utils/updateVersion.ts +0 -186
  162. /package/dist/templates/app/{config/public → public}/404.png +0 -0
  163. /package/dist/templates/app/{config/public → public}/favicon.ico +0 -0
  164. /package/dist/templates/app/{config/public → public}/images/banner_market_modal.webp +0 -0
  165. /package/dist/templates/app/{config/public → public}/images/chatmode_chat_dark.webp +0 -0
  166. /package/dist/templates/app/{config/public → public}/images/chatmode_chat_light.webp +0 -0
  167. /package/dist/templates/app/{config/public → public}/images/chatmode_docs_dark.webp +0 -0
  168. /package/dist/templates/app/{config/public → public}/images/chatmode_docs_light.webp +0 -0
  169. /package/dist/templates/app/{config/public → public}/images/empty_topic_dark.webp +0 -0
  170. /package/dist/templates/app/{config/public → public}/images/empty_topic_light.webp +0 -0
  171. /package/dist/templates/app/{config/public → public}/images/screenshot_background.webp +0 -0
  172. /package/dist/templates/app/{config/public → public}/images/theme_auto.webp +0 -0
  173. /package/dist/templates/app/{config/public → public}/images/theme_dark.webp +0 -0
  174. /package/dist/templates/app/{config/public → public}/images/theme_light.webp +0 -0
  175. /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,6 +0,0 @@
1
- import React from 'react';
2
- import { Outlet } from 'react-router';
3
-
4
- export default function BaseLayout() {
5
- return <Outlet />;
6
- }
@@ -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
- }
@@ -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
- };
@@ -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
- };
@@ -1,6 +0,0 @@
1
- import React from 'react';
2
- import { Outlet } from 'react-router';
3
-
4
- export default function BaseLayout() {
5
- return <Outlet />;
6
- }
@@ -1,6 +0,0 @@
1
- import React from 'react';
2
- import { Outlet } from 'react-router';
3
-
4
- export default function BaseLayout() {
5
- return <Outlet />;
6
- }