@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.
- package/CHANGELOG.md +32 -0
- package/dist/configs/_common/.github/workflows/general-check.yml +1 -1
- package/dist/configs/_common/.github/workflows/release.yml +2 -2
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/templates/next-app/.env.template +9 -10
- package/dist/templates/next-app/eslint.config.mjs +5 -0
- package/dist/templates/next-app/next.config.ts +1 -1
- package/dist/templates/next-app/src/app/[locale]/login/page.tsx +1 -1
- package/dist/templates/next-app/src/app/[locale]/page.tsx +1 -1
- package/dist/templates/next-app/src/app/[locale]/register/page.tsx +1 -1
- package/dist/templates/next-app/src/app/api/locales/json/route.ts +2 -1
- package/dist/templates/next-app/src/i18n/request.ts +2 -2
- package/dist/templates/react-app/__tests__/__mocks__/{MockAppConfit.ts → MockAppConfig.ts} +1 -1
- package/dist/templates/react-app/__tests__/__mocks__/components/TestApp.tsx +10 -17
- package/dist/templates/react-app/__tests__/__mocks__/components/TestBootstrapsProvider.tsx +27 -8
- package/dist/templates/react-app/__tests__/__mocks__/createMockGlobals.ts +1 -1
- package/dist/templates/react-app/__tests__/__mocks__/i18nextHttpBackend.ts +110 -0
- package/dist/templates/react-app/__tests__/__mocks__/testIOC/TestIOCRegister.ts +3 -2
- package/dist/templates/react-app/__tests__/setup/setupGlobal.ts +13 -0
- package/dist/templates/react-app/__tests__/src/base/services/I18nService.test.ts +3 -1
- package/dist/templates/react-app/__tests__/src/uikit/components/chatMessage/ChatRoot.test.tsx +274 -0
- package/dist/templates/react-app/config/IOCIdentifier.ts +9 -3
- package/dist/templates/react-app/config/Identifier/components/component.chatMessage.ts +56 -0
- package/dist/templates/react-app/config/Identifier/components/component.messageBaseList.ts +103 -0
- package/dist/templates/react-app/config/Identifier/pages/index.ts +1 -0
- package/dist/templates/react-app/config/Identifier/pages/page.message.ts +20 -0
- package/dist/templates/react-app/config/app.router.ts +23 -0
- package/dist/templates/react-app/config/common.ts +38 -0
- package/dist/templates/react-app/config/feapi.mock.json +5 -12
- package/dist/templates/react-app/config/i18n/chatMessageI18n.ts +17 -0
- package/dist/templates/react-app/config/i18n/messageBaseListI18n.ts +22 -0
- package/dist/templates/react-app/config/i18n/messageI18n.ts +14 -0
- package/dist/templates/react-app/docs/en/components/chat-message-component.md +314 -0
- package/dist/templates/react-app/docs/en/components/chat-message-refactor.md +270 -0
- package/dist/templates/react-app/docs/en/components/message-base-list-component.md +172 -0
- package/dist/templates/react-app/docs/zh/components/chat-message-component.md +314 -0
- package/dist/templates/react-app/docs/zh/components/chat-message-refactor.md +270 -0
- package/dist/templates/react-app/docs/zh/components/message-base-list-component.md +172 -0
- package/dist/templates/react-app/eslint.config.mjs +6 -5
- package/dist/templates/react-app/package.json +1 -1
- package/dist/templates/react-app/playwright.config.ts +6 -6
- package/dist/templates/react-app/public/locales/en/common.json +44 -1
- package/dist/templates/react-app/public/locales/zh/common.json +44 -1
- package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +22 -13
- package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +3 -3
- package/dist/templates/react-app/src/base/apis/userApi/UserApiType.ts +17 -12
- package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +19 -2
- package/dist/templates/react-app/src/base/port/RouteServiceInterface.ts +2 -4
- package/dist/templates/react-app/src/base/port/UserServiceInterface.ts +15 -9
- package/dist/templates/react-app/src/base/services/BaseLayoutService.ts +55 -0
- package/dist/templates/react-app/src/base/services/I18nService.ts +1 -0
- package/dist/templates/react-app/src/base/services/UserBootstrap.ts +43 -0
- package/dist/templates/react-app/src/base/services/UserGatewayPlugin.ts +16 -0
- package/dist/templates/react-app/src/base/services/UserService.ts +51 -80
- package/dist/templates/react-app/src/core/bootstraps/BootstrapClient.ts +8 -3
- package/dist/templates/react-app/src/core/bootstraps/BootstrapsRegistry.ts +6 -6
- package/dist/templates/react-app/src/core/bootstraps/SaveAppInfo.ts +28 -0
- package/dist/templates/react-app/src/core/clientIoc/ClientIOCRegister.ts +24 -18
- package/dist/templates/react-app/src/core/globals.ts +10 -11
- package/dist/templates/react-app/src/main.tsx +1 -1
- package/dist/templates/react-app/src/pages/auth/Layout.tsx +4 -4
- package/dist/templates/react-app/src/pages/auth/RegisterPage.tsx +1 -1
- package/dist/templates/react-app/src/pages/base/Layout.tsx +3 -3
- package/dist/templates/react-app/src/pages/base/MessagePage.tsx +40 -0
- package/dist/templates/react-app/src/uikit/components/BaseLayoutProvider.tsx +44 -0
- package/dist/templates/react-app/src/uikit/components/LogoutButton.tsx +1 -3
- package/dist/templates/react-app/src/uikit/components/MessageBaseList.tsx +240 -0
- package/dist/templates/react-app/src/uikit/components/chatMessage/ChatMessageBridge.ts +176 -0
- package/dist/templates/react-app/src/uikit/components/chatMessage/ChatRoot.tsx +21 -0
- package/dist/templates/react-app/src/uikit/components/chatMessage/FocusBar.tsx +106 -0
- package/dist/templates/react-app/src/uikit/components/chatMessage/MessageApi.ts +271 -0
- package/dist/templates/react-app/src/uikit/components/chatMessage/MessageItem.tsx +102 -0
- package/dist/templates/react-app/src/uikit/components/chatMessage/MessagesList.tsx +86 -0
- package/dist/templates/react-app/src/uikit/hooks/useNavigateBridge.ts +9 -0
- package/dist/templates/react-app/src/uikit/hooks/{useI18nGuard.ts → useRouterI18nGuard.ts} +7 -4
- package/dist/templates/react-app/tsconfig.app.json +4 -2
- package/dist/templates/react-app/tsconfig.node.json +4 -0
- package/dist/templates/react-app/tsconfig.test.json +3 -1
- package/package.json +3 -3
- package/dist/templates/react-app/__tests__/src/base/cases/AppError.test.ts +0 -102
- package/dist/templates/react-app/__tests__/src/main.integration.test.tsx +0 -61
- package/dist/templates/react-app/src/base/services/ProcesserExecutor.ts +0 -57
- package/dist/templates/react-app/src/uikit/components/ProcessExecutorProvider.tsx +0 -28
- 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';
|
|
@@ -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
|
-
|
|
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
|
|
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
|
+
});
|