@qlover/create-app 0.8.0 → 0.10.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.
Files changed (85) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/configs/_common/.github/workflows/general-check.yml +1 -1
  3. package/dist/configs/_common/.github/workflows/release.yml +2 -2
  4. package/dist/index.cjs +1 -1
  5. package/dist/index.js +1 -1
  6. package/dist/templates/next-app/.env.template +9 -10
  7. package/dist/templates/next-app/eslint.config.mjs +5 -0
  8. package/dist/templates/next-app/next.config.ts +1 -1
  9. package/dist/templates/next-app/src/app/[locale]/login/page.tsx +1 -1
  10. package/dist/templates/next-app/src/app/[locale]/page.tsx +1 -1
  11. package/dist/templates/next-app/src/app/[locale]/register/page.tsx +1 -1
  12. package/dist/templates/next-app/src/app/api/locales/json/route.ts +2 -1
  13. package/dist/templates/next-app/src/i18n/request.ts +2 -2
  14. package/dist/templates/react-app/__tests__/__mocks__/{MockAppConfit.ts → MockAppConfig.ts} +1 -1
  15. package/dist/templates/react-app/__tests__/__mocks__/components/TestApp.tsx +10 -17
  16. package/dist/templates/react-app/__tests__/__mocks__/components/TestBootstrapsProvider.tsx +27 -8
  17. package/dist/templates/react-app/__tests__/__mocks__/createMockGlobals.ts +1 -1
  18. package/dist/templates/react-app/__tests__/__mocks__/i18nextHttpBackend.ts +110 -0
  19. package/dist/templates/react-app/__tests__/__mocks__/testIOC/TestIOCRegister.ts +3 -2
  20. package/dist/templates/react-app/__tests__/setup/setupGlobal.ts +13 -0
  21. package/dist/templates/react-app/__tests__/src/base/services/I18nService.test.ts +3 -1
  22. package/dist/templates/react-app/__tests__/src/uikit/components/chatMessage/ChatRoot.test.tsx +274 -0
  23. package/dist/templates/react-app/config/IOCIdentifier.ts +9 -3
  24. package/dist/templates/react-app/config/Identifier/components/component.chatMessage.ts +56 -0
  25. package/dist/templates/react-app/config/Identifier/components/component.messageBaseList.ts +103 -0
  26. package/dist/templates/react-app/config/Identifier/pages/index.ts +1 -0
  27. package/dist/templates/react-app/config/Identifier/pages/page.message.ts +20 -0
  28. package/dist/templates/react-app/config/app.router.ts +23 -0
  29. package/dist/templates/react-app/config/common.ts +38 -0
  30. package/dist/templates/react-app/config/feapi.mock.json +5 -12
  31. package/dist/templates/react-app/config/i18n/chatMessageI18n.ts +17 -0
  32. package/dist/templates/react-app/config/i18n/messageBaseListI18n.ts +22 -0
  33. package/dist/templates/react-app/config/i18n/messageI18n.ts +14 -0
  34. package/dist/templates/react-app/docs/en/components/chat-message-component.md +314 -0
  35. package/dist/templates/react-app/docs/en/components/chat-message-refactor.md +270 -0
  36. package/dist/templates/react-app/docs/en/components/message-base-list-component.md +172 -0
  37. package/dist/templates/react-app/docs/zh/components/chat-message-component.md +314 -0
  38. package/dist/templates/react-app/docs/zh/components/chat-message-refactor.md +270 -0
  39. package/dist/templates/react-app/docs/zh/components/message-base-list-component.md +172 -0
  40. package/dist/templates/react-app/eslint.config.mjs +6 -5
  41. package/dist/templates/react-app/package.json +1 -1
  42. package/dist/templates/react-app/playwright.config.ts +6 -6
  43. package/dist/templates/react-app/public/locales/en/common.json +44 -1
  44. package/dist/templates/react-app/public/locales/zh/common.json +44 -1
  45. package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +22 -13
  46. package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +3 -3
  47. package/dist/templates/react-app/src/base/apis/userApi/UserApiType.ts +17 -12
  48. package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +19 -2
  49. package/dist/templates/react-app/src/base/port/RouteServiceInterface.ts +2 -4
  50. package/dist/templates/react-app/src/base/port/UserServiceInterface.ts +15 -9
  51. package/dist/templates/react-app/src/base/services/BaseLayoutService.ts +55 -0
  52. package/dist/templates/react-app/src/base/services/I18nService.ts +1 -0
  53. package/dist/templates/react-app/src/base/services/UserBootstrap.ts +43 -0
  54. package/dist/templates/react-app/src/base/services/UserGatewayPlugin.ts +16 -0
  55. package/dist/templates/react-app/src/base/services/UserService.ts +51 -80
  56. package/dist/templates/react-app/src/core/bootstraps/BootstrapClient.ts +8 -3
  57. package/dist/templates/react-app/src/core/bootstraps/BootstrapsRegistry.ts +6 -6
  58. package/dist/templates/react-app/src/core/bootstraps/SaveAppInfo.ts +28 -0
  59. package/dist/templates/react-app/src/core/clientIoc/ClientIOCRegister.ts +24 -18
  60. package/dist/templates/react-app/src/core/globals.ts +10 -11
  61. package/dist/templates/react-app/src/main.tsx +1 -1
  62. package/dist/templates/react-app/src/pages/auth/Layout.tsx +4 -4
  63. package/dist/templates/react-app/src/pages/auth/RegisterPage.tsx +1 -1
  64. package/dist/templates/react-app/src/pages/base/Layout.tsx +3 -3
  65. package/dist/templates/react-app/src/pages/base/MessagePage.tsx +40 -0
  66. package/dist/templates/react-app/src/uikit/components/BaseLayoutProvider.tsx +44 -0
  67. package/dist/templates/react-app/src/uikit/components/LogoutButton.tsx +1 -3
  68. package/dist/templates/react-app/src/uikit/components/MessageBaseList.tsx +240 -0
  69. package/dist/templates/react-app/src/uikit/components/chatMessage/ChatMessageBridge.ts +176 -0
  70. package/dist/templates/react-app/src/uikit/components/chatMessage/ChatRoot.tsx +21 -0
  71. package/dist/templates/react-app/src/uikit/components/chatMessage/FocusBar.tsx +106 -0
  72. package/dist/templates/react-app/src/uikit/components/chatMessage/MessageApi.ts +271 -0
  73. package/dist/templates/react-app/src/uikit/components/chatMessage/MessageItem.tsx +102 -0
  74. package/dist/templates/react-app/src/uikit/components/chatMessage/MessagesList.tsx +86 -0
  75. package/dist/templates/react-app/src/uikit/hooks/useNavigateBridge.ts +9 -0
  76. package/dist/templates/react-app/src/uikit/hooks/{useI18nGuard.ts → useRouterI18nGuard.ts} +7 -4
  77. package/dist/templates/react-app/tsconfig.app.json +4 -2
  78. package/dist/templates/react-app/tsconfig.node.json +4 -0
  79. package/dist/templates/react-app/tsconfig.test.json +3 -1
  80. package/package.json +3 -3
  81. package/dist/templates/react-app/__tests__/src/base/cases/AppError.test.ts +0 -102
  82. package/dist/templates/react-app/__tests__/src/main.integration.test.tsx +0 -61
  83. package/dist/templates/react-app/src/base/services/ProcesserExecutor.ts +0 -57
  84. package/dist/templates/react-app/src/uikit/components/ProcessExecutorProvider.tsx +0 -28
  85. package/dist/templates/react-app/src/uikit/components/UserAuthProvider.tsx +0 -16
@@ -0,0 +1,274 @@
1
+ import { BootstrapTest } from '@__mocks__/BootstrapTest';
2
+ import { TestApp } from '@__mocks__/components';
3
+ import * as chatI18nKeys from '@config/Identifier/components/component.chatMessage';
4
+ import { ChatMessageRole, ChatMessageStore } from '@qlover/corekit-bridge';
5
+ import { render, screen } from '@testing-library/react';
6
+ import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
7
+ import { logger } from '@/core/globals';
8
+ import { ChatMessageBridge } from '@/uikit/components/chatMessage/ChatMessageBridge';
9
+ import { ChatRoot } from '@/uikit/components/chatMessage/ChatRoot';
10
+ import type { ChatMessageI18nInterface } from '@config/i18n/chatMessageI18n';
11
+ import type { MessageGetwayInterface } from '@qlover/corekit-bridge';
12
+
13
+ // Mock i18n values matching the actual i18n keys
14
+ const mockI18n: ChatMessageI18nInterface = {
15
+ send: chatI18nKeys.COMPONENT_CHAT_SEND,
16
+ stop: chatI18nKeys.COMPONENT_CHAT_STOP,
17
+ loading: chatI18nKeys.COMPONENT_CHAT_LOADING,
18
+ inputPlaceholder: chatI18nKeys.COMPONENT_CHAT_INPUT_PLACEHOLDER,
19
+ empty: chatI18nKeys.COMPONENT_CHAT_EMPTY,
20
+ start: chatI18nKeys.COMPONENT_CHAT_START,
21
+ retry: chatI18nKeys.COMPONENT_CHAT_RETRY,
22
+ duration: chatI18nKeys.COMPONENT_CHAT_DURATION
23
+ };
24
+
25
+ // Simple mock gateway for testing
26
+ class MockMessageGateway implements MessageGetwayInterface {
27
+ sendMessage = vi.fn();
28
+ }
29
+
30
+ describe('ChatRoot Component', () => {
31
+ let messagesStore: ChatMessageStore<string>;
32
+ let mockGateway: MockMessageGateway;
33
+ let bridge: ChatMessageBridge<string>;
34
+
35
+ beforeAll(async () => {
36
+ await BootstrapTest.main({
37
+ root: globalThis,
38
+ bootHref: 'http://localhost:3000/en/test'
39
+ });
40
+ });
41
+
42
+ beforeEach(() => {
43
+ // Create fresh instances for each test
44
+ messagesStore = new ChatMessageStore<string>();
45
+ mockGateway = new MockMessageGateway();
46
+ bridge = new ChatMessageBridge<string>(messagesStore, {
47
+ gateway: mockGateway,
48
+ logger: logger,
49
+ senderName: 'TestSender',
50
+ gatewayOptions: {}
51
+ });
52
+
53
+ // Reset mocks
54
+ vi.clearAllMocks();
55
+ });
56
+
57
+ describe('Component Rendering', () => {
58
+ it('should render ChatRoot with all required components', () => {
59
+ render(
60
+ <TestApp>
61
+ <ChatRoot bridge={bridge} tt={mockI18n} />
62
+ </TestApp>
63
+ );
64
+
65
+ // Check main container
66
+ const chatRoot = screen.getByTestId('ChatRoot');
67
+ expect(chatRoot).toBeDefined();
68
+
69
+ // Check MessagesList component
70
+ const messagesList = screen.getByTestId('MessagesList');
71
+ expect(messagesList).toBeDefined();
72
+
73
+ // Check FocusBar component
74
+ const focusBar = screen.getByTestId('FocusBar');
75
+ expect(focusBar).toBeDefined();
76
+ });
77
+
78
+ it('should display empty state initially', () => {
79
+ render(
80
+ <TestApp>
81
+ <ChatRoot bridge={bridge} tt={mockI18n} />
82
+ </TestApp>
83
+ );
84
+
85
+ // Empty state text should be visible
86
+ // Note: The actual text will be the i18n key, not the translated text in tests
87
+ const emptyText = screen.getByText(/component_chat:empty/i);
88
+ expect(emptyText).toBeDefined();
89
+ });
90
+
91
+ it('should render textarea for input', () => {
92
+ render(
93
+ <TestApp>
94
+ <ChatRoot bridge={bridge} tt={mockI18n} />
95
+ </TestApp>
96
+ );
97
+
98
+ const textarea = screen.getByRole('textbox');
99
+ expect(textarea).toBeDefined();
100
+ });
101
+
102
+ it('should render send button', () => {
103
+ render(
104
+ <TestApp>
105
+ <ChatRoot bridge={bridge} tt={mockI18n} />
106
+ </TestApp>
107
+ );
108
+
109
+ const sendButton = screen.getByTestId('FocusBar-Button-Send');
110
+ expect(sendButton).toBeDefined();
111
+ });
112
+ });
113
+
114
+ describe('Props Integration', () => {
115
+ it('should accept and use bridge prop', () => {
116
+ render(
117
+ <TestApp>
118
+ <ChatRoot bridge={bridge} tt={mockI18n} />
119
+ </TestApp>
120
+ );
121
+
122
+ // Verify bridge is connected by checking store state
123
+ const state = messagesStore.state;
124
+ expect(state).toBeDefined();
125
+ expect(state.messages).toEqual([]);
126
+ expect(state.draftMessages).toEqual([]);
127
+ });
128
+
129
+ it('should accept different bridge instances', () => {
130
+ const newStore = new ChatMessageStore<string>();
131
+ const newBridge = new ChatMessageBridge<string>(newStore, {
132
+ gateway: mockGateway,
133
+ logger: logger,
134
+ senderName: 'NewTestSender',
135
+ gatewayOptions: {}
136
+ });
137
+
138
+ render(
139
+ <TestApp>
140
+ <ChatRoot bridge={newBridge} tt={mockI18n} />
141
+ </TestApp>
142
+ );
143
+
144
+ const chatRoot = screen.getByTestId('ChatRoot');
145
+ expect(chatRoot).toBeDefined();
146
+ });
147
+ });
148
+
149
+ describe('Bridge Integration', () => {
150
+ it('should connect to message store through bridge', () => {
151
+ render(
152
+ <TestApp>
153
+ <ChatRoot bridge={bridge} tt={mockI18n} />
154
+ </TestApp>
155
+ );
156
+
157
+ // Bridge should have access to store
158
+ const messageStore = bridge.getMessageStore();
159
+ expect(messageStore).toBe(messagesStore);
160
+ });
161
+
162
+ it('should update UI when content is changed via bridge', () => {
163
+ render(
164
+ <TestApp>
165
+ <ChatRoot bridge={bridge} tt={mockI18n} />
166
+ </TestApp>
167
+ );
168
+
169
+ // Initially, send button should be disabled (no content)
170
+ const sendButton = screen.getByTestId('FocusBar-Button-Send');
171
+ expect(sendButton).toHaveProperty('disabled', true);
172
+
173
+ // Change content via bridge
174
+ bridge.onChangeContent('Test message');
175
+
176
+ // Now send button should be enabled (has content)
177
+ // Note: This requires the component to re-render based on store updates
178
+ const state = messagesStore.state;
179
+ expect(state.draftMessages.length).toBeGreaterThan(0);
180
+ expect(state.draftMessages[0]?.content).toBe('Test message');
181
+ });
182
+ });
183
+
184
+ describe('Store State Management', () => {
185
+ it('should reflect message store state', () => {
186
+ render(
187
+ <TestApp>
188
+ <ChatRoot bridge={bridge} tt={mockI18n} />
189
+ </TestApp>
190
+ );
191
+
192
+ // Initial state should be empty
193
+ const initialState = messagesStore.state;
194
+ expect(initialState.messages).toEqual([]);
195
+ expect(initialState.draftMessages).toEqual([]);
196
+ // These properties might be undefined initially, which is fine
197
+ expect(initialState.disabledSend).toBeFalsy();
198
+ expect(initialState.streaming).toBeFalsy();
199
+ });
200
+
201
+ it('should update when messages are added to store', () => {
202
+ render(
203
+ <TestApp>
204
+ <ChatRoot bridge={bridge} tt={mockI18n} />
205
+ </TestApp>
206
+ );
207
+
208
+ // Add a message to the store
209
+ messagesStore.addMessage({
210
+ id: 'test-1',
211
+ role: ChatMessageRole.USER,
212
+ content: 'Test message',
213
+ loading: false,
214
+ startTime: Date.now()
215
+ });
216
+
217
+ // Verify message is in store
218
+ const state = messagesStore.state;
219
+ expect(state.messages.length).toBe(1);
220
+ expect(state.messages[0]?.content).toBe('Test message');
221
+ });
222
+ });
223
+
224
+ describe('Button States', () => {
225
+ it('should have disabled send button when no content', () => {
226
+ render(
227
+ <TestApp>
228
+ <ChatRoot bridge={bridge} tt={mockI18n} />
229
+ </TestApp>
230
+ );
231
+
232
+ const sendButton = screen.getByTestId('FocusBar-Button-Send');
233
+ expect(sendButton).toHaveProperty('disabled', true);
234
+ });
235
+ });
236
+
237
+ describe('Component Structure', () => {
238
+ it('should have correct CSS classes for layout', () => {
239
+ render(
240
+ <TestApp>
241
+ <ChatRoot bridge={bridge} tt={mockI18n} />
242
+ </TestApp>
243
+ );
244
+
245
+ const chatRoot = screen.getByTestId('ChatRoot');
246
+ expect(chatRoot.className).toContain('flex');
247
+ expect(chatRoot.className).toContain('flex-col');
248
+ });
249
+
250
+ it('should render MessagesList with correct data-testid', () => {
251
+ render(
252
+ <TestApp>
253
+ <ChatRoot bridge={bridge} tt={mockI18n} />
254
+ </TestApp>
255
+ );
256
+
257
+ const messagesList = screen.getByTestId('MessagesList');
258
+ expect(messagesList).toBeDefined();
259
+ expect(messagesList.className).toContain('overflow-y-auto');
260
+ });
261
+
262
+ it('should render FocusBar with correct data-testid', () => {
263
+ render(
264
+ <TestApp>
265
+ <ChatRoot bridge={bridge} tt={mockI18n} />
266
+ </TestApp>
267
+ );
268
+
269
+ const focusBar = screen.getByTestId('FocusBar');
270
+ expect(focusBar).toBeDefined();
271
+ expect(focusBar.className).toContain('border-t');
272
+ });
273
+ });
274
+ });
@@ -6,7 +6,6 @@ import type { ExecutorPageBridgeInterface } from '@/base/port/ExecutorPageBridge
6
6
  import type { JSONStoragePageBridgeInterface } from '@/base/port/JSONStoragePageBridgeInterface';
7
7
  import type { RequestPageBridgeInterface } from '@/base/port/RequestPageBridgeInterface';
8
8
  import type { I18nService } from '@/base/services/I18nService';
9
- import type { ProcesserExecutor } from '@/base/services/ProcesserExecutor';
10
9
  import type { RouteService } from '@/base/services/RouteService';
11
10
  import type { UserService } from '@/base/services/UserService';
12
11
  import type * as CorekitBridge from '@qlover/corekit-bridge';
@@ -29,8 +28,16 @@ export const IOCIdentifier = Object.freeze({
29
28
  AntdStaticApiInterface: 'AntdStaticApiInterface',
30
29
  RequestCatcherInterface: 'RequestCatcherInterface',
31
30
  I18nServiceInterface: 'I18nServiceInterface',
32
- ProcesserExecutorInterface: 'ProcesserExecutorInterface',
33
31
  RouteServiceInterface: 'RouteServiceInterface',
32
+ /**
33
+ * User service interface
34
+ *
35
+ * This interface is implemented by the corekit-bridge UserServiceInterface interface, used to manage user information and authentication.
36
+ *
37
+ * @example ```
38
+ * const userService = useIOC(IOCIdentifier.UserServiceInterface);
39
+ * ```
40
+ */
34
41
  UserServiceInterface: 'UserServiceInterface',
35
42
  I18nKeyErrorPlugin: 'I18nKeyErrorPlugin',
36
43
  FeApiCommonPlugin: 'FeApiCommonPlugin',
@@ -71,7 +78,6 @@ export interface IOCIdentifierMap {
71
78
  [IOCIdentifier.AntdStaticApiInterface]: DialogHandler;
72
79
  [IOCIdentifier.RequestCatcherInterface]: RequestStatusCatcher;
73
80
  [IOCIdentifier.I18nServiceInterface]: I18nService;
74
- [IOCIdentifier.ProcesserExecutorInterface]: ProcesserExecutor;
75
81
  [IOCIdentifier.RouteServiceInterface]: RouteService;
76
82
  [IOCIdentifier.UserServiceInterface]: UserService;
77
83
  [IOCIdentifier.I18nKeyErrorPlugin]: I18nKeyErrorPlugin;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @description Chat send button text
3
+ * @localZh 发送
4
+ * @localEn Send
5
+ */
6
+ export const COMPONENT_CHAT_SEND = 'component_chat:send';
7
+
8
+ /**
9
+ * @description Chat stop button text
10
+ * @localZh 停止
11
+ * @localEn Stop
12
+ */
13
+ export const COMPONENT_CHAT_STOP = 'component_chat:stop';
14
+
15
+ /**
16
+ * @description Chat loading text
17
+ * @localZh 加载中...
18
+ * @localEn Loading...
19
+ */
20
+ export const COMPONENT_CHAT_LOADING = 'component_chat:loading';
21
+
22
+ /**
23
+ * @description Chat input placeholder
24
+ * @localZh 输入消息... (Ctrl+Enter 发送)
25
+ * @localEn Type a message... (Ctrl+Enter to send)
26
+ */
27
+ export const COMPONENT_CHAT_INPUT_PLACEHOLDER =
28
+ 'component_chat:input_placeholder';
29
+
30
+ /**
31
+ * @description Chat empty messages
32
+ * @localZh 暂无对话
33
+ * @localEn No messages yet
34
+ */
35
+ export const COMPONENT_CHAT_EMPTY = 'component_chat:empty';
36
+
37
+ /**
38
+ * @description Chat start conversation
39
+ * @localZh 开始对话
40
+ * @localEn Start a conversation
41
+ */
42
+ export const COMPONENT_CHAT_START = 'component_chat:start';
43
+
44
+ /**
45
+ * @description Chat retry button
46
+ * @localZh 重试
47
+ * @localEn Retry
48
+ */
49
+ export const COMPONENT_CHAT_RETRY = 'component_chat:retry';
50
+
51
+ /**
52
+ * @description Chat duration label
53
+ * @localZh 耗时
54
+ * @localEn Duration
55
+ */
56
+ export const COMPONENT_CHAT_DURATION = 'component_chat:duration';
@@ -0,0 +1,103 @@
1
+ /**
2
+ * @description Message gateway test title
3
+ * @localZh 消息网关测试
4
+ * @localEn Message Gateway Test
5
+ */
6
+ export const COMPONENT_MESSAGE_BASE_LIST_TITLE =
7
+ 'component_message_base_list:title';
8
+
9
+ /**
10
+ * @description Message gateway test description
11
+ * @localZh 发送消息并等待网关响应
12
+ * @localEn Send messages and wait for gateway response
13
+ */
14
+ export const COMPONENT_MESSAGE_BASE_LIST_DESCRIPTION =
15
+ 'component_message_base_list:description';
16
+
17
+ /**
18
+ * @description No messages yet
19
+ * @localZh 暂无消息
20
+ * @localEn No messages yet
21
+ */
22
+ export const COMPONENT_MESSAGE_BASE_LIST_NO_MESSAGES =
23
+ 'component_message_base_list:no_messages';
24
+
25
+ /**
26
+ * @description Send your first message to get started
27
+ * @localZh 发送第一条消息开始使用
28
+ * @localEn Send your first message to get started
29
+ */
30
+ export const COMPONENT_MESSAGE_BASE_LIST_GET_STARTED =
31
+ 'component_message_base_list:get_started';
32
+
33
+ /**
34
+ * @description User label
35
+ * @localZh 你
36
+ * @localEn You
37
+ */
38
+ export const COMPONENT_MESSAGE_BASE_LIST_USER =
39
+ 'component_message_base_list:user';
40
+
41
+ /**
42
+ * @description Gateway label
43
+ * @localZh 网关
44
+ * @localEn Gateway
45
+ */
46
+ export const COMPONENT_MESSAGE_BASE_LIST_GATEWAY =
47
+ 'component_message_base_list:gateway';
48
+
49
+ /**
50
+ * @description Processing status
51
+ * @localZh 处理中...
52
+ * @localEn Processing...
53
+ */
54
+ export const COMPONENT_MESSAGE_BASE_LIST_PROCESSING =
55
+ 'component_message_base_list:processing';
56
+
57
+ /**
58
+ * @description Gateway failed label
59
+ * @localZh 网关(失败)
60
+ * @localEn Gateway (Failed)
61
+ */
62
+ export const COMPONENT_MESSAGE_BASE_LIST_GATEWAY_FAILED =
63
+ 'component_message_base_list:gateway_failed';
64
+
65
+ /**
66
+ * @description Failed to send message
67
+ * @localZh 发送消息失败
68
+ * @localEn Failed to send message
69
+ */
70
+ export const COMPONENT_MESSAGE_BASE_LIST_SEND_FAILED =
71
+ 'component_message_base_list:send_failed';
72
+
73
+ /**
74
+ * @description Gateway response label
75
+ * @localZh 网关响应
76
+ * @localEn Gateway Response
77
+ */
78
+ export const COMPONENT_MESSAGE_BASE_LIST_GATEWAY_RESPONSE =
79
+ 'component_message_base_list:gateway_response';
80
+
81
+ /**
82
+ * @description Input placeholder
83
+ * @localZh 在此输入您的消息...
84
+ * @localEn Type your message here...
85
+ */
86
+ export const COMPONENT_MESSAGE_BASE_LIST_INPUT_PLACEHOLDER =
87
+ 'component_message_base_list:input_placeholder';
88
+
89
+ /**
90
+ * @description Send button
91
+ * @localZh 发送
92
+ * @localEn Send
93
+ */
94
+ export const COMPONENT_MESSAGE_BASE_LIST_SEND_BUTTON =
95
+ 'component_message_base_list:send_button';
96
+
97
+ /**
98
+ * @description Error handling tip
99
+ * @localZh 提示:尝试发送 "error" 或 "Failed" 来测试错误处理
100
+ * @localEn Tip: Try sending "error" or "Failed" to test error handling
101
+ */
102
+ export const COMPONENT_MESSAGE_BASE_LIST_ERROR_TIP =
103
+ 'component_message_base_list:error_tip';
@@ -4,5 +4,6 @@ export * from './page.home';
4
4
  export * from './page.identifiter';
5
5
  export * from './page.jsonStorage';
6
6
  export * from './page.login';
7
+ export * from './page.message';
7
8
  export * from './page.register';
8
9
  export * from './page.request';
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @description Message page title
3
+ * @localZh 消息测试
4
+ * @localEn Message Test
5
+ */
6
+ export const PAGE_MESSAGE_TITLE = 'page_message:title';
7
+
8
+ /**
9
+ * @description Message page description
10
+ * @localZh 消息网关测试页面
11
+ * @localEn Message gateway test page
12
+ */
13
+ export const PAGE_MESSAGE_DESCRIPTION = 'page_message:description';
14
+
15
+ /**
16
+ * @description Message page keywords
17
+ * @localZh 消息, 网关, 测试
18
+ * @localEn Message, Gateway, Test
19
+ */
20
+ export const PAGE_MESSAGE_KEYWORDS = 'page_message:keywords';
@@ -5,6 +5,7 @@ import { homeI18n } from './i18n/homeI18n';
5
5
  import { identifiter18n } from './i18n/identifiter18n';
6
6
  import { jsonStorage18n } from './i18n/jsonStorage18n';
7
7
  import { login18n } from './i18n/login18n';
8
+ import { messageI18n } from './i18n/messageI18n';
8
9
  import { notFound18n, serverError18n } from './i18n/notFoundI18n';
9
10
  import { register18n } from './i18n/register18n';
10
11
  import { request18n } from './i18n/request18n';
@@ -88,6 +89,17 @@ export const baseRoutes: RouteConfigValue[] = [
88
89
  i18nInterface: identifiter18n
89
90
  }
90
91
  },
92
+ {
93
+ path: 'message',
94
+ element: 'base/MessagePage',
95
+ meta: {
96
+ title: identifier.PAGE_MESSAGE_TITLE,
97
+ description: identifier.PAGE_MESSAGE_DESCRIPTION,
98
+ icon: 'message',
99
+ localNamespace: 'common',
100
+ i18nInterface: messageI18n
101
+ }
102
+ },
91
103
  {
92
104
  path: '*',
93
105
  element: 'NoRouteFound',
@@ -249,6 +261,17 @@ export const baseNoLocaleRoutes: RouteConfigValue[] = [
249
261
  localNamespace: 'common',
250
262
  i18nInterface: identifiter18n
251
263
  }
264
+ },
265
+ {
266
+ path: 'message',
267
+ element: 'base/MessagePage',
268
+ meta: {
269
+ title: identifier.PAGE_MESSAGE_TITLE,
270
+ description: identifier.PAGE_MESSAGE_DESCRIPTION,
271
+ icon: 'message',
272
+ localNamespace: 'common',
273
+ i18nInterface: messageI18n
274
+ }
252
275
  }
253
276
  ]
254
277
  },
@@ -35,6 +35,8 @@ export const loggerStyles = {
35
35
  *
36
36
  * - 需要以 / 开头
37
37
  * - 但是不能只有 /
38
+ *
39
+ * **TODO: 未来可能需要修改为支持 vercel 环境使用前缀**
38
40
  */
39
41
  export const routerPrefix = '/router-root';
40
42
 
@@ -45,3 +47,39 @@ export const routerPrefix = '/router-root';
45
47
  * - false: 不使用本地化路由,直接使用路径 (例如: /home)
46
48
  */
47
49
  export const useLocaleRoutes = true;
50
+
51
+ /**
52
+ * 注入到浏览器全局变量中需要忽略的变量
53
+ *
54
+ * 应用 `@/core/globals.ts` 中的变量
55
+ *
56
+ * 可能 appConfig 有敏感信息,需要忽略
57
+ *
58
+ * - 可以直接忽略整个 appConfig 对象, 例如: 'appConfig'
59
+ * - 也可以忽略单个属性, 例如: 'appConfig.openAiTokenPrefix', 'appConfig.openAiToken'
60
+ *
61
+ * @example 忽略 appConfig 对象
62
+ * ```typescript
63
+ * export const omitInjectedGlobals = [
64
+ * 'appConfig'
65
+ * ];
66
+ * ```
67
+ *
68
+ * @example 忽略 appConfig 中的 openAiTokenPrefix 和 openAiToken 属性
69
+ * ```typescript
70
+ * export const omitInjectedGlobals = [
71
+ * 'appConfig.openAiTokenPrefix',
72
+ * 'appConfig.openAiToken'
73
+ * ];
74
+ * ```
75
+ */
76
+ export const omitInjectedGlobals = [
77
+ 'appConfig.openAiTokenPrefix',
78
+ 'appConfig.openAiToken',
79
+ 'appConfig.loginPassword',
80
+ 'appConfig.loginUser',
81
+ 'appConfig.aiApiTokenPrefix',
82
+ 'appConfig.openAiBaseUrl',
83
+ 'appConfig.aiApiBaseUrl',
84
+ 'appConfig.aiApiToken'
85
+ ];
@@ -3,29 +3,19 @@
3
3
  "mock": true,
4
4
  "noUrl": true
5
5
  },
6
- "GET https://feapi.example.com/api/userinfo": {
7
- "name": "John Doe",
8
- "email": "john.doe@example.com",
9
- "picture": "https://randomuser.me/api/portraits/men/1.jpg"
10
- },
6
+
11
7
  "GET /api/userinfo": {
12
8
  "name": "John Doe",
13
9
  "email": "john.doe@example.com",
14
10
  "picture": "https://randomuser.me/api/portraits/men/1.jpg"
15
11
  },
16
- "POST https://feapi.example.com/api/login": {
17
- "token": "asdfasdf123123asdfasdf"
18
- },
19
12
  "POST /api/login": {
20
13
  "token": "/api/login-token-adfasdfasdf"
21
14
  },
22
- "POST https://feapi.example.com/api/register": {
23
- "token": "asdfasdf123123asdfasdf"
24
- },
25
15
  "POST /api/register": {
26
16
  "token": "asdfasdf123123asdfasdf"
27
17
  },
28
- "POST https://api.openai.com/v1/chat/completions": {
18
+ "POST /chat/completions": {
29
19
  "id": "chatcmpl-1234567890",
30
20
  "object": "chat.completion",
31
21
  "created": 1721702400,
@@ -37,5 +27,8 @@
37
27
  }
38
28
  }
39
29
  ]
30
+ },
31
+ "POST /api/logout": {
32
+ "redirect": "/login"
40
33
  }
41
34
  }
@@ -0,0 +1,17 @@
1
+ import * as i18nKeys from '../Identifier/components/component.chatMessage';
2
+
3
+ /**
4
+ * ChatMessage component i18n interface
5
+ */
6
+ export type ChatMessageI18nInterface = typeof chatMessageI18n;
7
+
8
+ export const chatMessageI18n = Object.freeze({
9
+ send: i18nKeys.COMPONENT_CHAT_SEND,
10
+ stop: i18nKeys.COMPONENT_CHAT_STOP,
11
+ loading: i18nKeys.COMPONENT_CHAT_LOADING,
12
+ inputPlaceholder: i18nKeys.COMPONENT_CHAT_INPUT_PLACEHOLDER,
13
+ empty: i18nKeys.COMPONENT_CHAT_EMPTY,
14
+ start: i18nKeys.COMPONENT_CHAT_START,
15
+ retry: i18nKeys.COMPONENT_CHAT_RETRY,
16
+ duration: i18nKeys.COMPONENT_CHAT_DURATION
17
+ });
@@ -0,0 +1,22 @@
1
+ import * as i18nKeys from '../Identifier/components/component.messageBaseList';
2
+
3
+ /**
4
+ * MessageBaseList component i18n interface
5
+ */
6
+ export type MessageBaseListI18nInterface = typeof messageBaseListI18n;
7
+
8
+ export const messageBaseListI18n = Object.freeze({
9
+ title: i18nKeys.COMPONENT_MESSAGE_BASE_LIST_TITLE,
10
+ description: i18nKeys.COMPONENT_MESSAGE_BASE_LIST_DESCRIPTION,
11
+ noMessages: i18nKeys.COMPONENT_MESSAGE_BASE_LIST_NO_MESSAGES,
12
+ getStarted: i18nKeys.COMPONENT_MESSAGE_BASE_LIST_GET_STARTED,
13
+ user: i18nKeys.COMPONENT_MESSAGE_BASE_LIST_USER,
14
+ gateway: i18nKeys.COMPONENT_MESSAGE_BASE_LIST_GATEWAY,
15
+ processing: i18nKeys.COMPONENT_MESSAGE_BASE_LIST_PROCESSING,
16
+ gatewayFailed: i18nKeys.COMPONENT_MESSAGE_BASE_LIST_GATEWAY_FAILED,
17
+ sendFailed: i18nKeys.COMPONENT_MESSAGE_BASE_LIST_SEND_FAILED,
18
+ gatewayResponse: i18nKeys.COMPONENT_MESSAGE_BASE_LIST_GATEWAY_RESPONSE,
19
+ inputPlaceholder: i18nKeys.COMPONENT_MESSAGE_BASE_LIST_INPUT_PLACEHOLDER,
20
+ sendButton: i18nKeys.COMPONENT_MESSAGE_BASE_LIST_SEND_BUTTON,
21
+ errorTip: i18nKeys.COMPONENT_MESSAGE_BASE_LIST_ERROR_TIP
22
+ });
@@ -0,0 +1,14 @@
1
+ import * as i18nKeys from '../Identifier/pages/page.message';
2
+
3
+ /**
4
+ * Message page i18n interface
5
+ */
6
+ export type MessageI18nInterface = typeof messageI18n;
7
+
8
+ export const messageI18n = Object.freeze({
9
+ // basic meta properties
10
+ title: i18nKeys.PAGE_MESSAGE_TITLE,
11
+ description: i18nKeys.PAGE_MESSAGE_DESCRIPTION,
12
+ content: i18nKeys.PAGE_MESSAGE_DESCRIPTION,
13
+ keywords: i18nKeys.PAGE_MESSAGE_KEYWORDS
14
+ });