feat: 增加授权趋势、最近授权两个接口
This commit is contained in:
1 parent
2f23e2c07e
commit
795458f6d8
16 files changed
+1755
-2
No files matched your search
@@ -35,6 +35,15 @@ errors:
|
||||
"300009": "Failed to generate license file"
|
||||
"300010": "Invalid configuration parameters"
|
||||
|
||||
# Dashboard module (40xxxx)
|
||||
dashboard:
|
||||
"400001": "Invalid time type parameter"
|
||||
"400002": "Invalid start date format"
|
||||
"400003": "Invalid end date format"
|
||||
"400004": "Time range exceeds limit (over one year)"
|
||||
"400005": "Start date cannot be later than end date"
|
||||
"400006": "Invalid limit parameter"
|
||||
|
||||
# System general (90xxxx)
|
||||
system:
|
||||
"900001": "Invalid request parameters"
|
||||
@@ -42,14 +51,26 @@ errors:
|
||||
"900003": "Resource conflict"
|
||||
"900004": "Internal server error"
|
||||
|
||||
# Common text
|
||||
common:
|
||||
success: "Success"
|
||||
|
||||
# Enum translations
|
||||
enums:
|
||||
dashboard_period:
|
||||
week: "This Week"
|
||||
month: "This Month"
|
||||
customer_type:
|
||||
"individual": "Individual"
|
||||
"enterprise": "Enterprise"
|
||||
"government": "Government"
|
||||
"education": "Education"
|
||||
|
||||
authorization_code_status:
|
||||
normal: "Normal"
|
||||
locked: "Locked"
|
||||
expired: "Expired"
|
||||
|
||||
customer_level:
|
||||
"normal": "Normal"
|
||||
"vip": "VIP"
|
||||
|
||||
@@ -35,6 +35,15 @@ errors:
|
||||
"300009": "ライセンスファイルの生成に失敗しました"
|
||||
"300010": "無効な設定パラメータ"
|
||||
|
||||
# ダッシュボードモジュール (40xxxx)
|
||||
dashboard:
|
||||
"400001": "無効な時間タイプパラメータ"
|
||||
"400002": "無効な開始日付形式"
|
||||
"400003": "無効な終了日付形式"
|
||||
"400004": "時間範囲が制限を超えています(1年以上)"
|
||||
"400005": "開始日は終了日より後にできません"
|
||||
"400006": "無効な制限パラメータ"
|
||||
|
||||
# システム共通 (90xxxx)
|
||||
system:
|
||||
"900001": "無効なリクエストパラメータ"
|
||||
@@ -42,14 +51,26 @@ errors:
|
||||
"900003": "リソースの競合"
|
||||
"900004": "内部サーバーエラー"
|
||||
|
||||
# 共通テキスト
|
||||
common:
|
||||
success: "成功"
|
||||
|
||||
# 列挙値多言語
|
||||
enums:
|
||||
dashboard_period:
|
||||
week: "今週"
|
||||
month: "今月"
|
||||
customer_type:
|
||||
"individual": "個人顧客"
|
||||
"enterprise": "企業顧客"
|
||||
"government": "政府顧客"
|
||||
"education": "教育顧客"
|
||||
|
||||
authorization_code_status:
|
||||
normal: "正常"
|
||||
locked: "ロック済み"
|
||||
expired: "期限切れ"
|
||||
|
||||
customer_level:
|
||||
"normal": "一般顧客"
|
||||
"vip": "VIP顧客"
|
||||
|
||||
@@ -35,6 +35,15 @@ errors:
|
||||
"300009": "许可证文件生成失败"
|
||||
"300010": "配置参数错误"
|
||||
|
||||
# 仪表盘模块 (40xxxx)
|
||||
dashboard:
|
||||
"400001": "时间类型参数错误"
|
||||
"400002": "开始日期格式错误"
|
||||
"400003": "结束日期格式错误"
|
||||
"400004": "时间范围超过限制(超过一年)"
|
||||
"400005": "开始日期不能晚于结束日期"
|
||||
"400006": "数量限制参数错误"
|
||||
|
||||
# 系统通用 (90xxxx)
|
||||
system:
|
||||
"900001": "请求参数无效"
|
||||
@@ -42,14 +51,26 @@ errors:
|
||||
"900003": "资源冲突"
|
||||
"900004": "服务器内部错误"
|
||||
|
||||
# 通用文本
|
||||
common:
|
||||
success: "成功"
|
||||
|
||||
# 枚举值多语言
|
||||
enums:
|
||||
dashboard_period:
|
||||
week: "本周"
|
||||
month: "本月"
|
||||
customer_type:
|
||||
"individual": "个人客户"
|
||||
"enterprise": "企业客户"
|
||||
"government": "政府客户"
|
||||
"education": "教育客户"
|
||||
|
||||
authorization_code_status:
|
||||
normal: "正常"
|
||||
locked: "已锁定"
|
||||
expired: "已过期"
|
||||
|
||||
customer_level:
|
||||
"normal": "普通客户"
|
||||
"vip": "VIP客户"
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
## 核心要点
|
||||
|
||||
一定要阅读customer模块的实现,看看其他模块的实,明白编码细节,现然后再进行开发。
|
||||
|
||||
### 1. 分层架构
|
||||
```
|
||||
internal/
|
||||
@@ -77,4 +79,5 @@ internal/
|
||||
- 分层职责是否清晰
|
||||
- 多语言字段是否完整
|
||||
- 错误处理是否统一
|
||||
- Swagger注解是否完整
|
||||
- Swagger注解是否完整
|
||||
- 避免不必要的冗余,能写到工具函数的不要写在模块内
|
||||
@@ -25,8 +25,10 @@ backend/
|
||||
│ ├── api/
|
||||
│ │ ├── handlers/ # HTTP处理器
|
||||
│ │ │ ├── auth_handler.go
|
||||
│ │ │ ├── authorization_code_handler.go
|
||||
│ │ │ ├── customer_handler.go
|
||||
│ │ │ ├── enum_handler.go
|
||||
│ │ │ ├── license_handler.go
|
||||
│ │ │ └── system_handler.go
|
||||
│ │ ├── middleware/ # 中间件
|
||||
│ │ │ ├── auth.go
|
||||
@@ -37,19 +39,26 @@ backend/
|
||||
│ │ └── router.go
|
||||
│ ├── service/ # 业务逻辑层
|
||||
│ │ ├── auth_service.go
|
||||
│ │ ├── authorization_code_service.go
|
||||
│ │ ├── customer_service.go
|
||||
│ │ ├── enum_service.go
|
||||
│ │ ├── license_service.go
|
||||
│ │ ├── system_service.go
|
||||
│ │ └── interfaces.go # 接口定义
|
||||
│ ├── repository/ # 数据访问层
|
||||
│ │ ├── authorization_code_repository.go
|
||||
│ │ ├── customer_repository.go
|
||||
│ │ ├── license_repository.go
|
||||
│ │ ├── user_repository.go
|
||||
│ │ ├── errors.go
|
||||
│ │ └── interfaces.go
|
||||
│ ├── models/ # 数据模型
|
||||
│ │ ├── auth.go
|
||||
│ │ ├── common.go
|
||||
│ │ ├── customer.go
|
||||
│ │ ├── license.go
|
||||
│ │ ├── system.go
|
||||
│ │ └── common.go
|
||||
│ │ └── user.go
|
||||
│ ├── config/ # 配置管理
|
||||
│ │ └── config.go
|
||||
│ └── database/ # 数据库连接和迁移
|
||||
@@ -85,9 +94,11 @@ backend/
|
||||
│ │ ├── db_install.md
|
||||
│ │ └── swagger_install.md
|
||||
│ ├── modules_design/
|
||||
│ │ ├── auth_api.md
|
||||
│ │ ├── customer-api.md
|
||||
│ │ ├── customer.md
|
||||
│ │ ├── login&auth.md
|
||||
│ │ ├── user.md
|
||||
│ │ ├── user_story.md
|
||||
│ │ ├── 产品原型设计方案.md
|
||||
│ │ └── 授权模块属性设计.md
|
||||
@@ -98,6 +109,10 @@ backend/
|
||||
├── migrations/ # 数据库迁移
|
||||
│ ├── 001_create_customers_table.sql
|
||||
│ ├── 002_insert_sample_data.sql
|
||||
│ ├── 003_create_authorization_codes_table.sql
|
||||
│ ├── 004_create_licenses_table.sql
|
||||
│ ├── 005_create_authorization_changes_table.sql
|
||||
│ ├── 006_create_users_table.sql
|
||||
│ └── README.md
|
||||
├── go.mod
|
||||
└── go.sum
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
# 仪表盘 API 设计
|
||||
|
||||
## 1. 授权趋势统计 API
|
||||
|
||||
### 1.1 获取授权趋势数据
|
||||
```http
|
||||
GET /api/v1/dashboard/authorization-trend
|
||||
```
|
||||
|
||||
**查询参数**
|
||||
- `type` - 时间类型 (week/month/custom) 必填
|
||||
- `start_date` - 开始日期 (YYYY-MM-DD格式,当type为custom时必填)
|
||||
- `end_date` - 结束日期 (YYYY-MM-DD格式,当type为custom时必填)
|
||||
- `timezone` - 时区 (可选,如:Asia/Shanghai、UTC等,默认使用服务器本地时区)
|
||||
|
||||
**参数说明:**
|
||||
- `week`: 返回本周每日的授权总数(周一到周日)
|
||||
- `month`: 返回本月每日的授权总数(1号到当月最后一天)
|
||||
- `custom`: 返回指定时间段内每日授权总数,时间间隔不超过一年
|
||||
- `timezone`: 指定时区,影响"本周"、"本月"以及自定义日期的计算基准。支持标准时区名称如Asia/Shanghai、America/New_York、UTC等
|
||||
|
||||
**响应**
|
||||
```json
|
||||
{
|
||||
"code": "000000",
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"period": {
|
||||
"type": "week",
|
||||
"start_date": "2024-01-01",
|
||||
"end_date": "2024-01-07",
|
||||
"description_display": "本周"
|
||||
},
|
||||
"trend_data": [
|
||||
{
|
||||
"date": "2024-01-01",
|
||||
"total_authorizations": 15,
|
||||
"new_authorizations": 3,
|
||||
"expired_authorizations": 1
|
||||
},
|
||||
{
|
||||
"date": "2024-01-02",
|
||||
"total_authorizations": 17,
|
||||
"new_authorizations": 2,
|
||||
"expired_authorizations": 0
|
||||
}
|
||||
],
|
||||
"summary": {
|
||||
"total_count": 120,
|
||||
"new_count": 15,
|
||||
"expired_count": 5,
|
||||
"growth_rate": 5.2
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**响应字段说明:**
|
||||
- `description_display` - 多语言
|
||||
|
||||
## 2. 最近授权列表 API
|
||||
|
||||
### 2.1 获取最近授权列表
|
||||
```http
|
||||
GET /api/v1/dashboard/recent-authorizations
|
||||
```
|
||||
|
||||
**查询参数**
|
||||
- `limit` - 返回数量限制(默认20,最大100)
|
||||
- `customer_id` - 客户ID筛选(可选)
|
||||
- `status` - 状态筛选 (normal/locked/expired) 可选
|
||||
|
||||
**响应**
|
||||
```json
|
||||
{
|
||||
"code": "000000",
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"list": [
|
||||
{
|
||||
"id": "uuid-string",
|
||||
"code": "LIC-COMP001-A7B9X2-C8F4",
|
||||
"customer_id": "customer-uuid",
|
||||
"customer_name": "张三公司",
|
||||
"description": "企业版授权",
|
||||
"status": "normal",
|
||||
"status_display": "正常",
|
||||
"start_date": "2024-01-01T00:00:00Z",
|
||||
"end_date": "2024-12-31T23:59:59Z",
|
||||
"max_activations": 10,
|
||||
"current_activations": 7,
|
||||
"created_at": "2024-01-01T10:00:00Z",
|
||||
"updated_at": "2024-01-01T10:00:00Z"
|
||||
}
|
||||
],
|
||||
"total": 20
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**响应字段说明:**
|
||||
- `total` - 符合条件的授权总数量
|
||||
- `list` - 当前返回的授权列表数据
|
||||
- `status_display` - 多语言
|
||||
|
||||
## 3. 状态说明
|
||||
|
||||
### 3.1 授权码状态
|
||||
- `normal` - 正常:当前时间在有效期内且未被锁定
|
||||
- `locked` - 已锁定:is_locked=true
|
||||
- `expired` - 已过期:当前时间超过end_date
|
||||
|
||||
### 3.2 时间类型
|
||||
- `week` - 本周:从周一00:00:00到周日23:59:59 (基于指定时区)
|
||||
- `month` - 本月:从1号00:00:00到当月最后一天23:59:59 (基于指定时区)
|
||||
- `custom` - 自定义:指定开始和结束日期,最大跨度365天 (基于指定时区)
|
||||
|
||||
## 4. 错误码定义
|
||||
|
||||
- `400001` - 时间类型参数错误
|
||||
- `400002` - 开始日期格式错误
|
||||
- `400003` - 结束日期格式错误
|
||||
- `400004` - 时间范围超过限制(超过一年)
|
||||
- `400005` - 开始日期不能晚于结束日期
|
||||
- `400006` - 数量限制参数错误
|
||||
@@ -1439,6 +1439,185 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/dashboard/authorization-trend": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"BearerAuth": []
|
||||
}
|
||||
],
|
||||
"description": "根据时间类型(本周/本月/自定义)获取授权趋势统计数据",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"仪表盘"
|
||||
],
|
||||
"summary": "获取授权趋势数据",
|
||||
"parameters": [
|
||||
{
|
||||
"enum": [
|
||||
"week",
|
||||
"month",
|
||||
"custom"
|
||||
],
|
||||
"type": "string",
|
||||
"description": "时间类型",
|
||||
"name": "type",
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "开始日期(YYYY-MM-DD格式,当type为custom时必填)",
|
||||
"name": "start_date",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "结束日期(YYYY-MM-DD格式,当type为custom时必填)",
|
||||
"name": "end_date",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "授权趋势数据",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/models.APIResponse"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/models.DashboardAuthorizationTrendResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "请求参数错误",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "未认证",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "权限不足",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "服务器内部错误",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/dashboard/recent-authorizations": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"BearerAuth": []
|
||||
}
|
||||
],
|
||||
"description": "获取最近创建的授权码列表,支持按客户ID和状态筛选",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"仪表盘"
|
||||
],
|
||||
"summary": "获取最近授权列表",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "返回数量限制(默认20,最大100)",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "客户ID筛选",
|
||||
"name": "customer_id",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"normal",
|
||||
"locked",
|
||||
"expired"
|
||||
],
|
||||
"type": "string",
|
||||
"description": "状态筛选",
|
||||
"name": "status",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "最近授权列表",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/models.APIResponse"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/models.DashboardRecentAuthorizationsResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "请求参数错误",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "未认证",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "权限不足",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "服务器内部错误",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/heartbeat": {
|
||||
"post": {
|
||||
"description": "客户端定期发送心跳,更新在线状态和使用数据",
|
||||
@@ -2824,6 +3003,50 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.DashboardAuthorizationTrendResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"period": {
|
||||
"description": "时间段信息",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/models.TrendPeriod"
|
||||
}
|
||||
]
|
||||
},
|
||||
"summary": {
|
||||
"description": "汇总信息",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/models.TrendSummary"
|
||||
}
|
||||
]
|
||||
},
|
||||
"trend_data": {
|
||||
"description": "趋势数据",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/models.TrendData"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.DashboardRecentAuthorizationsResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"list": {
|
||||
"description": "授权列表",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/models.RecentAuthorization"
|
||||
}
|
||||
},
|
||||
"total": {
|
||||
"description": "符合条件的授权总数量",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.EnumItem": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -3242,6 +3465,63 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.RecentAuthorization": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"description": "授权码",
|
||||
"type": "string"
|
||||
},
|
||||
"created_at": {
|
||||
"description": "创建时间",
|
||||
"type": "string"
|
||||
},
|
||||
"current_activations": {
|
||||
"description": "当前激活数量",
|
||||
"type": "integer"
|
||||
},
|
||||
"customer_id": {
|
||||
"description": "客户ID",
|
||||
"type": "string"
|
||||
},
|
||||
"customer_name": {
|
||||
"description": "客户名称",
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "授权描述",
|
||||
"type": "string"
|
||||
},
|
||||
"end_date": {
|
||||
"description": "到期时间",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"description": "授权码ID",
|
||||
"type": "string"
|
||||
},
|
||||
"max_activations": {
|
||||
"description": "最大激活数量",
|
||||
"type": "integer"
|
||||
},
|
||||
"start_date": {
|
||||
"description": "生效时间",
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"description": "状态 (normal/locked/expired)",
|
||||
"type": "string"
|
||||
},
|
||||
"status_display": {
|
||||
"description": "状态显示文本(多语言)",
|
||||
"type": "string"
|
||||
},
|
||||
"updated_at": {
|
||||
"description": "更新时间",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.StatsOverviewResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -3290,6 +3570,69 @@ const docTemplate = `{
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.TrendData": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"date": {
|
||||
"description": "日期 (YYYY-MM-DD)",
|
||||
"type": "string"
|
||||
},
|
||||
"expired_authorizations": {
|
||||
"description": "当日过期授权数",
|
||||
"type": "integer"
|
||||
},
|
||||
"new_authorizations": {
|
||||
"description": "当日新增授权数",
|
||||
"type": "integer"
|
||||
},
|
||||
"total_authorizations": {
|
||||
"description": "当日授权总数",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.TrendPeriod": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description_display": {
|
||||
"description": "多语言描述",
|
||||
"type": "string"
|
||||
},
|
||||
"end_date": {
|
||||
"description": "结束日期",
|
||||
"type": "string"
|
||||
},
|
||||
"start_date": {
|
||||
"description": "开始日期",
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"description": "时间类型",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.TrendSummary": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"expired_count": {
|
||||
"description": "期间过期授权数",
|
||||
"type": "integer"
|
||||
},
|
||||
"growth_rate": {
|
||||
"description": "增长率(百分比)",
|
||||
"type": "number"
|
||||
},
|
||||
"new_count": {
|
||||
"description": "期间新增授权数",
|
||||
"type": "integer"
|
||||
},
|
||||
"total_count": {
|
||||
"description": "期间总授权数",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"securityDefinitions": {
|
||||
|
||||
@@ -1436,6 +1436,185 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/dashboard/authorization-trend": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"BearerAuth": []
|
||||
}
|
||||
],
|
||||
"description": "根据时间类型(本周/本月/自定义)获取授权趋势统计数据",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"仪表盘"
|
||||
],
|
||||
"summary": "获取授权趋势数据",
|
||||
"parameters": [
|
||||
{
|
||||
"enum": [
|
||||
"week",
|
||||
"month",
|
||||
"custom"
|
||||
],
|
||||
"type": "string",
|
||||
"description": "时间类型",
|
||||
"name": "type",
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "开始日期(YYYY-MM-DD格式,当type为custom时必填)",
|
||||
"name": "start_date",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "结束日期(YYYY-MM-DD格式,当type为custom时必填)",
|
||||
"name": "end_date",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "授权趋势数据",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/models.APIResponse"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/models.DashboardAuthorizationTrendResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "请求参数错误",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "未认证",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "权限不足",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "服务器内部错误",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/dashboard/recent-authorizations": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"BearerAuth": []
|
||||
}
|
||||
],
|
||||
"description": "获取最近创建的授权码列表,支持按客户ID和状态筛选",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"仪表盘"
|
||||
],
|
||||
"summary": "获取最近授权列表",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "返回数量限制(默认20,最大100)",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "客户ID筛选",
|
||||
"name": "customer_id",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"normal",
|
||||
"locked",
|
||||
"expired"
|
||||
],
|
||||
"type": "string",
|
||||
"description": "状态筛选",
|
||||
"name": "status",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "最近授权列表",
|
||||
"schema": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/models.APIResponse"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/models.DashboardRecentAuthorizationsResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "请求参数错误",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "未认证",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "权限不足",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "服务器内部错误",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/heartbeat": {
|
||||
"post": {
|
||||
"description": "客户端定期发送心跳,更新在线状态和使用数据",
|
||||
@@ -2821,6 +3000,50 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.DashboardAuthorizationTrendResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"period": {
|
||||
"description": "时间段信息",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/models.TrendPeriod"
|
||||
}
|
||||
]
|
||||
},
|
||||
"summary": {
|
||||
"description": "汇总信息",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/models.TrendSummary"
|
||||
}
|
||||
]
|
||||
},
|
||||
"trend_data": {
|
||||
"description": "趋势数据",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/models.TrendData"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.DashboardRecentAuthorizationsResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"list": {
|
||||
"description": "授权列表",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/models.RecentAuthorization"
|
||||
}
|
||||
},
|
||||
"total": {
|
||||
"description": "符合条件的授权总数量",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.EnumItem": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -3239,6 +3462,63 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.RecentAuthorization": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"description": "授权码",
|
||||
"type": "string"
|
||||
},
|
||||
"created_at": {
|
||||
"description": "创建时间",
|
||||
"type": "string"
|
||||
},
|
||||
"current_activations": {
|
||||
"description": "当前激活数量",
|
||||
"type": "integer"
|
||||
},
|
||||
"customer_id": {
|
||||
"description": "客户ID",
|
||||
"type": "string"
|
||||
},
|
||||
"customer_name": {
|
||||
"description": "客户名称",
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "授权描述",
|
||||
"type": "string"
|
||||
},
|
||||
"end_date": {
|
||||
"description": "到期时间",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"description": "授权码ID",
|
||||
"type": "string"
|
||||
},
|
||||
"max_activations": {
|
||||
"description": "最大激活数量",
|
||||
"type": "integer"
|
||||
},
|
||||
"start_date": {
|
||||
"description": "生效时间",
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"description": "状态 (normal/locked/expired)",
|
||||
"type": "string"
|
||||
},
|
||||
"status_display": {
|
||||
"description": "状态显示文本(多语言)",
|
||||
"type": "string"
|
||||
},
|
||||
"updated_at": {
|
||||
"description": "更新时间",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.StatsOverviewResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -3287,6 +3567,69 @@
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.TrendData": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"date": {
|
||||
"description": "日期 (YYYY-MM-DD)",
|
||||
"type": "string"
|
||||
},
|
||||
"expired_authorizations": {
|
||||
"description": "当日过期授权数",
|
||||
"type": "integer"
|
||||
},
|
||||
"new_authorizations": {
|
||||
"description": "当日新增授权数",
|
||||
"type": "integer"
|
||||
},
|
||||
"total_authorizations": {
|
||||
"description": "当日授权总数",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.TrendPeriod": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description_display": {
|
||||
"description": "多语言描述",
|
||||
"type": "string"
|
||||
},
|
||||
"end_date": {
|
||||
"description": "结束日期",
|
||||
"type": "string"
|
||||
},
|
||||
"start_date": {
|
||||
"description": "开始日期",
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"description": "时间类型",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.TrendSummary": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"expired_count": {
|
||||
"description": "期间过期授权数",
|
||||
"type": "integer"
|
||||
},
|
||||
"growth_rate": {
|
||||
"description": "增长率(百分比)",
|
||||
"type": "number"
|
||||
},
|
||||
"new_count": {
|
||||
"description": "期间新增授权数",
|
||||
"type": "integer"
|
||||
},
|
||||
"total_count": {
|
||||
"description": "期间总授权数",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"securityDefinitions": {
|
||||
|
||||
@@ -513,6 +513,33 @@ definitions:
|
||||
- disabled
|
||||
type: string
|
||||
type: object
|
||||
models.DashboardAuthorizationTrendResponse:
|
||||
properties:
|
||||
period:
|
||||
allOf:
|
||||
- $ref: '#/definitions/models.TrendPeriod'
|
||||
description: 时间段信息
|
||||
summary:
|
||||
allOf:
|
||||
- $ref: '#/definitions/models.TrendSummary'
|
||||
description: 汇总信息
|
||||
trend_data:
|
||||
description: 趋势数据
|
||||
items:
|
||||
$ref: '#/definitions/models.TrendData'
|
||||
type: array
|
||||
type: object
|
||||
models.DashboardRecentAuthorizationsResponse:
|
||||
properties:
|
||||
list:
|
||||
description: 授权列表
|
||||
items:
|
||||
$ref: '#/definitions/models.RecentAuthorization'
|
||||
type: array
|
||||
total:
|
||||
description: 符合条件的授权总数量
|
||||
type: integer
|
||||
type: object
|
||||
models.EnumItem:
|
||||
properties:
|
||||
display:
|
||||
@@ -796,6 +823,48 @@ definitions:
|
||||
message:
|
||||
type: string
|
||||
type: object
|
||||
models.RecentAuthorization:
|
||||
properties:
|
||||
code:
|
||||
description: 授权码
|
||||
type: string
|
||||
created_at:
|
||||
description: 创建时间
|
||||
type: string
|
||||
current_activations:
|
||||
description: 当前激活数量
|
||||
type: integer
|
||||
customer_id:
|
||||
description: 客户ID
|
||||
type: string
|
||||
customer_name:
|
||||
description: 客户名称
|
||||
type: string
|
||||
description:
|
||||
description: 授权描述
|
||||
type: string
|
||||
end_date:
|
||||
description: 到期时间
|
||||
type: string
|
||||
id:
|
||||
description: 授权码ID
|
||||
type: string
|
||||
max_activations:
|
||||
description: 最大激活数量
|
||||
type: integer
|
||||
start_date:
|
||||
description: 生效时间
|
||||
type: string
|
||||
status:
|
||||
description: 状态 (normal/locked/expired)
|
||||
type: string
|
||||
status_display:
|
||||
description: 状态显示文本(多语言)
|
||||
type: string
|
||||
updated_at:
|
||||
description: 更新时间
|
||||
type: string
|
||||
type: object
|
||||
models.StatsOverviewResponse:
|
||||
properties:
|
||||
abnormal_alerts:
|
||||
@@ -828,6 +897,51 @@ definitions:
|
||||
version:
|
||||
type: string
|
||||
type: object
|
||||
models.TrendData:
|
||||
properties:
|
||||
date:
|
||||
description: 日期 (YYYY-MM-DD)
|
||||
type: string
|
||||
expired_authorizations:
|
||||
description: 当日过期授权数
|
||||
type: integer
|
||||
new_authorizations:
|
||||
description: 当日新增授权数
|
||||
type: integer
|
||||
total_authorizations:
|
||||
description: 当日授权总数
|
||||
type: integer
|
||||
type: object
|
||||
models.TrendPeriod:
|
||||
properties:
|
||||
description_display:
|
||||
description: 多语言描述
|
||||
type: string
|
||||
end_date:
|
||||
description: 结束日期
|
||||
type: string
|
||||
start_date:
|
||||
description: 开始日期
|
||||
type: string
|
||||
type:
|
||||
description: 时间类型
|
||||
type: string
|
||||
type: object
|
||||
models.TrendSummary:
|
||||
properties:
|
||||
expired_count:
|
||||
description: 期间过期授权数
|
||||
type: integer
|
||||
growth_rate:
|
||||
description: 增长率(百分比)
|
||||
type: number
|
||||
new_count:
|
||||
description: 期间新增授权数
|
||||
type: integer
|
||||
total_count:
|
||||
description: 期间总授权数
|
||||
type: integer
|
||||
type: object
|
||||
info:
|
||||
contact:
|
||||
email: support@swagger.io
|
||||
@@ -1724,6 +1838,117 @@ paths:
|
||||
summary: 锁定/解锁授权码
|
||||
tags:
|
||||
- 授权码管理
|
||||
/api/v1/dashboard/authorization-trend:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 根据时间类型(本周/本月/自定义)获取授权趋势统计数据
|
||||
parameters:
|
||||
- description: 时间类型
|
||||
enum:
|
||||
- week
|
||||
- month
|
||||
- custom
|
||||
in: query
|
||||
name: type
|
||||
required: true
|
||||
type: string
|
||||
- description: 开始日期(YYYY-MM-DD格式,当type为custom时必填)
|
||||
in: query
|
||||
name: start_date
|
||||
type: string
|
||||
- description: 结束日期(YYYY-MM-DD格式,当type为custom时必填)
|
||||
in: query
|
||||
name: end_date
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: 授权趋势数据
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/models.APIResponse'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/models.DashboardAuthorizationTrendResponse'
|
||||
type: object
|
||||
"400":
|
||||
description: 请求参数错误
|
||||
schema:
|
||||
$ref: '#/definitions/models.ErrorResponse'
|
||||
"401":
|
||||
description: 未认证
|
||||
schema:
|
||||
$ref: '#/definitions/models.ErrorResponse'
|
||||
"403":
|
||||
description: 权限不足
|
||||
schema:
|
||||
$ref: '#/definitions/models.ErrorResponse'
|
||||
"500":
|
||||
description: 服务器内部错误
|
||||
schema:
|
||||
$ref: '#/definitions/models.ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: 获取授权趋势数据
|
||||
tags:
|
||||
- 仪表盘
|
||||
/api/v1/dashboard/recent-authorizations:
|
||||
get:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 获取最近创建的授权码列表,支持按客户ID和状态筛选
|
||||
parameters:
|
||||
- description: 返回数量限制(默认20,最大100)
|
||||
in: query
|
||||
name: limit
|
||||
type: integer
|
||||
- description: 客户ID筛选
|
||||
in: query
|
||||
name: customer_id
|
||||
type: string
|
||||
- description: 状态筛选
|
||||
enum:
|
||||
- normal
|
||||
- locked
|
||||
- expired
|
||||
in: query
|
||||
name: status
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: 最近授权列表
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/definitions/models.APIResponse'
|
||||
- properties:
|
||||
data:
|
||||
$ref: '#/definitions/models.DashboardRecentAuthorizationsResponse'
|
||||
type: object
|
||||
"400":
|
||||
description: 请求参数错误
|
||||
schema:
|
||||
$ref: '#/definitions/models.ErrorResponse'
|
||||
"401":
|
||||
description: 未认证
|
||||
schema:
|
||||
$ref: '#/definitions/models.ErrorResponse'
|
||||
"403":
|
||||
description: 权限不足
|
||||
schema:
|
||||
$ref: '#/definitions/models.ErrorResponse'
|
||||
"500":
|
||||
description: 服务器内部错误
|
||||
schema:
|
||||
$ref: '#/definitions/models.ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
summary: 获取最近授权列表
|
||||
tags:
|
||||
- 仪表盘
|
||||
/api/v1/heartbeat:
|
||||
post:
|
||||
consumes:
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"license-manager/internal/api/middleware"
|
||||
"license-manager/internal/models"
|
||||
"license-manager/internal/service"
|
||||
"license-manager/pkg/i18n"
|
||||
)
|
||||
|
||||
type DashboardHandler struct {
|
||||
dashboardService service.DashboardService
|
||||
}
|
||||
|
||||
// NewDashboardHandler 创建仪表盘处理器
|
||||
func NewDashboardHandler(dashboardService service.DashboardService) *DashboardHandler {
|
||||
return &DashboardHandler{
|
||||
dashboardService: dashboardService,
|
||||
}
|
||||
}
|
||||
|
||||
// GetAuthorizationTrend 获取授权趋势数据
|
||||
// @Summary 获取授权趋势数据
|
||||
// @Description 根据时间类型(本周/本月/自定义)获取授权趋势统计数据
|
||||
// @Tags 仪表盘
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param type query string true "时间类型" Enums(week,month,custom)
|
||||
// @Param start_date query string false "开始日期(YYYY-MM-DD格式,当type为custom时必填)"
|
||||
// @Param end_date query string false "结束日期(YYYY-MM-DD格式,当type为custom时必填)"
|
||||
// @Success 200 {object} models.APIResponse{data=models.DashboardAuthorizationTrendResponse} "授权趋势数据"
|
||||
// @Failure 400 {object} models.ErrorResponse "请求参数错误"
|
||||
// @Failure 401 {object} models.ErrorResponse "未认证"
|
||||
// @Failure 403 {object} models.ErrorResponse "权限不足"
|
||||
// @Failure 500 {object} models.ErrorResponse "服务器内部错误"
|
||||
// @Router /api/v1/dashboard/authorization-trend [get]
|
||||
func (h *DashboardHandler) GetAuthorizationTrend(c *gin.Context) {
|
||||
// 绑定查询参数
|
||||
var req models.DashboardAuthorizationTrendRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
lang := middleware.GetLanguage(c)
|
||||
status, errCode, message := i18n.NewI18nErrorResponse("900001", lang)
|
||||
c.JSON(status, models.ErrorResponse{
|
||||
Code: errCode,
|
||||
Message: message + ": " + err.Error(),
|
||||
Timestamp: time.Now().Format(time.RFC3339),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 设置语言到Context中
|
||||
ctx := middleware.WithLanguage(c.Request.Context(), c)
|
||||
|
||||
// 调用服务层获取数据
|
||||
response, err := h.dashboardService.GetAuthorizationTrend(ctx, &req)
|
||||
if err != nil {
|
||||
// 错误已经在Service层完全包装好了,直接使用
|
||||
var i18nErr *i18n.I18nError
|
||||
if errors.As(err, &i18nErr) {
|
||||
c.JSON(i18nErr.HttpCode, models.ErrorResponse{
|
||||
Code: i18nErr.Code,
|
||||
Message: i18nErr.Message,
|
||||
Timestamp: time.Now().Format(time.RFC3339),
|
||||
})
|
||||
} else {
|
||||
// 兜底:理论上不应该到这里,因为Service层应该返回I18nError
|
||||
lang := middleware.GetLanguage(c)
|
||||
status, errCode, message := i18n.NewI18nErrorResponse("900004", lang)
|
||||
c.JSON(status, models.ErrorResponse{
|
||||
Code: errCode,
|
||||
Message: message,
|
||||
Timestamp: time.Now().Format(time.RFC3339),
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 返回成功响应
|
||||
lang := middleware.GetLanguage(c)
|
||||
successMessage := i18n.GetErrorMessage("000000", lang)
|
||||
c.JSON(http.StatusOK, models.APIResponse{
|
||||
Code: "000000",
|
||||
Message: successMessage,
|
||||
Data: response,
|
||||
})
|
||||
}
|
||||
|
||||
// GetRecentAuthorizations 获取最近授权列表
|
||||
// @Summary 获取最近授权列表
|
||||
// @Description 获取最近创建的授权码列表,支持按客户ID和状态筛选
|
||||
// @Tags 仪表盘
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param limit query int false "返回数量限制(默认20,最大100)"
|
||||
// @Param customer_id query string false "客户ID筛选"
|
||||
// @Param status query string false "状态筛选" Enums(normal,locked,expired)
|
||||
// @Success 200 {object} models.APIResponse{data=models.DashboardRecentAuthorizationsResponse} "最近授权列表"
|
||||
// @Failure 400 {object} models.ErrorResponse "请求参数错误"
|
||||
// @Failure 401 {object} models.ErrorResponse "未认证"
|
||||
// @Failure 403 {object} models.ErrorResponse "权限不足"
|
||||
// @Failure 500 {object} models.ErrorResponse "服务器内部错误"
|
||||
// @Router /api/v1/dashboard/recent-authorizations [get]
|
||||
func (h *DashboardHandler) GetRecentAuthorizations(c *gin.Context) {
|
||||
// 绑定查询参数
|
||||
var req models.DashboardRecentAuthorizationsRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
lang := middleware.GetLanguage(c)
|
||||
status, errCode, message := i18n.NewI18nErrorResponse("900001", lang)
|
||||
c.JSON(status, models.ErrorResponse{
|
||||
Code: errCode,
|
||||
Message: message + ": " + err.Error(),
|
||||
Timestamp: time.Now().Format(time.RFC3339),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 设置语言到Context中
|
||||
ctx := middleware.WithLanguage(c.Request.Context(), c)
|
||||
|
||||
// 调用服务层获取数据
|
||||
response, err := h.dashboardService.GetRecentAuthorizations(ctx, &req)
|
||||
if err != nil {
|
||||
// 错误已经在Service层完全包装好了,直接使用
|
||||
var i18nErr *i18n.I18nError
|
||||
if errors.As(err, &i18nErr) {
|
||||
c.JSON(i18nErr.HttpCode, models.ErrorResponse{
|
||||
Code: i18nErr.Code,
|
||||
Message: i18nErr.Message,
|
||||
Timestamp: time.Now().Format(time.RFC3339),
|
||||
})
|
||||
} else {
|
||||
// 兜底:理论上不应该到这里,因为Service层应该返回I18nError
|
||||
lang := middleware.GetLanguage(c)
|
||||
status, errCode, message := i18n.NewI18nErrorResponse("900004", lang)
|
||||
c.JSON(status, models.ErrorResponse{
|
||||
Code: errCode,
|
||||
Message: message,
|
||||
Timestamp: time.Now().Format(time.RFC3339),
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 返回成功响应
|
||||
lang := middleware.GetLanguage(c)
|
||||
successMessage := i18n.GetErrorMessage("000000", lang)
|
||||
c.JSON(http.StatusOK, models.APIResponse{
|
||||
Code: "000000",
|
||||
Message: successMessage,
|
||||
Data: response,
|
||||
})
|
||||
}
|
||||
@@ -40,6 +40,7 @@ func SetupRouter() *gin.Engine {
|
||||
userRepo := repository.NewUserRepository(db)
|
||||
authCodeRepo := repository.NewAuthorizationCodeRepository(db)
|
||||
licenseRepo := repository.NewLicenseRepository(db)
|
||||
dashboardRepo := repository.NewDashboardRepository(db)
|
||||
|
||||
// 获取logger实例
|
||||
log := logger.GetLogger()
|
||||
@@ -51,6 +52,7 @@ func SetupRouter() *gin.Engine {
|
||||
enumService := service.NewEnumService()
|
||||
authCodeService := service.NewAuthorizationCodeService(authCodeRepo)
|
||||
licenseService := service.NewLicenseService(licenseRepo, db, log)
|
||||
dashboardService := service.NewDashboardService(dashboardRepo)
|
||||
|
||||
// 初始化处理器层
|
||||
authHandler := handlers.NewAuthHandler(authService)
|
||||
@@ -59,6 +61,7 @@ func SetupRouter() *gin.Engine {
|
||||
enumHandler := handlers.NewEnumHandler(enumService)
|
||||
authCodeHandler := handlers.NewAuthorizationCodeHandler(authCodeService)
|
||||
licenseHandler := handlers.NewLicenseHandler(licenseService)
|
||||
dashboardHandler := handlers.NewDashboardHandler(dashboardService)
|
||||
|
||||
// 健康检测接口(无需认证)
|
||||
router.GET("/health", systemHandler.HealthCheck)
|
||||
@@ -117,6 +120,10 @@ func SetupRouter() *gin.Engine {
|
||||
|
||||
// 统计分析
|
||||
auth.GET("/v1/stats/overview", licenseHandler.GetStatsOverview)
|
||||
|
||||
// 仪表盘接口
|
||||
auth.GET("/v1/dashboard/authorization-trend", dashboardHandler.GetAuthorizationTrend)
|
||||
auth.GET("/v1/dashboard/recent-authorizations", dashboardHandler.GetRecentAuthorizations)
|
||||
}
|
||||
|
||||
// 管理员接口
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
// DashboardAuthorizationTrendRequest 授权趋势查询请求
|
||||
type DashboardAuthorizationTrendRequest struct {
|
||||
Type string `form:"type" binding:"required,oneof=week month custom" json:"type"` // 时间类型: week/month/custom
|
||||
StartDate string `form:"start_date" json:"start_date,omitempty"` // 开始日期 (YYYY-MM-DD格式,当type为custom时必填)
|
||||
EndDate string `form:"end_date" json:"end_date,omitempty"` // 结束日期 (YYYY-MM-DD格式,当type为custom时必填)
|
||||
Timezone string `form:"timezone" json:"timezone,omitempty"` // 时区 (如: Asia/Shanghai, UTC等,默认使用服务器本地时区)
|
||||
}
|
||||
|
||||
// DashboardAuthorizationTrendResponse 授权趋势响应
|
||||
type DashboardAuthorizationTrendResponse struct {
|
||||
Period TrendPeriod `json:"period"` // 时间段信息
|
||||
TrendData []TrendData `json:"trend_data"` // 趋势数据
|
||||
Summary TrendSummary `json:"summary"` // 汇总信息
|
||||
}
|
||||
|
||||
// TrendPeriod 时间段信息
|
||||
type TrendPeriod struct {
|
||||
Type string `json:"type"` // 时间类型
|
||||
StartDate string `json:"start_date"` // 开始日期
|
||||
EndDate string `json:"end_date"` // 结束日期
|
||||
DescriptionDisplay string `json:"description_display"` // 多语言描述
|
||||
}
|
||||
|
||||
// TrendData 单日趋势数据
|
||||
type TrendData struct {
|
||||
Date string `json:"date"` // 日期 (YYYY-MM-DD)
|
||||
TotalAuthorizations int64 `json:"total_authorizations"` // 当日授权总数
|
||||
NewAuthorizations int64 `json:"new_authorizations"` // 当日新增授权数
|
||||
ExpiredAuthorizations int64 `json:"expired_authorizations"` // 当日过期授权数
|
||||
}
|
||||
|
||||
// TrendSummary 趋势汇总信息
|
||||
type TrendSummary struct {
|
||||
TotalCount int64 `json:"total_count"` // 期间总授权数
|
||||
NewCount int64 `json:"new_count"` // 期间新增授权数
|
||||
ExpiredCount int64 `json:"expired_count"` // 期间过期授权数
|
||||
GrowthRate float64 `json:"growth_rate"` // 增长率(百分比)
|
||||
}
|
||||
|
||||
// DashboardRecentAuthorizationsRequest 最近授权列表查询请求
|
||||
type DashboardRecentAuthorizationsRequest struct {
|
||||
Limit int `form:"limit" json:"limit,omitempty"` // 返回数量限制(默认20,最大100)
|
||||
CustomerID string `form:"customer_id" json:"customer_id,omitempty"` // 客户ID筛选(可选)
|
||||
Status string `form:"status" json:"status,omitempty"` // 状态筛选 (normal/locked/expired) 可选
|
||||
}
|
||||
|
||||
// DashboardRecentAuthorizationsResponse 最近授权列表响应
|
||||
type DashboardRecentAuthorizationsResponse struct {
|
||||
List []RecentAuthorization `json:"list"` // 授权列表
|
||||
Total int64 `json:"total"` // 符合条件的授权总数量
|
||||
}
|
||||
|
||||
// RecentAuthorization 最近授权信息
|
||||
type RecentAuthorization struct {
|
||||
ID string `json:"id"` // 授权码ID
|
||||
Code string `json:"code"` // 授权码
|
||||
CustomerID string `json:"customer_id"` // 客户ID
|
||||
CustomerName string `json:"customer_name"` // 客户名称
|
||||
Description string `json:"description"` // 授权描述
|
||||
Status string `json:"status"` // 状态 (normal/locked/expired)
|
||||
StatusDisplay string `json:"status_display"` // 状态显示文本(多语言)
|
||||
StartDate time.Time `json:"start_date"` // 生效时间
|
||||
EndDate time.Time `json:"end_date"` // 到期时间
|
||||
MaxActivations int `json:"max_activations"` // 最大激活数量
|
||||
CurrentActivations int `json:"current_activations"` // 当前激活数量
|
||||
CreatedAt time.Time `json:"created_at"` // 创建时间
|
||||
UpdatedAt time.Time `json:"updated_at"` // 更新时间
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"license-manager/internal/models"
|
||||
pkgcontext "license-manager/pkg/context"
|
||||
"license-manager/pkg/i18n"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type dashboardRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
// NewDashboardRepository 创建仪表盘数据访问层实例
|
||||
func NewDashboardRepository(db *gorm.DB) DashboardRepository {
|
||||
return &dashboardRepository{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
// GetAuthorizationTrendData 获取授权趋势数据
|
||||
func (r *dashboardRepository) GetAuthorizationTrendData(ctx context.Context, startDate, endDate time.Time) ([]models.TrendData, error) {
|
||||
lang := pkgcontext.GetLanguageFromContext(ctx)
|
||||
var trendData []models.TrendData
|
||||
|
||||
// 生成日期范围
|
||||
dates := make([]time.Time, 0)
|
||||
for d := startDate; !d.After(endDate); d = d.AddDate(0, 0, 1) {
|
||||
dates = append(dates, d)
|
||||
}
|
||||
|
||||
// 查询每日数据
|
||||
for _, date := range dates {
|
||||
dayStart := time.Date(date.Year(), date.Month(), date.Day(), 0, 0, 0, 0, date.Location())
|
||||
dayEnd := dayStart.Add(24*time.Hour - time.Nanosecond)
|
||||
|
||||
// 统计当日的授权数据
|
||||
var totalCount, newCount, expiredCount int64
|
||||
|
||||
// 当日总授权数(截至当日24:00的累计有效授权数)
|
||||
err := r.db.WithContext(ctx).Model(&models.AuthorizationCode{}).
|
||||
Where("created_at <= ?", dayEnd).
|
||||
Count(&totalCount).Error
|
||||
if err != nil {
|
||||
return nil, i18n.NewI18nError("900004", lang, err.Error())
|
||||
}
|
||||
|
||||
// 当日新增授权数
|
||||
err = r.db.WithContext(ctx).Model(&models.AuthorizationCode{}).
|
||||
Where("created_at >= ? AND created_at <= ?", dayStart, dayEnd).
|
||||
Count(&newCount).Error
|
||||
if err != nil {
|
||||
return nil, i18n.NewI18nError("900004", lang, err.Error())
|
||||
}
|
||||
|
||||
// 当日过期授权数
|
||||
err = r.db.WithContext(ctx).Model(&models.AuthorizationCode{}).
|
||||
Where("end_date >= ? AND end_date < ?", dayStart, dayEnd).
|
||||
Count(&expiredCount).Error
|
||||
if err != nil {
|
||||
return nil, i18n.NewI18nError("900004", lang, err.Error())
|
||||
}
|
||||
|
||||
trendData = append(trendData, models.TrendData{
|
||||
Date: date.Format("2006-01-02"),
|
||||
TotalAuthorizations: totalCount,
|
||||
NewAuthorizations: newCount,
|
||||
ExpiredAuthorizations: expiredCount,
|
||||
})
|
||||
}
|
||||
|
||||
return trendData, nil
|
||||
}
|
||||
|
||||
// GetRecentAuthorizations 获取最近授权列表
|
||||
func (r *dashboardRepository) GetRecentAuthorizations(ctx context.Context, req *models.DashboardRecentAuthorizationsRequest) (*models.DashboardRecentAuthorizationsResponse, error) {
|
||||
lang := pkgcontext.GetLanguageFromContext(ctx)
|
||||
|
||||
// 设置默认值
|
||||
limit := req.Limit
|
||||
if limit <= 0 {
|
||||
limit = 20
|
||||
}
|
||||
if limit > 100 {
|
||||
limit = 100
|
||||
}
|
||||
|
||||
// 构建查询
|
||||
query := r.db.WithContext(ctx).Table("authorization_codes ac").
|
||||
Select(`ac.id, ac.code, ac.customer_id, c.customer_name as customer_name,
|
||||
ac.description, ac.start_date, ac.end_date, ac.max_activations,
|
||||
COALESCE(l.active_count, 0) as current_activations,
|
||||
ac.created_at, ac.updated_at, ac.is_locked`).
|
||||
Joins("LEFT JOIN customers c ON ac.customer_id = c.id").
|
||||
Joins(`LEFT JOIN (
|
||||
SELECT authorization_code_id, COUNT(*) as active_count
|
||||
FROM licenses
|
||||
WHERE status = 'active' AND deleted_at IS NULL
|
||||
GROUP BY authorization_code_id
|
||||
) l ON ac.id = l.authorization_code_id`).
|
||||
Where("1=1").
|
||||
Order("ac.created_at DESC")
|
||||
|
||||
// 添加筛选条件
|
||||
if req.CustomerID != "" {
|
||||
query = query.Where("ac.customer_id = ?", req.CustomerID)
|
||||
}
|
||||
|
||||
// 状态筛选(虚字段)
|
||||
now := time.Now()
|
||||
switch req.Status {
|
||||
case "normal":
|
||||
query = query.Where("ac.is_locked = ? AND ac.end_date > ?", false, now)
|
||||
case "locked":
|
||||
query = query.Where("ac.is_locked = ?", true)
|
||||
case "expired":
|
||||
query = query.Where("ac.end_date <= ?", now)
|
||||
}
|
||||
|
||||
// 查询总数 - 使用简化查询避免JOIN复杂性
|
||||
var total int64
|
||||
countQuery := r.db.WithContext(ctx).Model(&models.AuthorizationCode{}).Where("1=1")
|
||||
|
||||
// 添加相同的筛选条件
|
||||
if req.CustomerID != "" {
|
||||
countQuery = countQuery.Where("customer_id = ?", req.CustomerID)
|
||||
}
|
||||
|
||||
// 状态筛选
|
||||
switch req.Status {
|
||||
case "normal":
|
||||
countQuery = countQuery.Where("is_locked = ? AND end_date > ?", false, now)
|
||||
case "locked":
|
||||
countQuery = countQuery.Where("is_locked = ?", true)
|
||||
case "expired":
|
||||
countQuery = countQuery.Where("end_date <= ?", now)
|
||||
}
|
||||
|
||||
err := countQuery.Count(&total).Error
|
||||
if err != nil {
|
||||
return nil, i18n.NewI18nError("900004", lang, err.Error())
|
||||
}
|
||||
|
||||
// 查询列表数据
|
||||
type queryResult struct {
|
||||
ID string `gorm:"column:id"`
|
||||
Code string `gorm:"column:code"`
|
||||
CustomerID string `gorm:"column:customer_id"`
|
||||
CustomerName string `gorm:"column:customer_name"`
|
||||
Description string `gorm:"column:description"`
|
||||
StartDate time.Time `gorm:"column:start_date"`
|
||||
EndDate time.Time `gorm:"column:end_date"`
|
||||
MaxActivations int `gorm:"column:max_activations"`
|
||||
CurrentActivations int `gorm:"column:current_activations"`
|
||||
CreatedAt time.Time `gorm:"column:created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at"`
|
||||
IsLocked bool `gorm:"column:is_locked"`
|
||||
}
|
||||
|
||||
var results []queryResult
|
||||
err = query.Limit(limit).Find(&results).Error
|
||||
if err != nil {
|
||||
return nil, i18n.NewI18nError("900004", lang, err.Error())
|
||||
}
|
||||
|
||||
// 转换为响应格式
|
||||
authorizations := make([]models.RecentAuthorization, 0, len(results))
|
||||
for _, result := range results {
|
||||
// 计算状态
|
||||
status := "normal"
|
||||
statusDisplay := i18n.GetEnumMessage("authorization_code_status", "normal", lang)
|
||||
|
||||
if result.IsLocked {
|
||||
status = "locked"
|
||||
statusDisplay = i18n.GetEnumMessage("authorization_code_status", "locked", lang)
|
||||
} else if result.EndDate.Before(now) {
|
||||
status = "expired"
|
||||
statusDisplay = i18n.GetEnumMessage("authorization_code_status", "expired", lang)
|
||||
}
|
||||
|
||||
authorizations = append(authorizations, models.RecentAuthorization{
|
||||
ID: result.ID,
|
||||
Code: result.Code,
|
||||
CustomerID: result.CustomerID,
|
||||
CustomerName: result.CustomerName,
|
||||
Description: result.Description,
|
||||
Status: status,
|
||||
StatusDisplay: statusDisplay,
|
||||
StartDate: result.StartDate,
|
||||
EndDate: result.EndDate,
|
||||
MaxActivations: result.MaxActivations,
|
||||
CurrentActivations: result.CurrentActivations,
|
||||
CreatedAt: result.CreatedAt,
|
||||
UpdatedAt: result.UpdatedAt,
|
||||
})
|
||||
}
|
||||
|
||||
return &models.DashboardRecentAuthorizationsResponse{
|
||||
List: authorizations,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
"license-manager/internal/models"
|
||||
)
|
||||
|
||||
@@ -99,4 +100,13 @@ type LicenseRepository interface {
|
||||
|
||||
// GetActiveLicenseCount 获取指定授权码的激活许可证数量
|
||||
GetActiveLicenseCount(ctx context.Context, authCodeID string) (int64, error)
|
||||
}
|
||||
|
||||
// DashboardRepository 仪表盘数据访问接口
|
||||
type DashboardRepository interface {
|
||||
// GetAuthorizationTrendData 获取授权趋势数据
|
||||
GetAuthorizationTrendData(ctx context.Context, startDate, endDate time.Time) ([]models.TrendData, error)
|
||||
|
||||
// GetRecentAuthorizations 获取最近授权列表
|
||||
GetRecentAuthorizations(ctx context.Context, req *models.DashboardRecentAuthorizationsRequest) (*models.DashboardRecentAuthorizationsResponse, error)
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"license-manager/internal/models"
|
||||
"license-manager/internal/repository"
|
||||
pkgcontext "license-manager/pkg/context"
|
||||
"license-manager/pkg/i18n"
|
||||
)
|
||||
|
||||
type dashboardService struct {
|
||||
dashboardRepo repository.DashboardRepository
|
||||
}
|
||||
|
||||
// NewDashboardService 创建仪表盘服务实例
|
||||
func NewDashboardService(dashboardRepo repository.DashboardRepository) DashboardService {
|
||||
return &dashboardService{
|
||||
dashboardRepo: dashboardRepo,
|
||||
}
|
||||
}
|
||||
|
||||
// GetAuthorizationTrend 获取授权趋势数据
|
||||
func (s *dashboardService) GetAuthorizationTrend(ctx context.Context, req *models.DashboardAuthorizationTrendRequest) (*models.DashboardAuthorizationTrendResponse, error) {
|
||||
lang := pkgcontext.GetLanguageFromContext(ctx)
|
||||
|
||||
// 业务逻辑:参数验证
|
||||
if req == nil {
|
||||
return nil, i18n.NewI18nError("900001", lang)
|
||||
}
|
||||
|
||||
var startDate, endDate time.Time
|
||||
var descriptionDisplay string
|
||||
|
||||
// 获取时区,默认使用本地时区
|
||||
loc := time.Local
|
||||
if req.Timezone != "" {
|
||||
var err error
|
||||
loc, err = time.LoadLocation(req.Timezone)
|
||||
if err != nil {
|
||||
// 时区解析失败,使用本地时区
|
||||
loc = time.Local
|
||||
}
|
||||
}
|
||||
|
||||
now := time.Now().In(loc)
|
||||
|
||||
// 根据类型计算时间范围
|
||||
switch req.Type {
|
||||
case "week":
|
||||
// 本周:从周一到周日
|
||||
weekday := int(now.Weekday())
|
||||
if weekday == 0 { // Sunday
|
||||
weekday = 7
|
||||
}
|
||||
startDate = now.AddDate(0, 0, -(weekday-1))
|
||||
startDate = time.Date(startDate.Year(), startDate.Month(), startDate.Day(), 0, 0, 0, 0, loc)
|
||||
endDate = startDate.AddDate(0, 0, 6)
|
||||
endDate = time.Date(endDate.Year(), endDate.Month(), endDate.Day(), 23, 59, 59, 999999999, loc)
|
||||
descriptionDisplay = i18n.GetEnumMessage("dashboard_period", "week", lang)
|
||||
|
||||
case "month":
|
||||
// 本月:从1号到月末
|
||||
startDate = time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, loc)
|
||||
endDate = startDate.AddDate(0, 1, -1)
|
||||
endDate = time.Date(endDate.Year(), endDate.Month(), endDate.Day(), 23, 59, 59, 999999999, loc)
|
||||
descriptionDisplay = i18n.GetEnumMessage("dashboard_period", "month", lang)
|
||||
|
||||
case "custom":
|
||||
// 自定义时间范围
|
||||
if req.StartDate == "" || req.EndDate == "" {
|
||||
return nil, i18n.NewI18nError("400002", lang) // 开始日期和结束日期都是必填的
|
||||
}
|
||||
|
||||
var err error
|
||||
startDate, err = time.ParseInLocation("2006-01-02", req.StartDate, loc)
|
||||
if err != nil {
|
||||
return nil, i18n.NewI18nError("400002", lang) // 开始日期格式错误
|
||||
}
|
||||
|
||||
endDate, err = time.ParseInLocation("2006-01-02", req.EndDate, loc)
|
||||
if err != nil {
|
||||
return nil, i18n.NewI18nError("400003", lang) // 结束日期格式错误
|
||||
}
|
||||
|
||||
// 验证时间范围
|
||||
if startDate.After(endDate) {
|
||||
return nil, i18n.NewI18nError("400005", lang) // 开始日期不能晚于结束日期
|
||||
}
|
||||
|
||||
// 验证时间跨度不超过一年
|
||||
if endDate.Sub(startDate) > 365*24*time.Hour {
|
||||
return nil, i18n.NewI18nError("400004", lang) // 时间范围超过限制
|
||||
}
|
||||
|
||||
// 设置为全天
|
||||
startDate = time.Date(startDate.Year(), startDate.Month(), startDate.Day(), 0, 0, 0, 0, startDate.Location())
|
||||
endDate = time.Date(endDate.Year(), endDate.Month(), endDate.Day(), 23, 59, 59, 999999999, endDate.Location())
|
||||
descriptionDisplay = fmt.Sprintf("%s - %s", req.StartDate, req.EndDate)
|
||||
|
||||
default:
|
||||
return nil, i18n.NewI18nError("400001", lang) // 时间类型参数错误
|
||||
}
|
||||
|
||||
// 获取趋势数据
|
||||
trendData, err := s.dashboardRepo.GetAuthorizationTrendData(ctx, startDate, endDate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 计算汇总信息
|
||||
var totalCount, newCount, expiredCount int64
|
||||
for _, data := range trendData {
|
||||
newCount += data.NewAuthorizations
|
||||
expiredCount += data.ExpiredAuthorizations
|
||||
}
|
||||
|
||||
// 获取期间结束时的总授权数
|
||||
if len(trendData) > 0 {
|
||||
totalCount = trendData[len(trendData)-1].TotalAuthorizations
|
||||
}
|
||||
|
||||
// 计算增长率(本期新增相对于期初的百分比)
|
||||
var growthRate float64
|
||||
if totalCount > 0 && newCount > 0 {
|
||||
periodStartCount := totalCount - newCount
|
||||
if periodStartCount > 0 {
|
||||
growthRate = float64(newCount) / float64(periodStartCount) * 100
|
||||
} else {
|
||||
growthRate = 100.0 // 如果期初为0,则增长率为100%
|
||||
}
|
||||
}
|
||||
|
||||
return &models.DashboardAuthorizationTrendResponse{
|
||||
Period: models.TrendPeriod{
|
||||
Type: req.Type,
|
||||
StartDate: startDate.Format("2006-01-02"),
|
||||
EndDate: endDate.Format("2006-01-02"),
|
||||
DescriptionDisplay: descriptionDisplay,
|
||||
},
|
||||
TrendData: trendData,
|
||||
Summary: models.TrendSummary{
|
||||
TotalCount: totalCount,
|
||||
NewCount: newCount,
|
||||
ExpiredCount: expiredCount,
|
||||
GrowthRate: growthRate,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetRecentAuthorizations 获取最近授权列表
|
||||
func (s *dashboardService) GetRecentAuthorizations(ctx context.Context, req *models.DashboardRecentAuthorizationsRequest) (*models.DashboardRecentAuthorizationsResponse, error) {
|
||||
lang := pkgcontext.GetLanguageFromContext(ctx)
|
||||
|
||||
// 业务逻辑:参数验证
|
||||
if req == nil {
|
||||
return nil, i18n.NewI18nError("900001", lang)
|
||||
}
|
||||
|
||||
// 验证limit参数
|
||||
if req.Limit < 0 || req.Limit > 100 {
|
||||
return nil, i18n.NewI18nError("400006", lang) // 数量限制参数错误
|
||||
}
|
||||
|
||||
// 验证status参数
|
||||
if req.Status != "" && req.Status != "normal" && req.Status != "locked" && req.Status != "expired" {
|
||||
return nil, i18n.NewI18nError("400001", lang) // 状态参数错误
|
||||
}
|
||||
|
||||
// 调用repository获取数据
|
||||
return s.dashboardRepo.GetRecentAuthorizations(ctx, req)
|
||||
}
|
||||
@@ -60,3 +60,12 @@ type LicenseService interface {
|
||||
// 统计接口
|
||||
GetStatsOverview(ctx context.Context) (*models.StatsOverviewResponse, error)
|
||||
}
|
||||
|
||||
// DashboardService 仪表盘服务接口
|
||||
type DashboardService interface {
|
||||
// 获取授权趋势数据
|
||||
GetAuthorizationTrend(ctx context.Context, req *models.DashboardAuthorizationTrendRequest) (*models.DashboardAuthorizationTrendResponse, error)
|
||||
|
||||
// 获取最近授权列表
|
||||
GetRecentAuthorizations(ctx context.Context, req *models.DashboardRecentAuthorizationsRequest) (*models.DashboardRecentAuthorizationsResponse, error)
|
||||
}
|
||||
Reference in new issue
Block a user