Files
AIclinicalresearch/docs/04-开发规范/10-模块认证规范.md
HaHafeng 1b53ab9d52 feat(aia): Complete AIA V2.0 with universal streaming capabilities
Major Changes:
- Add StreamingService with OpenAI Compatible format
- Upgrade Chat component V2 with Ant Design X integration
- Implement AIA module with 12 intelligent agents
- Update API routes to unified /api/v1 prefix
- Update system documentation

Backend (~1300 lines):
- common/streaming: OpenAI Compatible adapter
- modules/aia: 12 agents, conversation service, streaming integration
- Update route versions (RVW, PKB to v1)

Frontend (~3500 lines):
- modules/aia: AgentHub + ChatWorkspace (100% prototype restoration)
- shared/Chat: AIStreamChat, ThinkingBlock, useAIStream Hook
- Update API endpoints to v1

Documentation:
- AIA module status guide
- Universal capabilities catalog
- System overview updates
- All module documentation sync

Tested: Stream response verified, authentication working
Status: AIA V2.0 core completed (85%)
2026-01-14 19:15:01 +08:00

195 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 璅<E79285>霈方<E99C88><EFBFBD><E996AB>
> <EFBFBD><EFBFBD><EFBFBD><EFBFBD>銋劐<EFBFBD>銝𡁜𦛚璅<EFBFBD><EFBFBD><EFBFBD><EFBFBD>雿輻鍂撟喳蝱霈方<EFBFBD><EFBFBD><EFBFBD>嚗𣬚靽脲<EFBFBD><EFBFBD>?API <20>賣迤蝖格𡉼撣血<E692A3>撉諹<E69289><E8ABB9><EFBFBD>頨思遢<E6809D>?
## 1. <20><EFBFBD><EFBFBD><E79281>
```
<EFBFBD>𢞖<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
<EFBFBD>? <20>滨垢 <20>?
<EFBFBD>? <20>𢞖<EFBFBD><F0A29E96><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?
<EFBFBD>? <20>? common/api/axios.ts <20>?撣西恕霂<E68195><E99C82> axios 摰硺<E691B0> <20>? <20>?
<EFBFBD>? <20>? framework/auth/api.ts <20>?Token 蝞∠<E89D9E> (getAccessToken)<29>? <20>?
<EFBFBD>? <20><EFBFBD><E5A999><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
<20>?
<20>?Authorization: Bearer <token>
<20>?
<EFBFBD>𢞖<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
<EFBFBD>? <20>𡒊垢 <20>?
<EFBFBD>? <20>𢞖<EFBFBD><F0A29E96><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?
<EFBFBD>? <20>? common/auth/auth.middleware.ts <20>? <20>?
<EFBFBD>? <20>? - authenticate: 撉諹<E69289> JWT Token <20>? <20>?
<EFBFBD>? <20>? - requirePermission: <20><><EFBFBD><EFBFBD><E79289>? <20>? <20>?
<EFBFBD>? <20>? - requireRoles: 閫坿𠧧璉<F0A0A7A7><E79289>? <20>? <20>?
<EFBFBD>? <20><EFBFBD><E5A999><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? <20>?
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
```
## 2. <20>滨垢閫<E59EA2><E996AB>
### 2.1 雿輻鍂撣西恕霂<E68195><E99C82> axios 摰硺<E691B0><EFBFBD><EFBFBD><EFBFBD>
```typescript
// 撖澆<E69296>撣西恕霂<E68195><E99C82> apiClient
import apiClient from '../../../common/api/axios';
// 雿輻鍂<E8BCBB><EFBFBD>銝?axios 摰<><E691B0><EFBFBD><EFBFBD>嚗諹䌊<E8ABB9>冽𡉼撣?JWT Token
const response = await apiClient.get('/api/v2/xxx');
const response = await apiClient.post('/api/v2/xxx', data);
```
### 2.2 雿輻鍂<E8BCBB><EFBFBD> fetch嚗<68><E59A97><EFBFBD>见𢆡瘛餃<E7989B> Token嚗?
```typescript
import { getAccessToken } from '../../../framework/auth/api';
// <20>𥕦遣 getAuthHeaders <20>賣㺭
function getAuthHeaders(): HeadersInit {
const headers: Record<string, string> = {
'Content-Type': 'application/json',
};
const token = getAccessToken();
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
return headers;
}
// <20><><EFBFBD>?fetch 霂瑟<E99C82>雿輻鍂 getAuthHeaders()
const response = await fetch(url, {
headers: getAuthHeaders(),
});
// <20><>辣銝𠹺<E98A9D><EFBFBD><E59A97>霈曄蔭 Content-Type嚗?
const token = getAccessToken();
const headers: HeadersInit = {};
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
const response = await fetch(url, {
method: 'POST',
headers,
body: formData,
});
```
## 3. <20>𡒊垢閫<E59EA2><E996AB>
### 3.1 頝舐眏瘛餃<E7989B>霈方<E99C88>銝剝𡢿隞?
```typescript
// 撖澆<E69296>霈方<E99C88>銝剝𡢿隞?
import { authenticate, requirePermission } from '../../../common/auth/auth.middleware.js';
// 瘛餃<E7989B><E9A483>啗楝<E59597>?
fastify.get('/xxx', { preHandler: [authenticate] }, handler);
// <20><><EFBFBD>鸌摰𡁏<E691B0><F0A1818F>?
fastify.post('/xxx', {
preHandler: [authenticate, requirePermission('module:action')]
}, handler);
```
### 3.2 <20><EFBFBD><E689B9>刻繮<E588BB>𣇉鍂<F0A38789>?ID
```typescript
/**
* <20><EFBFBD><E79195><EFBFBD>ID嚗<44><E59A97>JWT Token銝剛繮<E5899B><EFBFBD>
*/
function getUserId(request: FastifyRequest): string {
const userId = (request as any).user?.userId;
if (!userId) {
throw new Error('User not authenticated');
}
return userId;
}
// <20>冽綉<E586BD>嗅膥<E59785><EFBFBD>銝凋蝙<E5878B>?
async function myHandler(request: FastifyRequest, reply: FastifyReply) {
const userId = getUserId(request);
// ... 雿輻鍂 userId
}
```
### 3.3 JWT Token 蝏𤘪<E89D8F>
```typescript
interface DecodedToken {
userId: string; // <20><EFBFBD>ID
phone: string; // <20>𧢲㦤<F0A7A2B2>?
role: string; // 閫坿𠧧
tenantId: string; // 蝘<><E89D98>ID
tenantCode?: string; // 蝘<><E89D98>Code
iat: number; // 蝑曉<E89D91><E69B89>園𡢿
exp: number; // 餈<><E9A488><EFBFBD>園𡢿
}
```
## 4. 璉<><E79289><EFBFBD><E4BAA4>?
### 4.1 <20>唳芋<E594B3><EFBFBD><E5A092><EFBFBD><E78390><EFBFBD><E4BAA4>?
- [ ] **<EFBFBD>滨垢 API <20><>辣**
- [ ] 雿輻鍂 `apiClient` <20>𡝗溶<F0A19D97>?`getAuthHeaders()`
- [ ] <20><>辣銝𠹺<E98A9D><F0A0B9BA>閧𡠺憭<F0A1A0BA><E686AD><EFBFBD><E59A97>霈曄蔭 Content-Type嚗?
- [ ] 撖澆枂<E6BE86>賣㺭銝滚<E98A9D><E6BB9A><EFBFBD>霂閧鍂 userId <20><>
- [ ] **<EFBFBD>𡒊垢頝舐眏<EFBFBD><EFBFBD>辣**
- [ ] 撖澆<E69296> `authenticate` 銝剝𡢿隞?
- [ ] <20><><EFBFBD><EFBFBD><EFBFBD>恕霂<E68195><E99C82>頝舐眏瘛餃<E7989B> `preHandler: [authenticate]`
- [ ] <20><EFBFBD> API嚗<49><E59A97>璅⊥踎<E28AA5>𡑒”嚗匧虾銝齿溶<E9BDBF>㰘恕霂?
- [ ] **<EFBFBD>𡒊垢<EFBFBD><EFBFBD><EFBFBD><EFBFBD>隞?*
- [ ] 瘛餃<E7989B> `getUserId()`<>𨭌<EFBFBD>賣㺭
- [ ] 蝘駁膄<E9A781><E88684><EFBFBD>?`MOCK_USER_ID` <20>𣇉蝻𣇉<E89DBB>暺䁅恕<E48185>?
- [ ] 雿輻鍂 `getUserId(request)` <20><EFBFBD><E79195><EFBFBD> ID
### 4.2 撌脣<E6928C><E884A3>鞉芋<E99E89>㛖𠶖<E39B96>?
| 璅<E79285> | <20>滨垢 API | <20>𡒊垢頝舐眏 | <20>𡒊垢<F0A1928A><EFBFBD><E689B9>?| <20><EFBFBD>?|
|------|---------|---------|-----------|------|
| RVW | <20>?apiClient | <20>?authenticate | <20>?getUserId | <20>?|
| PKB | <20>?<3F>行⏛<E8A18C>?| <20>?authenticate | <20>?getUserId | <20>?|
| ASL | <20>?getAuthHeaders | <20>?authenticate | <20>?getUserId | <20>?|
| DC Tool B | <20>?getAuthHeaders | <20>?authenticate | <20>?getUserId | <20>?|
| DC Tool C | <20>?apiClient | <20>?authenticate | <20>?getUserId | <20>?|
| IIT | N/A (隡<><E99AA1>敺桐縑) | N/A | <20>?隡<><E99AA1>敺桐縑userId | <20>?|
| Prompt蝞∠<E89D9E> | <20>?getAuthHeaders | <20>?authenticate | <20>?getUserId | <20>?|
## 5. 撣貉<E692A3><E8B289>躰秤<E8BAB0>諹圾<E8ABB9>單䲮獢?
### 5.1 401 Unauthorized
**<EFBFBD><EFBFBD>**: <20>滨垢瘝⊥<E7989D><E28AA5>箏蒂 JWT Token <20>?Token 餈<><E9A488>
**閫<><E996AB>**:
1.<><E79289><EFBFBD>蝡?API <20>臬炏雿輻鍂 `apiClient` <20>?`getAuthHeaders()`
2.<><E79289>?localStorage 銝剜糓<E5899C><EFBFBD> `accessToken`
3.<><E68692> Token 餈<><E9A488><EFBFBD><E59A97>霂訫<E99C82><E8A8AB><EFBFBD><E594B3>齿鰵<E9BDBF><EFBFBD>
### 5.2 User not authenticated
**<EFBFBD><EFBFBD>**: <20>𡒊垢頝舐眏瘝⊥<E7989D>瘛餃<E7989B> `authenticate` 銝剝𡢿隞?
**閫<><E996AB>**: <20>刻楝<E588BB><EFBFBD>銋劐葉瘛餃<E7989B> `preHandler: [authenticate]`
### 5.3 TypeError: Cannot read property 'userId' of undefined
**<EFBFBD><EFBFBD>**: 雿輻鍂鈭<E98D82><E988AD>霂舐<E99C82>撅墧<E69285><EFBFBD>嚗Ǒrequest.user.id` <20><EFBFBD> `request.user.userId`嚗?
**閫<><E996AB>**: 雿輻鍂 `(request as any).user?.userId`
## 6. <20><><EFBFBD><EFBFBD><EFBFBD>隞?
- <20>滨垢 axios 摰硺<E691B0>: `frontend-v2/src/common/api/axios.ts`
- <20>滨垢 Token 蝞∠<E89D9E>: `frontend-v2/src/framework/auth/api.ts`
- <20>𡒊垢霈方<E99C88>銝剝𡢿隞? `backend/src/common/auth/auth.middleware.ts`
- <20>𡒊垢 JWT <20>滚𦛚: `backend/src/common/auth/jwt.service.ts`