f
This commit is contained in:
158
deploy/sql/Context参数优化说明.md
Normal file
158
deploy/sql/Context参数优化说明.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# Context参数优化说明
|
||||
|
||||
## 优化内容
|
||||
|
||||
将 `ctx context.Context` 从 `ProcessRequests` 方法作为参数传入,而不是在每个 `ProcessXXXRequest` 方法内部创建。
|
||||
|
||||
## 优化原因
|
||||
|
||||
1. **更好的上下文管理**:可以从上层传递 context,支持超时、取消等操作
|
||||
2. **避免重复代码**:不需要在每个方法里都写 `ctx := context.Background()`
|
||||
3. **更好的可追踪性**:可以通过 context 传递请求ID、用户ID等元数据
|
||||
4. **符合Go最佳实践**:context 应该作为第一个参数传递
|
||||
|
||||
## 修改内容
|
||||
|
||||
### 1. ProcessRequests 方法签名修改
|
||||
|
||||
**修改前:**
|
||||
```go
|
||||
func (a *ApiRequestService) ProcessRequests(params []byte, productID string) ([]byte, error) {
|
||||
var ctx, cancel = context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
```
|
||||
|
||||
**修改后:**
|
||||
```go
|
||||
func (a *ApiRequestService) ProcessRequests(ctx context.Context, params []byte, productID string) ([]byte, error) {
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
```
|
||||
|
||||
### 2. PreprocessRequestApi 方法修改
|
||||
|
||||
**修改前:**
|
||||
```go
|
||||
func (a *ApiRequestService) PreprocessRequestApi(params []byte, apiID string) ([]byte, error) {
|
||||
if processor, exists := requestProcessors[apiID]; exists {
|
||||
return processor(a, params)
|
||||
}
|
||||
return nil, errors.New("api请求, 未找到相应的处理程序")
|
||||
}
|
||||
```
|
||||
|
||||
**修改后:**
|
||||
```go
|
||||
func (a *ApiRequestService) PreprocessRequestApi(ctx context.Context, params []byte, apiID string) ([]byte, error) {
|
||||
if processor, exists := requestProcessors[apiID]; exists {
|
||||
return processor(a, ctx, params)
|
||||
}
|
||||
return nil, errors.New("api请求, 未找到相应的处理程序")
|
||||
}
|
||||
```
|
||||
|
||||
### 3. requestProcessors map 类型定义修改
|
||||
|
||||
**修改前:**
|
||||
```go
|
||||
var requestProcessors = map[string]func(*ApiRequestService, []byte) ([]byte, error){
|
||||
```
|
||||
|
||||
**修改后:**
|
||||
```go
|
||||
var requestProcessors = map[string]func(*ApiRequestService, context.Context, []byte) ([]byte, error){
|
||||
```
|
||||
|
||||
### 4. 所有 ProcessXXXRequest 方法签名修改
|
||||
|
||||
**修改前:**
|
||||
```go
|
||||
func (a *ApiRequestService) ProcessYYSYBE08Request(params []byte) ([]byte, error) {
|
||||
ctx := context.Background()
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**修改后:**
|
||||
```go
|
||||
func (a *ApiRequestService) ProcessYYSYBE08Request(ctx context.Context, params []byte) ([]byte, error) {
|
||||
// 移除了 ctx := context.Background()
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### 5. 错误码提取优化
|
||||
|
||||
**修改前:**
|
||||
```go
|
||||
if tianyuanErr, ok := err.(*tianyuanapi.Error); ok {
|
||||
errorCode = fmt.Sprintf("%d", tianyuanErr.Code)
|
||||
}
|
||||
```
|
||||
|
||||
**修改后:**
|
||||
```go
|
||||
if code := tianyuanapi.GetCodeByError(err); code != -1 {
|
||||
errorCode = fmt.Sprintf("%d", code)
|
||||
}
|
||||
```
|
||||
|
||||
## 修改的方法列表(32个)
|
||||
|
||||
所有以下方法都已添加 `ctx context.Context` 作为第一个参数,并移除了内部的 `ctx := context.Background()` 声明:
|
||||
|
||||
1. ProcessPersonEnterpriseProRequest
|
||||
2. ProcessBehaviorRiskScanRequest
|
||||
3. ProcessYYSYBE08Request
|
||||
4. ProcessYYSY09CDRequest
|
||||
5. ProcessFLXG0687Request
|
||||
6. ProcessFLXG3D56Request
|
||||
7. ProcessFLXG0V4BRequest
|
||||
8. ProcessQYGL8271Request
|
||||
9. ProcessIVYZ5733Request
|
||||
10. ProcessIVYZ9A2BRequest
|
||||
11. ProcessJRZQ0A03Request
|
||||
12. ProcessQYGL6F2DRequest
|
||||
13. ProcessJRZQ8203Request
|
||||
14. ProcessJRZQ4AA8Request
|
||||
15. ProcessQCXG7A2BRequest
|
||||
16. ProcessDWBG8B4DRequest
|
||||
17. ProcessDWBG6A2CRequest
|
||||
18. ProcessJRZQ4B6CRequest
|
||||
19. ProcessJRZQ09J8Request
|
||||
20. ProcessJRZQ5E9FRequest
|
||||
21. ProcessQYGL3F8ERequest
|
||||
22. ProcessIVYZ81NCRequest
|
||||
23. ProcessIVYZ7F3ARequest
|
||||
24. ProcessDWBG7F3ARequest
|
||||
25. ProcessJRZQ8A2DRequest
|
||||
26. ProcessYYSY8B1CRequest
|
||||
27. ProcessYYSY7D3ERequest
|
||||
28. ProcessFLXG7E8FRequest
|
||||
29. ProcessIVYZ8I9JRequest
|
||||
30. ProcessJRZQ7F1ARequest
|
||||
31. ProcessIVYZ3P9MRequest
|
||||
32. ProcessJRZQ6F2ARequest
|
||||
|
||||
## 调用方验证
|
||||
|
||||
调用方 `paySuccessNotify.go` 已经正确传递了 `ctx`:
|
||||
|
||||
```go
|
||||
combinedResponse, err := l.svcCtx.ApiRequestService.ProcessRequests(ctx, decryptData, product.Id)
|
||||
```
|
||||
|
||||
## 优势
|
||||
|
||||
1. **统一的上下文管理**:所有API调用共享同一个 context,可以统一控制超时和取消
|
||||
2. **更好的错误追踪**:可以在 context 中传递请求ID、用户ID等信息,方便日志追踪
|
||||
3. **代码更简洁**:不需要在每个方法中重复创建 context
|
||||
4. **符合Go规范**:context 作为第一个参数是 Go 的标准做法
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 所有方法现在都依赖外部传入的 `ctx`,不再内部创建
|
||||
- `ProcessRequests` 方法内部仍然会创建一个带 cancel 的 context,用于控制并发请求的取消
|
||||
- 如果将来需要在 context 中传递元数据(如请求ID、用户ID),可以在调用 `ProcessRequests` 之前设置
|
||||
|
||||
35
deploy/sql/generate_tianyuanapi_models.sh
Normal file
35
deploy/sql/generate_tianyuanapi_models.sh
Normal file
@@ -0,0 +1,35 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 天元API调用记录表 - Model生成脚本
|
||||
|
||||
# 数据库配置(从main.yaml中提取)
|
||||
DB_HOST="ycc_mysql:3306"
|
||||
DB_USER="ycc"
|
||||
DB_PASS="5vg67b3UNHu8"
|
||||
DB_NAME="ycc"
|
||||
MODEL_DIR="../../app/main/model"
|
||||
TEMPLATE_DIR="./template"
|
||||
|
||||
# 生成feature表(已添加cost_price字段)
|
||||
echo "正在生成 feature 表Model..."
|
||||
goctl model mysql datasource -url="$DB_USER:$DB_PASS@tcp($DB_HOST)/$DB_NAME" -table="feature" -dir="$MODEL_DIR" -cache=true --style=goZero --home="$TEMPLATE_DIR"
|
||||
|
||||
# 生成tianyuanapi_call_log表
|
||||
echo "正在生成 tianyuanapi_call_log 表Model..."
|
||||
goctl model mysql datasource -url="$DB_USER:$DB_PASS@tcp($DB_HOST)/$DB_NAME" -table="tianyuanapi_call_log" -dir="$MODEL_DIR" -cache=true --style=goZero --home="$TEMPLATE_DIR"
|
||||
|
||||
echo "========================================="
|
||||
echo "Model生成完成!"
|
||||
echo "========================================="
|
||||
echo "生成的文件:"
|
||||
echo " 1. featureModel_gen.go (已更新)"
|
||||
echo " 2. featureModel.go (已更新)"
|
||||
echo " 3. tianyuanapiCallLogModel_gen.go (新建)"
|
||||
echo " 4. tianyuanapiCallLogModel.go (新建)"
|
||||
echo "========================================="
|
||||
echo "下一步:"
|
||||
echo " 1. 检查生成的Model文件"
|
||||
echo " 2. 更新svc/servicecontext.go,添加新Model的初始化"
|
||||
echo " 3. 在apirequestService.go中添加调用记录逻辑"
|
||||
echo "========================================="
|
||||
|
||||
64
deploy/sql/tianyuanapi_cost_migration.sql
Normal file
64
deploy/sql/tianyuanapi_cost_migration.sql
Normal file
@@ -0,0 +1,64 @@
|
||||
-- ============================================
|
||||
-- Feature表 - 添加成本价字段
|
||||
-- 说明:为 feature 表添加天远API调用成本价字段
|
||||
-- 执行时间:2025-01-13
|
||||
-- ============================================
|
||||
|
||||
-- 添加成本价字段
|
||||
ALTER TABLE `feature`
|
||||
ADD COLUMN `cost_price` decimal(10, 2) DEFAULT 0.00 COMMENT '天远API调用成本价(单位:元)' AFTER `whitelist_price`;
|
||||
|
||||
-- ============================================
|
||||
-- 说明:
|
||||
-- 1. cost_price 默认值为 0.00,表示该feature的成本价为0元
|
||||
-- 2. 后台可以在"功能管理"页面配置每个feature的调用成本
|
||||
-- 3. 成本价用于统计天远API的调用成本
|
||||
-- ============================================
|
||||
|
||||
-- ============================================
|
||||
-- 天远API调用记录表
|
||||
-- 说明:记录每次调用天远API的详细信息
|
||||
-- ============================================
|
||||
|
||||
CREATE TABLE `tianyuanapi_call_log` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`feature_id` varchar(36) NOT NULL COMMENT '功能ID(关联feature表)',
|
||||
`api_id` varchar(50) NOT NULL COMMENT 'API标识(如:YYSYBE08)',
|
||||
`order_id` varchar(36) DEFAULT NULL COMMENT '订单ID(关联order表)',
|
||||
`query_id` varchar(36) DEFAULT NULL COMMENT '查询ID(关联query表)',
|
||||
`call_status` tinyint NOT NULL DEFAULT 0 COMMENT '调用状态:0=失败,1=成功',
|
||||
`call_time` datetime NOT NULL COMMENT '调用时间',
|
||||
`response_time` int DEFAULT NULL COMMENT '响应耗时(毫秒)',
|
||||
`cost_price` decimal(10, 2) DEFAULT 0.00 COMMENT '本次调用成本(成功时从feature.cost_price获取,失败时为0)',
|
||||
`error_code` varchar(50) DEFAULT NULL COMMENT '错误码(失败时记录)',
|
||||
`error_message` varchar(500) DEFAULT NULL COMMENT '错误信息(失败时记录)',
|
||||
`request_params` text DEFAULT NULL COMMENT '请求参数(JSON格式)',
|
||||
`response_data` text DEFAULT NULL COMMENT '响应数据(JSON格式,仅记录关键信息)',
|
||||
`transaction_id` varchar(100) DEFAULT NULL COMMENT '天远API流水号',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`delete_time` datetime DEFAULT NULL COMMENT '删除时间',
|
||||
`del_state` tinyint NOT NULL DEFAULT 0 COMMENT '删除状态:0=未删除,1=已删除',
|
||||
`version` bigint NOT NULL DEFAULT 0 COMMENT '版本号(乐观锁)',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_feature_id` (`feature_id`),
|
||||
KEY `idx_api_id` (`api_id`),
|
||||
KEY `idx_order_id` (`order_id`),
|
||||
KEY `idx_query_id` (`query_id`),
|
||||
KEY `idx_call_status` (`call_status`),
|
||||
KEY `idx_call_time` (`call_time`),
|
||||
KEY `idx_feature_time` (`feature_id`, `call_time`) COMMENT '复合索引:查询某个功能在某段时间的调用记录'
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '天远API调用记录表';
|
||||
|
||||
-- ============================================
|
||||
-- 说明:
|
||||
-- 1. feature_id: 关联到feature表,记录是哪个接口的调用
|
||||
-- 2. api_id: 天远API的接口标识(如:YYSYBE08)
|
||||
-- 3. order_id/query_id: 关联订单或查询,方便追溯
|
||||
-- 4. call_status: 调用状态,成功=1,失败=0
|
||||
-- 5. cost_price: 成本价,成功时为feature.cost_price,失败时为0
|
||||
-- 6. error_code/error_message: 失败时记录错误信息
|
||||
-- 7. request_params/response_data: 请求和响应数据(可选择性记录)
|
||||
-- 8. transaction_id: 天远API返回的流水号
|
||||
-- 9. 无论成功失败都会记录,方便统计分析
|
||||
-- ============================================
|
||||
183
deploy/sql/优化后的批量修改说明.md
Normal file
183
deploy/sql/优化后的批量修改说明.md
Normal file
@@ -0,0 +1,183 @@
|
||||
# 优化后的批量修改说明 - 使用ctx参数
|
||||
|
||||
## 优化说明
|
||||
|
||||
根据建议,我们通过 `ProcessRequests` 方法传入 `ctx context.Context` 参数,而不是在每个方法内部创建 `context.Background()`。
|
||||
|
||||
这样的好处:
|
||||
1. **符合Go最佳实践**:Context应该从上层传入
|
||||
2. **更好的控制**:可以统一控制请求超时、取消等
|
||||
3. **代码更简洁**:不需要在每个方法中重复创建context
|
||||
4. **更好的追踪**:可以统一传递追踪信息
|
||||
|
||||
## 已完成的修改
|
||||
|
||||
### 1. 修改了 ProcessRequests 方法签名
|
||||
```go
|
||||
func (a *ApiRequestService) ProcessRequests(ctx context.Context, params []byte, productID string) ([]byte, error)
|
||||
```
|
||||
- 移除了内部的 `ctx, cancel = context.WithCancel(context.Background())`
|
||||
- 直接使用外部传入的 `ctx`
|
||||
|
||||
### 2. 定义了 RequestProcessor 类型
|
||||
```go
|
||||
type RequestProcessor func(ctx context.Context, a *ApiRequestService, params []byte) ([]byte, error)
|
||||
```
|
||||
|
||||
### 3. 更新了 requestProcessors 映射
|
||||
所有方法签名的类型都更新为接收 `context.Context` 参数
|
||||
|
||||
### 4. 修改了 PreprocessRequestApi 方法
|
||||
```go
|
||||
func (a *ApiRequestService) PreprocessRequestApi(ctx context.Context, params []byte, apiID string) ([]byte, error) {
|
||||
if processor, exists := requestProcessors[apiID]; exists {
|
||||
return processor(ctx, a, params) // 传递ctx
|
||||
}
|
||||
return nil, errors.New("api请求, 未找到相应的处理程序")
|
||||
}
|
||||
```
|
||||
|
||||
### 5. 修改了示例方法
|
||||
- `ProcessYYSYBE08Request` ✅ - 已添加 `ctx context.Context` 参数
|
||||
- `ProcessFLXG0V4BRequest` ✅ - 已添加 `ctx context.Context` 参数
|
||||
|
||||
## 需要完成的修改
|
||||
|
||||
现在还需要修改剩余30个方法的签名,在每个方法签名的 `params` 参数前添加 `ctx context.Context` 参数。
|
||||
|
||||
### 方法1:使用批量修改脚本(推荐)
|
||||
|
||||
#### Linux/Mac 环境
|
||||
```bash
|
||||
cd ycc-proxy-server
|
||||
chmod +x deploy/sql/批量修改方法签名.sh
|
||||
./deploy/sql/批量修改方法签名.sh
|
||||
```
|
||||
|
||||
这个脚本会:
|
||||
1. 备份 `apirequestService.go` 文件
|
||||
2. 批量修改31个方法的签名
|
||||
3. 显示修改统计
|
||||
|
||||
### 方法2:使用IDE查找替换(Windows环境推荐)
|
||||
|
||||
#### 步骤1:在IDE中打开查找替换
|
||||
打开 `apirequestService.go`,按 `Ctrl+H` 打开查找替换
|
||||
|
||||
#### 步骤2:查找并替换
|
||||
**查找内容:**
|
||||
```text
|
||||
func (a *ApiRequestService) Process(params []byte) ([]byte, error)
|
||||
```
|
||||
|
||||
**替换为:**
|
||||
```text
|
||||
func (a *ApiRequestService) Process(ctx context.Context, params []byte) ([]byte, error)
|
||||
```
|
||||
|
||||
**注意:**
|
||||
- 这个模式会匹配所有 `Process*Request` 方法
|
||||
- 点击"全部替换"即可
|
||||
|
||||
#### 步骤3:验证替换
|
||||
替换后,检查是否所有31个方法都成功修改。如果没有修改成功,可能是因为:
|
||||
1. 某些方法已经修改过了
|
||||
2. 方法签名格式有差异
|
||||
|
||||
### 方法3:逐个手动修改
|
||||
|
||||
如果批量方法不适用,可以逐个修改。需要修改的方法列表:
|
||||
|
||||
#### 已修改 ✅
|
||||
1. ProcessYYSYBE08Request
|
||||
2. ProcessFLXG0V4BRequest
|
||||
|
||||
#### 待修改 ⏳
|
||||
1. ProcessPersonEnterpriseProRequest (第312行)
|
||||
2. ProcessFLXG0687Request (第671行)
|
||||
3. ProcessFLXG3D56Request (第699行)
|
||||
4. ProcessIVYZ5733Request (第754行)
|
||||
5. ProcessIVYZ9A2BRequest (第810行)
|
||||
6. ProcessJRZQ0A03Request (第922行)
|
||||
7. ProcessJRZQ8203Request (第979行)
|
||||
8. ProcessJRZQ4AA8Request (第1036行)
|
||||
9. ProcessQYGL8271Request (第1085行)
|
||||
10. ProcessQYGL6F2DRequest (第1150行)
|
||||
11. ProcessQCXG7A2BRequest (第1191行)
|
||||
12. ProcessYYSY09CDRequest (第1211行)
|
||||
13. ProcessBehaviorRiskScanRequest (第1247行)
|
||||
14. ProcessDWBG8B4DRequest (第1314行)
|
||||
15. ProcessDWBG6A2CRequest (第1339行)
|
||||
16. ProcessJRZQ4B6CRequest (第1363行)
|
||||
17. ProcessJRZQ09J8Request (第1387行)
|
||||
18. ProcessJRZQ5E9FRequest (第1411行)
|
||||
19. ProcessQYGL3F8ERequest (第1433行)
|
||||
20. ProcessIVYZ81NCRequest (第1461行)
|
||||
21. ProcessIVYZ7F3ARequest (第1482行)
|
||||
22. ProcessDWBG7F3ARequest (第1505行)
|
||||
23. ProcessJRZQ8A2DRequest (第1528行)
|
||||
24. ProcessYYSY8B1CRequest (第1550行)
|
||||
25. ProcessYYSY7D3ERequest (第1569行)
|
||||
26. ProcessFLXG7E8FRequest (第1590行)
|
||||
27. ProcessIVYZ8I9JRequest (第1613行)
|
||||
28. ProcessJRZQ7F1ARequest (第1636行)
|
||||
29. ProcessIVYZ3P9MRequest (第1659行)
|
||||
30. ProcessJRZQ6F2ARequest (第1680行)
|
||||
|
||||
每个方法需要做的修改:
|
||||
|
||||
**修改前:**
|
||||
```go
|
||||
func (a *ApiRequestService) ProcessMethodName(params []byte) ([]byte, error) {
|
||||
// 方法体
|
||||
}
|
||||
```
|
||||
|
||||
**修改后:**
|
||||
```go
|
||||
func (a *ApiRequestService) ProcessMethodName(ctx context.Context, params []byte) ([]byte, error) {
|
||||
// 方法体
|
||||
}
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **不需要在每个方法中添加 `ctx := context.Background()`**
|
||||
- 因为现在通过参数传入
|
||||
- 使用 `ctx context.Context` 参数即可
|
||||
|
||||
2. **`callTianyuanApiWithLog` 方法已经支持传入 ctx**
|
||||
- 如果第一个参数为空字符串 `""`,会自动从缓存获取featureID
|
||||
- 否则使用传入的featureID
|
||||
|
||||
3. **不需要修改方法内部的 API 调用**
|
||||
- 因为我们已经修改了部分方法使用 `callTianyuanApiWithLog`
|
||||
- 批量替换后,记得将所有 `a.tianyuanapi.CallInterface` 替换为 `a.callTianyuanApiWithLog(ctx, "",`
|
||||
|
||||
## 完成后验证
|
||||
|
||||
1. **编译项目**
|
||||
```bash
|
||||
cd ycc-proxy-server
|
||||
go build ./...
|
||||
```
|
||||
|
||||
2. **检查编译错误**
|
||||
- 主要是方法签名不匹配的错误
|
||||
- 如果有错误,检查哪些方法没有正确修改
|
||||
|
||||
3. **运行测试**
|
||||
- 发起几个API请求
|
||||
- 检查 `tianyuanapi_call_log` 表
|
||||
- 验证日志是否正确记录
|
||||
|
||||
## 优势总结
|
||||
|
||||
使用 `ctx` 参数的方式:
|
||||
|
||||
✅ **代码更简洁** - 不需要重复创建context
|
||||
✅ **更好的控制** - 可以统一管理超时、取消
|
||||
✅ **符合最佳实践** - Context应该从上层传入
|
||||
✅ **便于追踪** - 可以在ctx中传递追踪信息
|
||||
✅ **便于测试** - 测试时可以传入自定义的ctx
|
||||
|
||||
135
deploy/sql/利润统计API成本计入说明.md
Normal file
135
deploy/sql/利润统计API成本计入说明.md
Normal file
@@ -0,0 +1,135 @@
|
||||
# 利润统计API成本计入说明
|
||||
|
||||
## 修改内容
|
||||
|
||||
在后台统计面板的利润统计部分,将API调用成本计入成本计算中。
|
||||
|
||||
## 修改位置
|
||||
|
||||
文件:`ycc-proxy-server/app/main/api/internal/logic/admin_dashboard/admingetdashboardstatisticslogic.go`
|
||||
|
||||
方法:`calculateProfitStatistics`
|
||||
|
||||
## 修改详情
|
||||
|
||||
### 1. 今日利润计算
|
||||
|
||||
**修改前:**
|
||||
```go
|
||||
// 今日利润 = 营收 - 佣金 - 返利 - 税务成本 + 提现收税
|
||||
stats.TodayProfit = todayRevenue - todayCommission - todayRebate - todayCompanyTax + todayTaxIncome
|
||||
```
|
||||
|
||||
**修改后:**
|
||||
```go
|
||||
// 今日API调用成本
|
||||
todayApiCost := 0.0
|
||||
if l.svcCtx.TianyuanapiCallLogService != nil {
|
||||
todayApiStats, err := l.svcCtx.TianyuanapiCallLogService.GetStatistics(l.ctx, service.StatisticsFilter{
|
||||
StartDate: todayStart,
|
||||
EndDate: todayEnd,
|
||||
})
|
||||
if err != nil {
|
||||
logx.Errorf("获取今日API调用成本失败: %v", err)
|
||||
} else {
|
||||
todayApiCost = todayApiStats.TotalCost
|
||||
}
|
||||
}
|
||||
// 今日利润 = 营收 - 佣金 - 返利 - 税务成本 - API调用成本 + 提现收税
|
||||
stats.TodayProfit = todayRevenue - todayCommission - todayRebate - todayCompanyTax - todayApiCost + todayTaxIncome
|
||||
```
|
||||
|
||||
### 2. 当月利润计算
|
||||
|
||||
**修改前:**
|
||||
```go
|
||||
// 当月利润
|
||||
stats.MonthProfit = monthRevenue - monthCommission - monthRebate - monthCompanyTax + monthTaxIncome
|
||||
```
|
||||
|
||||
**修改后:**
|
||||
```go
|
||||
// 当月API调用成本
|
||||
monthApiCost := 0.0
|
||||
if l.svcCtx.TianyuanapiCallLogService != nil {
|
||||
monthApiStats, err := l.svcCtx.TianyuanapiCallLogService.GetStatistics(l.ctx, service.StatisticsFilter{
|
||||
StartDate: monthStart,
|
||||
EndDate: monthEnd,
|
||||
})
|
||||
if err != nil {
|
||||
logx.Errorf("获取当月API调用成本失败: %v", err)
|
||||
} else {
|
||||
monthApiCost = monthApiStats.TotalCost
|
||||
}
|
||||
}
|
||||
// 当月利润
|
||||
stats.MonthProfit = monthRevenue - monthCommission - monthRebate - monthCompanyTax - monthApiCost + monthTaxIncome
|
||||
```
|
||||
|
||||
### 3. 总利润计算
|
||||
|
||||
**修改前:**
|
||||
```go
|
||||
// 总利润
|
||||
stats.TotalProfit = totalRevenue - totalCommission - totalRebate - totalCompanyTax + totalTaxIncome
|
||||
```
|
||||
|
||||
**修改后:**
|
||||
```go
|
||||
// 总API调用成本
|
||||
totalApiCost := 0.0
|
||||
if l.svcCtx.TianyuanapiCallLogService != nil {
|
||||
totalApiStats, err := l.svcCtx.TianyuanapiCallLogService.GetStatistics(l.ctx, service.StatisticsFilter{})
|
||||
if err != nil {
|
||||
logx.Errorf("获取总API调用成本失败: %v", err)
|
||||
} else {
|
||||
totalApiCost = totalApiStats.TotalCost
|
||||
}
|
||||
}
|
||||
// 总利润
|
||||
stats.TotalProfit = totalRevenue - totalCommission - totalRebate - totalCompanyTax - totalApiCost + totalTaxIncome
|
||||
```
|
||||
|
||||
## 利润计算公式
|
||||
|
||||
修改后的利润计算公式为:
|
||||
|
||||
```
|
||||
利润 = 营收 - 佣金 - 返利 - 税务成本 - API调用成本 + 提现收税
|
||||
```
|
||||
|
||||
其中:
|
||||
- **营收**:订单金额总和(status = 'paid')
|
||||
- **佣金**:代理佣金总和(status != 3)
|
||||
- **返利**:代理返利总和(status != 3)
|
||||
- **税务成本**:订单金额的 6%
|
||||
- **API调用成本**:天元API成功调用的成本总和(从 `tianyuanapi_call_log` 表统计)
|
||||
- **提现收税**:代理提现税总和(tax_status = 2)
|
||||
|
||||
## API调用成本统计说明
|
||||
|
||||
API调用成本通过 `TianyuanapiCallLogService.GetStatistics` 方法获取:
|
||||
|
||||
1. **今日API调用成本**:统计 `call_time >= todayStart AND call_time < todayEnd` 的成功调用成本
|
||||
2. **当月API调用成本**:统计 `call_time >= monthStart AND call_time < monthEnd` 的成功调用成本
|
||||
3. **总API调用成本**:统计所有成功调用的成本
|
||||
|
||||
**注意**:只有成功调用(`call_status = 1`)才会计入成本,失败调用不计成本。
|
||||
|
||||
## 错误处理
|
||||
|
||||
如果获取API调用成本失败,会记录错误日志,但不会影响利润计算(API成本默认为0),确保统计功能的稳定性。
|
||||
|
||||
## 依赖项
|
||||
|
||||
- `TianyuanapiCallLogService`:需要在 `servicecontext.go` 中初始化
|
||||
- `tianyuanapi_call_log` 表:需要已创建并包含调用记录数据
|
||||
|
||||
## 验证
|
||||
|
||||
修改完成后,可以通过以下方式验证:
|
||||
|
||||
1. 查看后台统计面板的利润统计数据
|
||||
2. 检查日志,确认API调用成本是否正确获取
|
||||
3. 对比修改前后的利润数据,确认API成本已正确计入
|
||||
|
||||
149
deploy/sql/利润统计面板改造说明.md
Normal file
149
deploy/sql/利润统计面板改造说明.md
Normal file
@@ -0,0 +1,149 @@
|
||||
# 利润统计面板改造说明
|
||||
|
||||
## 改造内容
|
||||
|
||||
将利润统计从原来的卡片布局改为右侧栏面板,并展示详细的成本和收入明细。
|
||||
|
||||
## 修改文件
|
||||
|
||||
### 1. 后端API定义
|
||||
|
||||
**文件:** `ycc-proxy-server/app/main/api/desc/admin/dashboard.api`
|
||||
|
||||
**修改内容:**
|
||||
- 在 `AdminProfitStatistics` 中添加了三个明细字段:
|
||||
- `TodayDetail AdminProfitDetail` - 今日明细
|
||||
- `MonthDetail AdminProfitDetail` - 当月明细
|
||||
- `TotalDetail AdminProfitDetail` - 总计明细
|
||||
- 新增 `AdminProfitDetail` 类型,包含:
|
||||
- `Revenue` - 营收
|
||||
- `Commission` - 佣金
|
||||
- `Rebate` - 返利
|
||||
- `CompanyTax` - 税务成本
|
||||
- `ApiCost` - API调用成本
|
||||
- `TaxIncome` - 提现收税
|
||||
- `Profit` - 利润
|
||||
- `ProfitRate` - 利润率
|
||||
|
||||
### 2. 后端逻辑
|
||||
|
||||
**文件:** `ycc-proxy-server/app/main/api/internal/logic/admin_dashboard/admingetdashboardstatisticslogic.go`
|
||||
|
||||
**修改内容:**
|
||||
- 在 `calculateProfitStatistics` 方法中,为今日、当月、总计三个时间范围都填充了明细数据
|
||||
- 明细数据包含所有成本和收入的详细金额
|
||||
|
||||
### 3. 前端类型定义
|
||||
|
||||
**文件:** `ycc-proxy-admin/apps/web-antd/src/api/dashboard/dashboard.ts`
|
||||
|
||||
**修改内容:**
|
||||
- 添加了 `ProfitDetail` 接口
|
||||
- 更新了 `ProfitStatistics` 接口,添加三个明细字段
|
||||
|
||||
### 4. 前端主页面
|
||||
|
||||
**文件:** `ycc-proxy-admin/apps/web-antd/src/views/dashboard/analytics/index.vue`
|
||||
|
||||
**修改内容:**
|
||||
- 移除了利润统计卡片(从4列布局改为3列布局)
|
||||
- 改为左右布局:左侧是统计卡片和图表,右侧是利润统计面板
|
||||
- 添加了响应式布局,小屏幕下右侧面板会移到下方
|
||||
|
||||
### 5. 前端利润面板组件(新建)
|
||||
|
||||
**文件:** `ycc-proxy-admin/apps/web-antd/src/views/dashboard/analytics/analytics-profit-panel.vue`
|
||||
|
||||
**功能:**
|
||||
- 展示利润总额和利润率
|
||||
- 通过Tab切换今日/当月/总计
|
||||
- 详细展示收入明细(营收、提现收税)
|
||||
- 详细展示成本明细(代理佣金、代理返利、税务成本、API调用成本)
|
||||
- 分别计算收入合计和成本合计
|
||||
|
||||
## 布局说明
|
||||
|
||||
### 桌面端(>1200px)
|
||||
```
|
||||
┌─────────────────────────────────┬──────────────┐
|
||||
│ │ │
|
||||
│ 统计卡片(3列) │ 利润统计 │
|
||||
│ │ 面板 │
|
||||
│ 趋势图表 │ (固定) │
|
||||
│ │ │
|
||||
└─────────────────────────────────┴──────────────┘
|
||||
```
|
||||
|
||||
### 移动端(≤1200px)
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ 统计卡片(3列) │
|
||||
│ │
|
||||
│ 趋势图表 │
|
||||
│ │
|
||||
│ 利润统计面板 │
|
||||
│ (移到下方) │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 明细数据说明
|
||||
|
||||
### 收入项
|
||||
1. **营收**:订单金额总和(status = 'paid')
|
||||
2. **提现收税**:代理提现税总和(tax_status = 2)
|
||||
|
||||
### 成本项
|
||||
1. **代理佣金**:代理佣金总和(status != 3)
|
||||
2. **代理返利**:代理返利总和(status != 3)
|
||||
3. **税务成本**:订单金额的 6%
|
||||
4. **API调用成本**:天元API成功调用的成本总和
|
||||
|
||||
### 利润计算
|
||||
```
|
||||
利润 = 营收 + 提现收税 - 代理佣金 - 代理返利 - 税务成本 - API调用成本
|
||||
利润率 = (利润 / 营收) × 100%
|
||||
```
|
||||
|
||||
## 使用步骤
|
||||
|
||||
### 1. 生成API类型(后端)
|
||||
|
||||
运行API生成脚本:
|
||||
```bash
|
||||
cd ycc-proxy-server
|
||||
# 运行gen_api脚本生成types
|
||||
```
|
||||
|
||||
### 2. 编译验证
|
||||
|
||||
```bash
|
||||
# 后端编译
|
||||
cd ycc-proxy-server
|
||||
go build
|
||||
|
||||
# 前端编译
|
||||
cd ycc-proxy-admin
|
||||
npm run build
|
||||
```
|
||||
|
||||
### 3. 测试验证
|
||||
|
||||
1. 打开后台统计面板
|
||||
2. 查看右侧利润统计面板
|
||||
3. 切换今日/当月/总计Tab
|
||||
4. 验证各项成本和收入明细是否正确显示
|
||||
5. 验证收入合计和成本合计计算是否正确
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **必须运行gen_api脚本**:修改了API定义后,需要运行gen_api脚本生成新的types.go文件
|
||||
2. **数据准确性**:确保API调用成本数据已正确记录在 `tianyuanapi_call_log` 表中
|
||||
3. **响应式布局**:在小屏幕设备上,右侧面板会自动移到下方,确保良好的用户体验
|
||||
|
||||
## UI特性
|
||||
|
||||
- **固定定位**:右侧面板在桌面端使用sticky定位,滚动时保持可见
|
||||
- **颜色区分**:收入用绿色(+),成本用红色(-),利润根据正负显示不同颜色
|
||||
- **Tab切换**:可以快速切换查看不同时间范围的明细
|
||||
- **合计显示**:分别显示收入合计和成本合计,方便查看
|
||||
|
||||
159
deploy/sql/天元API调用记录修改说明.md
Normal file
159
deploy/sql/天元API调用记录修改说明.md
Normal file
@@ -0,0 +1,159 @@
|
||||
# 天元API调用记录功能 - 代码修改说明
|
||||
|
||||
## 概述
|
||||
本文档说明如何修改 `apirequestService.go`,为每次天元API调用添加记录功能。
|
||||
|
||||
## 已完成的修改
|
||||
|
||||
### 1. 数据库层面
|
||||
- ✅ 创建 `tianyuanapi_cost_migration.sql` 脚本
|
||||
- 在 `feature` 表添加 `cost_price` 字段
|
||||
- 创建 `tianyuanapi_call_log` 表
|
||||
|
||||
### 2. Service层面
|
||||
- ✅ 创建 `tianyuanapiCallLogService.go` 服务
|
||||
- `RecordCall()` - 记录API调用
|
||||
- `GetStatistics()` - 获取统计信息
|
||||
|
||||
### 3. Model层面
|
||||
- ⏳ 需要执行 `generate_tianyuanapi_models.sh` 生成Model代码
|
||||
|
||||
### 4. ApiRequestService修改
|
||||
- ✅ 添加 `tianyuanapiCallLogService` 字段
|
||||
- ✅ 修改构造函数,添加 `tianyuanapiCallLogService` 参数
|
||||
- ✅ 创建 `callTianyuanApiWithLog()` 辅助方法
|
||||
|
||||
## 待完成的修改
|
||||
|
||||
### 1. 执行SQL脚本
|
||||
```bash
|
||||
# 在数据库中执行迁移脚本
|
||||
mysql -u root -p ycc < ycc-proxy-server/deploy/sql/tianyuanapi_cost_migration.sql
|
||||
```
|
||||
|
||||
### 2. 生成Model代码
|
||||
```bash
|
||||
cd ycc-proxy-server/deploy/sql
|
||||
bash generate_tianyuanapi_models.sh
|
||||
```
|
||||
|
||||
### 3. 更新 servicecontext.go
|
||||
在 `svc/servicecontext.go` 中添加:
|
||||
```go
|
||||
// 初始化Model
|
||||
tianyuanapiCallLogModel := model.NewTianyuanapiCallLogModel(db, cacheConf)
|
||||
|
||||
// 初始化Service
|
||||
tianyuanapiCallLogService := service.NewTianyuanapiCallLogService(
|
||||
tianyuanapiCallLogModel,
|
||||
featureModel,
|
||||
)
|
||||
|
||||
// 修改ApiRequestService初始化
|
||||
apiRequestService := service.NewApiRequestService(
|
||||
c,
|
||||
featureModel,
|
||||
productFeatureModel,
|
||||
userFeatureWhitelistModel,
|
||||
tianyuanapi,
|
||||
tianyuanapiCallLogService, // 新增参数
|
||||
)
|
||||
|
||||
// 在ServiceContext结构体中添加字段
|
||||
TianyuanapiCallLogModel model.TianyuanapiCallLogModel
|
||||
TianyuanapiCallLogService *service.TianyuanapiCallLogService
|
||||
|
||||
// 在返回的ServiceContext中添加
|
||||
TianyuanapiCallLogModel: tianyuanapiCallLogModel,
|
||||
TianyuanapiCallLogService: tianyuanapiCallLogService,
|
||||
```
|
||||
|
||||
### 4. 修改API调用方法示例
|
||||
|
||||
#### 原代码:
|
||||
```go
|
||||
resp, err := a.callTianyuanApiWithLog(ctx, "", "QYGLB4C0", map[string]interface{}{
|
||||
"id_card": idCard.String(),
|
||||
})
|
||||
```
|
||||
|
||||
#### 修改后:
|
||||
```go
|
||||
resp, err := a.callTianyuanApiWithLog(ctx, featureID, "QYGLB4C0", map[string]interface{}{
|
||||
"id_card": idCard.String(),
|
||||
})
|
||||
```
|
||||
|
||||
### 需要修改的方法列表(共32个)
|
||||
|
||||
1. `ProcessPersonEnterpriseProRequest` - 需要修改2处
|
||||
- 第253行:`QYGLB4C0` - 主接口
|
||||
- 第455行:`QYGL8271` - 涉诉信息查询
|
||||
|
||||
2. `ProcessFLXG0V4BRequest` - 第586行:`FLXG0V4B`
|
||||
3. `ProcessFLXG0687Request` - 第608行:`FLXG0687`
|
||||
4. `ProcessFLXG3D56Request` - 第638行:`FLXG3D56`
|
||||
5. `ProcessIVYZ5733Request` - 第692行:`IVYZ5733`
|
||||
6. `ProcessIVYZ9A2BRequest` - 第748行:`IVYZ9A2B`
|
||||
7. `ProcessYYSYBE08Request` - 第819行:`YYSYBE08`
|
||||
8. `ProcessJRZQ0A03Request` - 第861行:`JRZQ0A03`
|
||||
9. `ProcessJRZQ8203Request` - 第918行:`JRZQ8203`
|
||||
10. `ProcessJRZQ4AA8Request` - 第975行:`JRZQ4AA8`
|
||||
11. `ProcessQYGL8271Request` - 第1024行:`QYGL8271`
|
||||
12. `ProcessQYGL6F2DRequest` - 第1082行:`QYGL6F2D`
|
||||
13. `ProcessQCXG7A2BRequest` - 第1123行:`QCXG7A2B`
|
||||
14. `ProcessYYSY09CDRequest` - 第1143行:`YYSY09CD`
|
||||
15. `ProcessDWBG8B4DRequest` - 第1254行:`DWBG8B4D`
|
||||
16. `ProcessDWBG6A2CRequest` - 第1279行:`DWBG6A2C`
|
||||
17. `ProcessJRZQ4B6CRequest` - 第1303行:`JRZQ4B6C`
|
||||
18. `ProcessJRZQ09J8Request` - 第1327行:`JRZQ09J8`
|
||||
19. `ProcessJRZQ5E9FRequest` - 第1351行:`JRZQ5E9F`
|
||||
20. `ProcessQYGL3F8ERequest` - 第1373行:`QYGL3F8E`
|
||||
21. `ProcessIVYZ81NCRequest` - 第1393行:`IVYZ81NC`
|
||||
22. `ProcessIVYZ7F3ARequest` - 第1414行:`IVYZ7F3A`
|
||||
23. `ProcessDWBG7F3ARequest` - 第1437行:`DWBG7F3A`
|
||||
24. `ProcessJRZQ8A2DRequest` - 第1460行:`JRZQ8A2D`
|
||||
25. `ProcessYYSY8B1CRequest` - 第1482行:`YYSY8B1C`
|
||||
26. `ProcessYYSY7D3ERequest` - 第1501行:`YYSY7D3E`
|
||||
27. `ProcessFLXG7E8FRequest` - 第1522行:`FLXG7E8F`
|
||||
28. `ProcessIVYZ8I9JRequest` - 第1545行:`IVYZ8I9J`
|
||||
29. `ProcessJRZQ7F1ARequest` - 第1568行:`JRZQ7F1A`
|
||||
30. `ProcessIVYZ3P9MRequest` - 第1591行:`IVYZ3P9M`
|
||||
31. `ProcessJRZQ6F2ARequest` - 第1612行:`JRZQ6F2A`
|
||||
|
||||
### 注意事项
|
||||
|
||||
1. **featureID获取**:每个方法中已经有了 `feature` 对象,直接使用 `feature.Id` 即可
|
||||
2. **context传递**:需要从方法签名中获取 `ctx context.Context` 参数
|
||||
3. **错误处理**:`callTianyuanApiWithLog` 已经包含了错误处理,无需额外处理
|
||||
4. **批量修改建议**:可以使用查找替换功能批量修改
|
||||
- 查找:`a.callTianyuanApiWithLog(ctx, "", "`
|
||||
- 替换为:`a.callTianyuanApiWithLog(ctx, feature.Id, "`
|
||||
|
||||
## 统计功能使用示例
|
||||
|
||||
```go
|
||||
// 获取某个功能在某个时间段的调用统计
|
||||
filter := StatisticsFilter{
|
||||
FeatureID: "feature-id-123",
|
||||
StartDate: time.Now().AddDate(0, 0, -30), // 30天前
|
||||
EndDate: time.Now(),
|
||||
}
|
||||
stats, err := ctx.TianyuanapiCallLogService.GetStatistics(context.Background(), filter)
|
||||
if err == nil {
|
||||
fmt.Printf("总调用次数: %d\n", stats.TotalCalls)
|
||||
fmt.Printf("成功次数: %d\n", stats.SuccessCalls)
|
||||
fmt.Printf("失败次数: %d\n", stats.FailedCalls)
|
||||
fmt.Printf("总成本: %.2f元\n", stats.TotalCost)
|
||||
}
|
||||
```
|
||||
|
||||
## 验证步骤
|
||||
|
||||
1. 执行SQL脚本,检查表是否创建成功
|
||||
2. 运行Model生成脚本,检查Model文件是否生成
|
||||
3. 编译项目,检查是否有编译错误
|
||||
4. 运行项目,发起一个API请求
|
||||
5. 检查 `tianyuanapi_call_log` 表,验证记录是否正确插入
|
||||
6. 检查成本价是否正确计算(成功调用有成本,失败调用成本为0)
|
||||
|
||||
297
deploy/sql/天元API调用记录功能完成总结.md
Normal file
297
deploy/sql/天元API调用记录功能完成总结.md
Normal file
@@ -0,0 +1,297 @@
|
||||
# 天元API调用记录功能 - 实施总结
|
||||
|
||||
## 功能概述
|
||||
|
||||
本功能实现了天元API调用的成本记录,包括:
|
||||
1. 在 `feature` 表添加 `cost_price` 字段,存储每个接口的成本价
|
||||
2. 创建 `tianyuanapi_call_log` 表,记录每次API调用的详细信息
|
||||
3. 无论成功失败都记录,但只有成功调用才计算成本
|
||||
4. 提供统计功能,可查询时间段内的调用次数和总成本
|
||||
|
||||
## 已完成的工作
|
||||
|
||||
### 1. 数据库层面 ✅
|
||||
|
||||
**文件:** `ycc-proxy-server/deploy/sql/tianyuanapi_cost_migration.sql`
|
||||
|
||||
**修改内容:**
|
||||
- 在 `feature` 表添加 `cost_price` 字段(decimal(10, 2),默认0.00)
|
||||
- 创建 `tianyuanapi_call_log` 表,包含以下字段:
|
||||
- `feature_id`: 关联feature表
|
||||
- `api_id`: 天元API标识(如:YYSYBE08)
|
||||
- `order_id`: 关联订单(可选)
|
||||
- `query_id`: 关联查询(可选)
|
||||
- `call_status`: 调用状态(0=失败,1=成功)
|
||||
- `call_time`: 调用时间
|
||||
- `response_time`: 响应耗时(毫秒)
|
||||
- `cost_price`: 本次调用成本(成功时有值,失败为0)
|
||||
- `error_code`: 错误码(失败时)
|
||||
- `error_message`: 错误信息(失败时)
|
||||
- `request_params`: 请求参数(JSON)
|
||||
- `response_data`: 响应数据(JSON,截取前1000字符)
|
||||
- `transaction_id`: 天元API流水号
|
||||
|
||||
**索引设计:**
|
||||
- `idx_feature_id`: 按feature_id查询
|
||||
- `idx_api_id`: 按api_id查询
|
||||
- `idx_order_id`: 按order_id查询
|
||||
- `idx_query_id`: 按query_id查询
|
||||
- `idx_call_status`: 按调用状态查询
|
||||
- `idx_call_time`: 按调用时间查询
|
||||
- `idx_feature_time`: 复合索引(feature_id + call_time)
|
||||
|
||||
### 2. Service层面 ✅
|
||||
|
||||
**文件:** `ycc-proxy-server/app/main/api/internal/service/tianyuanapiCallLogService.go`
|
||||
|
||||
**新增方法:**
|
||||
1. `RecordCall(ctx context.Context, opts CallLogOptions) error`
|
||||
- 记录API调用
|
||||
- 自动获取feature的成本价
|
||||
- 成功时记录成本,失败时成本为0
|
||||
- 异步记录,不影响主流程
|
||||
|
||||
2. `GetStatistics(ctx context.Context, filter StatisticsFilter) (*Statistics, error)`
|
||||
- 获取统计信息
|
||||
- 支持按feature_id、api_id、时间范围过滤
|
||||
- 返回:总调用次数、成功次数、失败次数、总成本
|
||||
|
||||
### 3. ApiRequestService修改 ✅
|
||||
|
||||
**文件:** `ycc-proxy-server/app/main/api/internal/service/apirequestService.go`
|
||||
|
||||
**新增字段:**
|
||||
- `tianyuanapiCallLogService *TianyuanapiCallLogService`
|
||||
- `apiFeatureMapCache map[string]string` - apiID到featureID的缓存
|
||||
- `apiFeatureMapMutex sync.RWMutex` - 缓存读写锁
|
||||
|
||||
**新增方法:**
|
||||
1. `callTianyuanApiWithLog(ctx context.Context, featureID, apiID string, params map[string]interface{}) (*tianyuanapi.Response, error)`
|
||||
- 调用天元API
|
||||
- 记录调用开始时间
|
||||
- 计算响应耗时
|
||||
- 异步记录调用日志
|
||||
- 返回响应和错误
|
||||
|
||||
2. 在 `ProcessRequests` 方法中构建 `apiID -> featureID` 映射缓存
|
||||
|
||||
**修改的方法(示例):**
|
||||
- `ProcessYYSYBE08Request` - 已修改
|
||||
- `ProcessFLXG0V4BRequest` - 已修改
|
||||
|
||||
**待修改的方法(30个):**
|
||||
剩余30个方法需要将 `a.callTianyuanApiWithLog(ctx, "", "API名称", ...)`
|
||||
替换为 `a.callTianyuanApiWithLog(ctx, "", "API名称", ...)`
|
||||
|
||||
详细列表见:`批量替换API调用说明.md`
|
||||
|
||||
### 4. ServiceContext修改 ✅
|
||||
|
||||
**文件:** `ycc-proxy-server/app/main/api/internal/svc/servicecontext.go`
|
||||
|
||||
**新增模型:**
|
||||
```go
|
||||
TianyuanapiCallLogModel model.TianyuanapiCallLogModel
|
||||
TianyuanapiCallLogService *service.TianyuanapiCallLogService
|
||||
```
|
||||
|
||||
**新增初始化:**
|
||||
```go
|
||||
tianyuanapiCallLogModel := model.NewTianyuanapiCallLogModel(db, cacheConf)
|
||||
tianyuanapiCallLogService := service.NewTianyuanapiCallLogService(tianyuanapiCallLogModel, featureModel)
|
||||
```
|
||||
|
||||
**修改ApiRequestService初始化:**
|
||||
```go
|
||||
apiRequestService := service.NewApiRequestService(
|
||||
c,
|
||||
featureModel,
|
||||
productFeatureModel,
|
||||
userFeatureWhitelistModel,
|
||||
tianyuanapi,
|
||||
tianyuanapiCallLogService, // 新增参数
|
||||
)
|
||||
```
|
||||
|
||||
### 5. Model生成脚本 ✅
|
||||
|
||||
**文件:** `ycc-proxy-server/deploy/sql/generate_tianyuanapi_models.sh`
|
||||
|
||||
**功能:**
|
||||
- 生成 `feature` 表的Model(已更新,包含cost_price字段)
|
||||
- 生成 `tianyuanapi_call_log` 表的Model
|
||||
|
||||
### 6. 文档 ✅
|
||||
|
||||
**已创建的文档:**
|
||||
1. `天元API调用记录修改说明.md` - 详细的修改步骤和示例
|
||||
2. `批量替换API调用说明.md` - 批量修改API调用方法的指南
|
||||
|
||||
## 待完成的工作
|
||||
|
||||
### 1. 执行SQL脚本 ⏳
|
||||
|
||||
```bash
|
||||
# 在数据库中执行迁移脚本
|
||||
mysql -u root -p ycc < ycc-proxy-server/deploy/sql/tianyuanapi_cost_migration.sql
|
||||
```
|
||||
|
||||
### 2. 生成Model代码 ⏳
|
||||
|
||||
```bash
|
||||
cd ycc-proxy-server/deploy/sql
|
||||
bash generate_tianyuanapi_models.sh
|
||||
```
|
||||
|
||||
这将生成以下文件:
|
||||
- `app/main/model/featureModel_gen.go` (已更新,包含cost_price字段)
|
||||
- `app/main/model/featureModel.go` (已更新)
|
||||
- `app/main/model/tianyuanapiCallLogModel_gen.go` (新建)
|
||||
- `app/main/model/tianyuanapiCallLogModel.go` (新建)
|
||||
|
||||
### 3. 批量修改API调用方法 ⏳
|
||||
|
||||
**需要修改30个方法,将:**
|
||||
```go
|
||||
resp, err := a.callTianyuanApiWithLog(ctx, "", "API名称", map[string]interface{}{
|
||||
```
|
||||
|
||||
**替换为:**
|
||||
```go
|
||||
ctx := context.Background()
|
||||
resp, err := a.callTianyuanApiWithLog(ctx, "", "API名称", map[string]interface{}{
|
||||
```
|
||||
|
||||
**参考文档:** `批量替换API调用说明.md`
|
||||
|
||||
**建议使用IDE批量替换功能:**
|
||||
1. 打开 `apirequestService.go`
|
||||
2. 按 `Ctrl+H` 打开查找替换
|
||||
3. 查找:`a.callTianyuanApiWithLog(ctx, "", "`
|
||||
4. 替换:`a.callTianyuanApiWithLog(ctx, "", "`
|
||||
5. 全部替换
|
||||
|
||||
**然后手动在每个方法开头添加:**
|
||||
```go
|
||||
ctx := context.Background()
|
||||
```
|
||||
|
||||
### 4. 编译验证 ⏳
|
||||
|
||||
```bash
|
||||
cd ycc-proxy-server
|
||||
go build ./...
|
||||
```
|
||||
|
||||
检查是否有编译错误。
|
||||
|
||||
### 5. 测试验证 ⏳
|
||||
|
||||
1. 运行项目
|
||||
2. 发起几个API请求(成功和失败各几次)
|
||||
3. 检查 `tianyuanapi_call_log` 表,验证:
|
||||
- 记录是否正确插入
|
||||
- 成功调用有正确的成本价
|
||||
- 失败调用成本为0
|
||||
- 响应耗时是否记录
|
||||
- 错误信息是否正确
|
||||
|
||||
### 6. 后台配置 ⏳
|
||||
|
||||
在后台"功能管理"页面,为每个feature配置成本价:
|
||||
1. 进入"功能管理"
|
||||
2. 编辑某个功能
|
||||
3. 设置"天元API调用成本价"字段
|
||||
4. 保存
|
||||
|
||||
## 统计功能使用示例
|
||||
|
||||
```go
|
||||
// 获取某个功能在某个时间段的调用统计
|
||||
filter := StatisticsFilter{
|
||||
FeatureID: "feature-id-123",
|
||||
StartDate: time.Now().AddDate(0, 0, -30), // 30天前
|
||||
EndDate: time.Now(),
|
||||
}
|
||||
stats, err := ctx.TianyuanapiCallLogService.GetStatistics(context.Background(), filter)
|
||||
if err == nil {
|
||||
fmt.Printf("总调用次数: %d\n", stats.TotalCalls)
|
||||
fmt.Printf("成功次数: %d\n", stats.SuccessCalls)
|
||||
fmt.Printf("失败次数: %d\n", stats.FailedCalls)
|
||||
fmt.Printf("总成本: %.2f元\n", stats.TotalCost)
|
||||
}
|
||||
```
|
||||
|
||||
## SQL查询示例
|
||||
|
||||
### 查询某个接口的调用记录
|
||||
```sql
|
||||
SELECT * FROM tianyuanapi_call_log
|
||||
WHERE api_id = 'YYSYBE08'
|
||||
ORDER BY call_time DESC
|
||||
LIMIT 100;
|
||||
```
|
||||
|
||||
### 统计某天所有接口的调用情况
|
||||
```sql
|
||||
SELECT
|
||||
api_id,
|
||||
COUNT(*) as total_calls,
|
||||
SUM(CASE WHEN call_status = 1 THEN 1 ELSE 0 END) as success_calls,
|
||||
SUM(CASE WHEN call_status = 0 THEN 1 ELSE 0 END) as failed_calls,
|
||||
SUM(cost_price) as total_cost
|
||||
FROM tianyuanapi_call_log
|
||||
WHERE DATE(call_time) = CURDATE()
|
||||
GROUP BY api_id;
|
||||
```
|
||||
|
||||
### 查询成功率最低的接口
|
||||
```sql
|
||||
SELECT
|
||||
api_id,
|
||||
COUNT(*) as total_calls,
|
||||
SUM(CASE WHEN call_status = 1 THEN 1 ELSE 0 END) as success_calls,
|
||||
(SUM(CASE WHEN call_status = 1 THEN 1 ELSE 0 END) * 100.0 / COUNT(*)) as success_rate
|
||||
FROM tianyuanapi_call_log
|
||||
WHERE call_time >= DATE_SUB(NOW(), INTERVAL 7 DAY)
|
||||
GROUP BY api_id
|
||||
ORDER BY success_rate ASC
|
||||
LIMIT 10;
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **成本价配置**:需要在后台为每个feature配置成本价,否则所有调用的成本都是0
|
||||
2. **性能考虑**:调用日志采用异步记录,不影响API响应速度
|
||||
3. **数据量控制**:response_data只记录前1000字符,避免存储过大
|
||||
4. **缓存机制**:apiID到featureID的映射在 `ProcessRequests` 时构建,避免频繁查询数据库
|
||||
5. **失败不收费**:根据需求,调用失败时天元API不收费,所以cost_price为0
|
||||
|
||||
## 后续优化建议
|
||||
|
||||
1. **定时清理**:可以添加定时任务,定期清理超过一定时间的日志数据(如90天)
|
||||
2. **成本预警**:可以添加监控,当某个时间段的总成本超过阈值时发送告警
|
||||
3. **成功率监控**:监控各接口的成功率,低于阈值时告警
|
||||
4. **性能分析**:分析响应时间,找出性能瓶颈
|
||||
5. **数据归档**:将历史日志归档到其他存储,避免主表过大
|
||||
|
||||
## 文件清单
|
||||
|
||||
### 新增文件
|
||||
1. `deploy/sql/tianyuanapi_cost_migration.sql` - 数据库迁移脚本
|
||||
2. `deploy/sql/generate_tianyuanapi_models.sh` - Model生成脚本
|
||||
3. `app/main/api/internal/service/tianyuanapiCallLogService.go` - 调用记录服务
|
||||
4. `deploy/sql/天元API调用记录修改说明.md` - 详细修改说明
|
||||
5. `deploy/sql/批量替换API调用说明.md` - 批量替换指南
|
||||
6. `deploy/sql/天元API调用记录功能完成总结.md` - 本文档
|
||||
|
||||
### 修改文件
|
||||
1. `app/main/api/internal/service/apirequestService.go` - 添加调用记录逻辑
|
||||
2. `app/main/api/internal/svc/servicecontext.go` - 添加新Model和Service初始化
|
||||
|
||||
### 待生成文件(执行脚本后)
|
||||
1. `app/main/model/featureModel_gen.go` - 已更新
|
||||
2. `app/main/model/featureModel.go` - 已更新
|
||||
3. `app/main/model/tianyuanapiCallLogModel_gen.go` - 新建
|
||||
4. `app/main/model/tianyuanapiCallLogModel.go` - 新建
|
||||
|
||||
83
deploy/sql/批量修改方法签名.sh
Normal file
83
deploy/sql/批量修改方法签名.sh
Normal file
@@ -0,0 +1,83 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 批量修改API请求方法签名,添加ctx参数
|
||||
|
||||
FILE="app/main/api/internal/service/apirequestService.go"
|
||||
|
||||
# 需要修改的方法列表(不包括ProcessYYSYBE08Request和ProcessFLXG0V4BRequest,因为已经修改过了)
|
||||
METHODS=(
|
||||
"ProcessPersonEnterpriseProRequest"
|
||||
"ProcessFLXG0687Request"
|
||||
"ProcessFLXG3D56Request"
|
||||
"ProcessIVYZ5733Request"
|
||||
"ProcessIVYZ9A2BRequest"
|
||||
"ProcessJRZQ0A03Request"
|
||||
"ProcessJRZQ8203Request"
|
||||
"ProcessJRZQ4AA8Request"
|
||||
"ProcessQYGL8271Request"
|
||||
"ProcessQYGL6F2DRequest"
|
||||
"ProcessQCXG7A2BRequest"
|
||||
"ProcessYYSY09CDRequest"
|
||||
"ProcessBehaviorRiskScanRequest"
|
||||
"ProcessDWBG8B4DRequest"
|
||||
"ProcessDWBG6A2CRequest"
|
||||
"ProcessJRZQ4B6CRequest"
|
||||
"ProcessJRZQ09J8Request"
|
||||
"ProcessJRZQ5E9FRequest"
|
||||
"ProcessQYGL3F8ERequest"
|
||||
"ProcessIVYZ81NCRequest"
|
||||
"ProcessIVYZ7F3ARequest"
|
||||
"ProcessDWBG7F3ARequest"
|
||||
"ProcessJRZQ8A2DRequest"
|
||||
"ProcessYYSY8B1CRequest"
|
||||
"ProcessYYSY7D3ERequest"
|
||||
"ProcessFLXG7E8FRequest"
|
||||
"ProcessIVYZ8I9JRequest"
|
||||
"ProcessJRZQ7F1ARequest"
|
||||
"ProcessIVYZ3P9MRequest"
|
||||
"ProcessJRZQ6F2ARequest"
|
||||
)
|
||||
|
||||
echo "开始批量修改方法签名..."
|
||||
echo ""
|
||||
|
||||
# 备份文件
|
||||
if [ ! -f "$FILE.backup" ]; then
|
||||
cp "$FILE" "$FILE.backup"
|
||||
echo "✓ 已备份文件到: $FILE.backup"
|
||||
echo ""
|
||||
else
|
||||
echo "⚠ 备份文件已存在,跳过备份"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# 逐个修改方法
|
||||
count=0
|
||||
for method in "${METHODS[@]}"; do
|
||||
# 查找方法定义
|
||||
old_pattern="func (a \*ApiRequestService) $method(params \[\]byte\) \(\[\]byte, error\)"
|
||||
new_pattern="func (a *ApiRequestService) $method(ctx context.Context, params \[\]byte\) \(\[\]byte, error\)"
|
||||
|
||||
# 检查文件中是否包含这个方法签名
|
||||
if grep -q "$method" "$FILE"; then
|
||||
# 使用sed替换
|
||||
sed -i "s/$old_pattern/$new_pattern/g" "$FILE"
|
||||
echo "✓ 已修改: $method"
|
||||
((count++))
|
||||
else
|
||||
echo "✗ 未找到: $method"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "========================================="
|
||||
echo "修改完成!"
|
||||
echo "========================================="
|
||||
echo "共修改了 $count 个方法"
|
||||
echo ""
|
||||
echo "下一步:"
|
||||
echo "1. 检查修改后的文件"
|
||||
echo "2. 编译项目验证是否有错误"
|
||||
echo "3. 运行测试"
|
||||
echo "========================================="
|
||||
|
||||
86
deploy/sql/批量替换API调用方法.ps1
Normal file
86
deploy/sql/批量替换API调用方法.ps1
Normal file
@@ -0,0 +1,86 @@
|
||||
# 批量替换API调用方法的PowerShell脚本
|
||||
|
||||
# 说明:此脚本用于批量修改apirequestService.go中的API调用方法
|
||||
# 使用前请先备份文件!
|
||||
|
||||
$filePath = "app\main\api\internal\service\apirequestService.go"
|
||||
|
||||
# 检查文件是否存在
|
||||
if (-not (Test-Path $filePath)) {
|
||||
Write-Host "错误:文件不存在 - $filePath" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 备份文件
|
||||
$backupPath = "$filePath.backup"
|
||||
Copy-Item $filePath $backupPath
|
||||
Write-Host "已备份文件到: $backupPath" -ForegroundColor Green
|
||||
|
||||
# 读取文件内容
|
||||
$content = Get-Content $filePath -Raw
|
||||
|
||||
# 需要修改的方法列表(已完成的除外)
|
||||
$methodsToSkip = @(
|
||||
"ProcessYYSYBE08Request",
|
||||
"ProcessFLXG0V4BRequest"
|
||||
)
|
||||
|
||||
# 需要添加ctx声明的模式
|
||||
$pattern1 = '(?m)(func \(a \*ApiRequestService\) Process(\w+)Request\(params \[\]byte\) \(\[\]byte, error\) \{)'
|
||||
|
||||
# 替换API调用
|
||||
$pattern2 = 'a\.tianyuanapi\.CallInterface\("'
|
||||
$replacement2 = 'a.callTianyuanApiWithLog(ctx, "", "'
|
||||
|
||||
# 执行替换
|
||||
$count = 0
|
||||
$content -replace $pattern2, $replacement2 | Out-File $filePath -Encoding UTF8
|
||||
|
||||
# 统计替换次数
|
||||
$matches = [regex]::Matches($content, $pattern2)
|
||||
$count = $matches.Count
|
||||
|
||||
Write-Host "已替换 $count 处 a.tianyuanapi.CallInterface 调用" -ForegroundColor Green
|
||||
|
||||
Write-Host "`n现在需要手动为每个方法添加 ctx 声明:" -ForegroundColor Yellow
|
||||
Write-Host "在每个方法的 func 声明后,第一行添加:" -ForegroundColor Yellow
|
||||
Write-Host 'ctx := context.Background()' -ForegroundColor Cyan
|
||||
|
||||
Write-Host "`n需要修改的方法列表(已完成的除外):" -ForegroundColor Yellow
|
||||
Write-Host "ProcessPersonEnterpriseProRequest - 主接口和涉诉查询" -ForegroundColor White
|
||||
Write-Host "ProcessFLXG0687Request" -ForegroundColor White
|
||||
Write-Host "ProcessFLXG3D56Request" -ForegroundColor White
|
||||
Write-Host "ProcessIVYZ5733Request" -ForegroundColor White
|
||||
Write-Host "ProcessIVYZ9A2BRequest" -ForegroundColor White
|
||||
Write-Host "ProcessJRZQ0A03Request" -ForegroundColor White
|
||||
Write-Host "ProcessJRZQ8203Request" -ForegroundColor White
|
||||
Write-Host "ProcessJRZQ4AA8Request" -ForegroundColor White
|
||||
Write-Host "ProcessQYGL8271Request" -ForegroundColor White
|
||||
Write-Host "ProcessQYGL6F2DRequest" -ForegroundColor White
|
||||
Write-Host "ProcessQCXG7A2BRequest" -ForegroundColor White
|
||||
Write-Host "ProcessYYSY09CDRequest" -ForegroundColor White
|
||||
Write-Host "ProcessDWBG8B4DRequest" -ForegroundColor White
|
||||
Write-Host "ProcessDWBG6A2CRequest" -ForegroundColor White
|
||||
Write-Host "ProcessJRZQ4B6CRequest" -ForegroundColor White
|
||||
Write-Host "ProcessJRZQ09J8Request" -ForegroundColor White
|
||||
Write-Host "ProcessJRZQ5E9FRequest" -ForegroundColor White
|
||||
Write-Host "ProcessQYGL3F8ERequest" -ForegroundColor White
|
||||
Write-Host "ProcessIVYZ81NCRequest" -ForegroundColor White
|
||||
Write-Host "ProcessIVYZ7F3ARequest" -ForegroundColor White
|
||||
Write-Host "ProcessDWBG7F3ARequest" -ForegroundColor White
|
||||
Write-Host "ProcessJRZQ8A2DRequest" -ForegroundColor White
|
||||
Write-Host "ProcessYYSY8B1CRequest" -ForegroundColor White
|
||||
Write-Host "ProcessYYSY7D3ERequest" -ForegroundColor White
|
||||
Write-Host "ProcessFLXG7E8FRequest" -ForegroundColor White
|
||||
Write-Host "ProcessIVYZ8I9JRequest" -ForegroundColor White
|
||||
Write-Host "ProcessJRZQ7F1ARequest" -ForegroundColor White
|
||||
Write-Host "ProcessIVYZ3P9MRequest" -ForegroundColor White
|
||||
Write-Host "ProcessJRZQ6F2ARequest" -ForegroundColor White
|
||||
|
||||
Write-Host "`n总计需要修改 30 个方法" -ForegroundColor Yellow
|
||||
Write-Host "`n提示:在IDE中使用查找替换功能会更方便" -ForegroundColor Cyan
|
||||
Write-Host "查找:a.tianyuanapi.CallInterface(`(" -ForegroundColor Cyan
|
||||
Write-Host "替换:a.callTianyuanApiWithLog(ctx, `", `(" -ForegroundColor Cyan
|
||||
|
||||
Write-Host "`n`n操作完成!请检查文件并手动添加 ctx 声明" -ForegroundColor Green
|
||||
|
||||
97
deploy/sql/批量替换API调用说明.md
Normal file
97
deploy/sql/批量替换API调用说明.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# 批量替换天元API调用方法
|
||||
|
||||
## 目的
|
||||
将所有 `a.tianyuanapi.CallInterface(` 替换为 `a.callTianyuanApiWithLog(ctx, "", `
|
||||
|
||||
## 需要修改的文件
|
||||
`ycc-proxy-server/app/main/api/internal/service/apirequestService.go`
|
||||
|
||||
## 手动修改步骤
|
||||
|
||||
### 步骤1:在方法开头添加 ctx 声明
|
||||
在每个需要修改的方法开头,在 `func` 声明后添加:
|
||||
```go
|
||||
ctx := context.Background()
|
||||
```
|
||||
|
||||
### 步骤2:替换调用
|
||||
查找并替换:
|
||||
```
|
||||
a.callTianyuanApiWithLog(ctx, "", "API名称", map[string]interface{}{
|
||||
```
|
||||
替换为:
|
||||
```
|
||||
a.callTianyuanApiWithLog(ctx, "", "API名称", map[string]interface{}{
|
||||
```
|
||||
|
||||
## 具体需要修改的方法列表(已完成部分)
|
||||
|
||||
### ✅ 已完成
|
||||
1. ✅ ProcessYYSYBE08Request (第886行)
|
||||
2. ✅ ProcessFLXG0V4BRequest (第653行)
|
||||
|
||||
### ⏳ 待修改
|
||||
1. ProcessPersonEnterpriseProRequest (第320行) - 主接口
|
||||
2. ProcessPersonEnterpriseProRequest (第522行) - 涉诉查询
|
||||
3. ProcessFLXG0687Request (第675行)
|
||||
4. ProcessFLXG3D56Request (第705行)
|
||||
5. ProcessIVYZ5733Request (第759行)
|
||||
6. ProcessIVYZ9A2BRequest (第815行)
|
||||
7. ProcessJRZQ0A03Request (第929行)
|
||||
8. ProcessJRZQ8203Request (第986行)
|
||||
9. ProcessJRZQ4AA8Request (第1043行)
|
||||
10. ProcessQYGL8271Request (第1092行)
|
||||
11. ProcessQYGL6F2DRequest (第1150行)
|
||||
12. ProcessQCXG7A2BRequest (第1191行)
|
||||
13. ProcessYYSY09CDRequest (第1211行)
|
||||
14. ProcessDWBG8B4DRequest (第1322行)
|
||||
15. ProcessDWBG6A2CRequest (第1347行)
|
||||
16. ProcessJRZQ4B6CRequest (第1371行)
|
||||
17. ProcessJRZQ09J8Request (第1395行)
|
||||
18. ProcessJRZQ5E9FRequest (第1419行)
|
||||
19. ProcessQYGL3F8ERequest (第1441行)
|
||||
20. ProcessIVYZ81NCRequest (第1461行)
|
||||
21. ProcessIVYZ7F3ARequest (第1482行)
|
||||
22. ProcessDWBG7F3ARequest (第1505行)
|
||||
23. ProcessJRZQ8A2DRequest (第1528行)
|
||||
24. ProcessYYSY8B1CRequest (第1550行)
|
||||
25. ProcessYYSY7D3ERequest (第1569行)
|
||||
26. ProcessFLXG7E8FRequest (第1590行)
|
||||
27. ProcessIVYZ8I9JRequest (第1545行)
|
||||
28. ProcessJRZQ7F1ARequest (第1568行)
|
||||
29. ProcessIVYZ3P9MRequest (第1591行)
|
||||
30. ProcessJRZQ6F2ARequest (第1612行)
|
||||
|
||||
## 使用IDE批量替换功能
|
||||
|
||||
### 方式1:使用VSCode查找替换
|
||||
1. 打开 `apirequestService.go`
|
||||
2. 按 `Ctrl+H` 打开查找替换
|
||||
3. 查找内容:`a.callTianyuanApiWithLog(ctx, "", "`
|
||||
4. 替换内容:`a.callTianyuanApiWithLog(ctx, "", "`
|
||||
5. 点击"全部替换"
|
||||
|
||||
### 方式2:使用正则表达式批量替换
|
||||
查找:`a\.tianyuanapi\.CallInterface\("(.+?)",`
|
||||
替换:`a.callTianyuanApiWithLog(ctx, "", "$1",`
|
||||
|
||||
**注意:** 执行批量替换后,还需要在每个方法开头添加 `ctx := context.Background()` 声明
|
||||
|
||||
## 验证修改
|
||||
|
||||
修改完成后,执行以下步骤验证:
|
||||
|
||||
1. 编译项目
|
||||
```bash
|
||||
cd ycc-proxy-server
|
||||
go build ./...
|
||||
```
|
||||
|
||||
2. 检查是否有编译错误
|
||||
|
||||
3. 运行测试,发起几个API请求
|
||||
|
||||
4. 检查数据库 `tianyuanapi_call_log` 表,验证记录是否正确插入
|
||||
|
||||
5. 检查成本价是否正确计算(成功调用有成本,失败调用成本为0)
|
||||
|
||||
Reference in New Issue
Block a user