- 添加缺失的认证参数:appId, appSecretCode, role - 修复 analysisType 和 departmentCode 参数 - 将所有接口改为使用 Form 参数(form-data 格式) - 更新服务层支持字典参数 - 更新所有测试代码 - 所有测试通过(7/7)
241 lines
5.4 KiB
Markdown
241 lines
5.4 KiB
Markdown
# ✅ Form-Data 实现最终确认
|
||
|
||
## 实现日期
|
||
2026-03-03
|
||
|
||
## 实现状态
|
||
✅ **完成并验证** - 所有接口使用 form-data,Swagger 正确显示
|
||
|
||
---
|
||
|
||
## 📋 实现总结
|
||
|
||
### ✅ 最终实现方式
|
||
|
||
**所有接口使用 Form 参数,Swagger UI 正确显示为 form-data 格式**
|
||
|
||
```python
|
||
@router.post("/account/common/getToken")
|
||
async def get_token(
|
||
projectNo: str = Form(..., description="项目编号"),
|
||
entityName: str = Form(..., description="项目名称"),
|
||
userId: str = Form(..., description="操作人员编号"),
|
||
# ... 其他参数
|
||
):
|
||
# 构建字典并传递给服务层
|
||
request_data = {
|
||
"projectNo": projectNo,
|
||
"entityName": entityName,
|
||
"userId": userId,
|
||
# ...
|
||
}
|
||
return token_service.create_token(request_data)
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 关键设计
|
||
|
||
### 1. **路由层**
|
||
- ✅ 使用 `Form(...)` 参数接收 form-data
|
||
- ✅ 将 Form 参数转换为字典传递给服务层
|
||
- ✅ 不使用 Pydantic 模型作为请求参数(避免 Swagger 显示为 JSON)
|
||
|
||
### 2. **服务层**
|
||
- ✅ 接受 `Union[Dict, object]` 类型参数
|
||
- ✅ 兼容字典和对象两种访问方式
|
||
- ✅ 使用字典访问:`request.get("key")` 或 `request["key"]`
|
||
|
||
### 3. **Swagger UI**
|
||
- ✅ 自动识别 Form 参数
|
||
- ✅ 显示为 `application/x-www-form-urlencoded`
|
||
- ✅ 提供表单字段输入框(不是 JSON 编辑器)
|
||
|
||
---
|
||
|
||
## 📊 实现对比
|
||
|
||
### ❌ 之前的实现(JSON 方式)
|
||
```python
|
||
@router.post("/account/common/getToken")
|
||
async def get_token(request: GetTokenRequest):
|
||
# 接收 JSON body
|
||
return token_service.create_token(request)
|
||
```
|
||
**问题**: Swagger UI 显示为 JSON 格式
|
||
|
||
### ✅ 现在的实现(Form-Data 方式)
|
||
```python
|
||
@router.post("/account/common/getToken")
|
||
async def get_token(
|
||
projectNo: str = Form(...),
|
||
entityName: str = Form(...),
|
||
# ...
|
||
):
|
||
request_data = {"projectNo": projectNo, "entityName": entityName, ...}
|
||
return token_service.create_token(request_data)
|
||
```
|
||
**结果**: Swagger UI 显示为 form-data 格式 ✅
|
||
|
||
---
|
||
|
||
## ✅ 测试结果
|
||
|
||
```bash
|
||
======================== 7 passed, 1 warning in 0.06s =========================
|
||
```
|
||
|
||
**所有 7 个测试通过** ✅
|
||
|
||
---
|
||
|
||
## 📖 使用方式
|
||
|
||
### Python requests
|
||
```python
|
||
import requests
|
||
|
||
# ✅ 使用 data 参数(form-data)
|
||
response = requests.post(
|
||
"http://localhost:8000/account/common/getToken",
|
||
data={
|
||
"projectNo": "test_001",
|
||
"entityName": "测试企业",
|
||
"userId": "902001",
|
||
"userName": "902001",
|
||
"appId": "remote_app",
|
||
"appSecretCode": "your_code",
|
||
"role": "VIEWER",
|
||
"orgCode": "902000",
|
||
"departmentCode": "902000"
|
||
}
|
||
)
|
||
```
|
||
|
||
### curl
|
||
```bash
|
||
curl -X POST http://localhost:8000/account/common/getToken \
|
||
-d "projectNo=test_001" \
|
||
-d "entityName=测试企业" \
|
||
-d "userId=902001" \
|
||
-d "userName=902001" \
|
||
-d "appId=remote_app" \
|
||
-d "appSecretCode=your_code" \
|
||
-d "role=VIEWER" \
|
||
-d "orgCode=902000" \
|
||
-d "departmentCode=902000"
|
||
```
|
||
|
||
### Swagger UI
|
||
1. 访问 http://localhost:8000/docs
|
||
2. 点击接口展开
|
||
3. 点击 "Try it out"
|
||
4. **看到表单字段**(不是 JSON 编辑器)
|
||
5. 填写参数并点击 "Execute"
|
||
|
||
---
|
||
|
||
## 📁 修改的文件
|
||
|
||
### 路由层
|
||
1. **routers/api.py**
|
||
- 所有接口使用 `Form(...)` 参数
|
||
- 构建 dict 传递给服务层
|
||
|
||
### 服务层
|
||
2. **services/token_service.py**
|
||
- `create_token()` 接受 `Union[Dict, object]`
|
||
- 支持字典访问方式
|
||
|
||
3. **services/file_service.py**
|
||
- `fetch_inner_flow()` 接受 `Union[Dict, object]`
|
||
- 移除 Pydantic 模型依赖
|
||
|
||
4. **services/statement_service.py**
|
||
- `get_bank_statement()` 接受 `Union[Dict, object]`
|
||
- 使用字典访问分页参数
|
||
|
||
---
|
||
|
||
## 🎨 Swagger UI 效果
|
||
|
||
### 显示方式
|
||
```
|
||
Request body
|
||
Content-Type: application/x-www-form-urlencoded
|
||
|
||
Form fields:
|
||
- projectNo: [input]
|
||
- entityName: [input]
|
||
- userId: [input]
|
||
- userName: [input]
|
||
- appId: [input with default: remote_app]
|
||
- appSecretCode: [input]
|
||
- role: [input with default: VIEWER]
|
||
- orgCode: [input]
|
||
- entityId: [optional input]
|
||
- xdRelatedPersons: [optional input]
|
||
- jzDataDateId: [input with default: 0]
|
||
- innerBSStartDateId: [input with default: 0]
|
||
- innerBSEndDateId: [input with default: 0]
|
||
- analysisType: [input with default: -1]
|
||
- departmentCode: [input]
|
||
```
|
||
|
||
---
|
||
|
||
## ⚠️ 注意事项
|
||
|
||
### 1. 不要使用 `json=` 参数
|
||
```python
|
||
# ❌ 错误
|
||
response = requests.post(url, json=data)
|
||
|
||
# ✅ 正确
|
||
response = requests.post(url, data=data)
|
||
```
|
||
|
||
### 2. 可选参数处理
|
||
```python
|
||
# 可选参数使用 Optional[str] = Form(None)
|
||
entityId: Optional[str] = Form(None, description="可选")
|
||
```
|
||
|
||
### 3. 默认值参数
|
||
```python
|
||
# 默认值使用 Form("default_value")
|
||
appId: str = Form("remote_app", description="固定值")
|
||
```
|
||
|
||
---
|
||
|
||
## ✅ 验证清单
|
||
|
||
- [x] 所有接口使用 Form 参数
|
||
- [x] 服务层接受字典参数
|
||
- [x] 移除 Pydantic 模型在路由层的依赖
|
||
- [x] Swagger UI 显示为 form-data
|
||
- [x] 所有测试通过(7/7)
|
||
- [x] 支持 Python requests 调用
|
||
- [x] 支持 curl 命令调用
|
||
|
||
---
|
||
|
||
## 🎉 总结
|
||
|
||
✅ **实现完成**
|
||
|
||
- **传输方式**: `application/x-www-form-urlencoded`
|
||
- **Swagger UI**: 正确显示为 form-data 表单
|
||
- **测试状态**: 7/7 通过
|
||
- **兼容性**: 支持字典和对象两种访问方式
|
||
|
||
**Mock 服务器已准备就绪!** 🚀
|
||
|
||
---
|
||
|
||
**实现人员**: Claude Code
|
||
**实现日期**: 2026-03-03
|
||
**版本**: v1.4.0
|
||
**状态**: ✅ 完成
|