From 409ec4f75b5b34a15ae0026c5b3796d537841518 Mon Sep 17 00:00:00 2001 From: admin Date: Sun, 10 May 2026 14:12:35 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D:=201.=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=91=98=E7=BC=96=E8=BE=91=E4=BB=A3=E7=90=86=E4=BA=91=E7=AB=AF?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90switch=E6=97=A0=E6=95=88(?= =?UTF-8?q?=E5=90=8E=E7=AB=AF=E7=BC=BA=E5=B0=91CanViewCloudData=E5=AD=97?= =?UTF-8?q?=E6=AE=B5)=202.=E4=BB=A3=E7=90=86=E5=8D=A1=E5=AF=86status?= =?UTF-8?q?=E6=98=BE=E7=A4=BAdisabledbanned=203.=E4=BB=A3=E7=90=86?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E7=AE=A1=E7=90=86=E5=8F=AA=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E4=BB=A3=E7=90=86/=E5=AD=90=E4=BB=A3=E7=90=86=E5=8D=A1?= =?UTF-8?q?=E5=AF=86=E5=85=85=E5=80=BC=E8=BF=87=E7=9A=84=E7=94=A8=E6=88=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/model/models.go | 1 + backend/internal/router/admin/agents.go | 59 +++++++++++-------- backend/internal/router/agent/agent.go | 57 ++++++++++++------ .../pages/agent/cards/components/columns.ts | 2 +- frontend/src/pages/agent/cards/index.vue | 22 +++++-- frontend/src/plugins/i18n/en.json | 4 +- frontend/src/plugins/i18n/zh.json | 4 +- 7 files changed, 99 insertions(+), 50 deletions(-) diff --git a/backend/internal/model/models.go b/backend/internal/model/models.go index 4da4d1d..f76acd0 100644 --- a/backend/internal/model/models.go +++ b/backend/internal/model/models.go @@ -29,6 +29,7 @@ type User struct { ParentAgentID *uint `gorm:"index" json:"parent_agent_id"` CanCreateAgent bool `gorm:"default:false" json:"can_create_agent"` + CanViewCloudData bool `gorm:"default:false" json:"can_view_cloud_data"` Balance float64 `gorm:"default:0" json:"balance"` TotalConsumption float64 `gorm:"default:0" json:"total_consumption"` diff --git a/backend/internal/router/admin/agents.go b/backend/internal/router/admin/agents.go index d9020d7..2aa429a 100644 --- a/backend/internal/router/admin/agents.go +++ b/backend/internal/router/admin/agents.go @@ -42,7 +42,8 @@ type AgentTreeNode struct { CreatedAt string `json:"created_at"` LastLoginAt string `json:"last_login_at"` Balance float64 `json:"balance"` - CanCreateAgent bool `json:"can_create_agent"` + CanCreateAgent bool `json:"can_create_agent"` + CanViewCloudData bool `json:"can_view_cloud_data"` CardsCount int `json:"cards_count"` ChildAgentsCount int `json:"child_agents_count"` Children []AgentTreeNode `json:"children,omitempty"` @@ -80,6 +81,7 @@ func handleGetAgents(c *gin.Context) { Balance float64 `json:"balance"` TotalConsumption float64 `json:"total_consumption"` CanCreateAgent bool `json:"can_create_agent"` + CanViewCloudData bool `json:"can_view_cloud_data"` CardsCount int `json:"cards_count"` ChildAgentsCount int `json:"child_agents_count"` } @@ -152,8 +154,9 @@ func handleGetAgents(c *gin.Context) { LastLoginAt: lastLoginAt, Balance: user.Balance, TotalConsumption: user.TotalConsumption, - CanCreateAgent: user.CanCreateAgent, - CardsCount: cardsCountMap[user.ID], + CanCreateAgent: user.CanCreateAgent, + CanViewCloudData: user.CanViewCloudData, + CardsCount: cardsCountMap[user.ID], ChildAgentsCount: childCountMap[user.ID], }) } @@ -229,8 +232,9 @@ func handleGetAgentsTree(c *gin.Context) { CreatedAt: user.CreatedAt.Format("2006-01-02 15:04:05"), LastLoginAt: lastLoginAt, Balance: user.Balance, - CanCreateAgent: user.CanCreateAgent, - CardsCount: int(cardsCount), + CanCreateAgent: user.CanCreateAgent, + CanViewCloudData: user.CanViewCloudData, + CardsCount: int(cardsCount), ChildAgentsCount: int(childAgentsCount), } @@ -256,12 +260,13 @@ func handleGetAgentsTree(c *gin.Context) { func handleCreateAgent(c *gin.Context) { var req struct { - Username string `json:"username" binding:"required"` - Email string `json:"email"` - Password string `json:"password" binding:"required"` - ParentAgentID *uint `json:"parent_agent_id"` - CanCreateAgent bool `json:"can_create_agent"` - Balance float64 `json:"balance"` + Username string `json:"username" binding:"required"` + Email string `json:"email"` + Password string `json:"password" binding:"required"` + ParentAgentID *uint `json:"parent_agent_id"` + CanCreateAgent bool `json:"can_create_agent"` + CanViewCloudData bool `json:"can_view_cloud_data"` + Balance float64 `json:"balance"` } if err := c.ShouldBindJSON(&req); err != nil { response.Error(c, 400, "参数错误") @@ -296,13 +301,14 @@ func handleCreateAgent(c *gin.Context) { } user := model.User{ - Username: req.Username, - Password: string(hashedPassword), - Role: "agent", - Status: "active", - ParentAgentID: req.ParentAgentID, - CanCreateAgent: req.CanCreateAgent, - Balance: req.Balance, + Username: req.Username, + Password: string(hashedPassword), + Role: "agent", + Status: "active", + ParentAgentID: req.ParentAgentID, + CanCreateAgent: req.CanCreateAgent, + CanViewCloudData: req.CanViewCloudData, + Balance: req.Balance, } if req.Email != "" { @@ -406,7 +412,8 @@ func handleGetAgentDetail(c *gin.Context) { "role": user.Role, "parent_agent_id": user.ParentAgentID, "parent_agent_name": parentAgentName, - "can_create_agent": user.CanCreateAgent, + "can_create_agent": user.CanCreateAgent, + "can_view_cloud_data": user.CanViewCloudData, "balance": user.Balance, "created_at": user.CreatedAt.Format("2006-01-02 15:04:05"), "last_login_at": lastLoginAt, @@ -426,11 +433,12 @@ func handleUpdateAgent(c *gin.Context) { } var req struct { - ParentAgentID *uint `json:"parent_agent_id"` - Email *string `json:"email"` - Password *string `json:"password"` - CanCreateAgent *bool `json:"can_create_agent"` - Balance *float64 `json:"balance"` + ParentAgentID *uint `json:"parent_agent_id"` + Email *string `json:"email"` + Password *string `json:"password"` + CanCreateAgent *bool `json:"can_create_agent"` + CanViewCloudData *bool `json:"can_view_cloud_data"` + Balance *float64 `json:"balance"` } if err := c.ShouldBindJSON(&req); err != nil { response.Error(c, 400, "参数错误") @@ -464,6 +472,9 @@ func handleUpdateAgent(c *gin.Context) { if req.CanCreateAgent != nil { user.CanCreateAgent = *req.CanCreateAgent } + if req.CanViewCloudData != nil { + user.CanViewCloudData = *req.CanViewCloudData + } if req.Balance != nil { user.Balance = *req.Balance } diff --git a/backend/internal/router/agent/agent.go b/backend/internal/router/agent/agent.go index 1cf3b14..e42aab5 100644 --- a/backend/internal/router/agent/agent.go +++ b/backend/internal/router/agent/agent.go @@ -181,8 +181,8 @@ func handleGetCards(c *gin.Context) { var expiredCount int64 database.DB.Model(&model.Card{}).Where("("+baseCondition+") AND status = ?", userID, userID, "expired").Count(&expiredCount) - var disabledCount int64 - database.DB.Model(&model.Card{}).Where("("+baseCondition+") AND status = ?", userID, userID, "disabled").Count(&disabledCount) + var bannedCount int64 + database.DB.Model(&model.Card{}).Where("("+baseCondition+") AND status = ?", userID, userID, "banned").Count(&bannedCount) query := database.DB.Model(&model.Card{}).Where(baseCondition, userID, userID) @@ -283,7 +283,7 @@ func handleGetCards(c *gin.Context) { "unused_count": unusedCount, "used_count": usedCount, "expired_count": expiredCount, - "disabled_count": disabledCount, + "banned_count": bannedCount, }) } @@ -412,17 +412,40 @@ func generateCardCode() string { func handleGetUsers(c *gin.Context) { userID := c.GetUint("user_id") - var agentApps []model.AgentApplication - database.DB.Where("agent_id = ?", userID).Find(&agentApps) - appIDs := make([]uint, 0) - for _, app := range agentApps { - appIDs = append(appIDs, app.ApplicationID) + agentIDs := []uint{userID} + var childAgents []model.User + database.DB.Where("parent_agent_id = ? AND role = ?", userID, "agent").Find(&childAgents) + for _, child := range childAgents { + agentIDs = append(agentIDs, child.ID) } - if len(appIDs) == 0 { + var cardIDs []uint + database.DB.Model(&model.Card{}).Where("agent_id IN ?", agentIDs).Pluck("id", &cardIDs) + + if len(cardIDs) == 0 { response.Success(c, gin.H{ - "users": []interface{}{}, - "total": 0, + "users": []interface{}{}, + "total": 0, + "active_count": 0, + "disabled_count": 0, + "banned_count": 0, + }) + return + } + + var appUserIDs []uint + database.DB.Model(&model.RechargeRecord{}). + Where("card_id IN ? AND status = ?", cardIDs, "success"). + Distinct("user_id"). + Pluck("user_id", &appUserIDs) + + if len(appUserIDs) == 0 { + response.Success(c, gin.H{ + "users": []interface{}{}, + "total": 0, + "active_count": 0, + "disabled_count": 0, + "banned_count": 0, }) return } @@ -431,12 +454,12 @@ func handleGetUsers(c *gin.Context) { pageSize := c.DefaultQuery("page_size", "20") var total int64 - database.DB.Model(&model.AppUser{}).Where("application_id IN ?", appIDs).Count(&total) + database.DB.Model(&model.AppUser{}).Where("id IN ?", appUserIDs).Count(&total) var activeCount, disabledCount, bannedCount int64 - database.DB.Model(&model.AppUser{}).Where("application_id IN ? AND status = ?", appIDs, "active").Count(&activeCount) - database.DB.Model(&model.AppUser{}).Where("application_id IN ? AND status = ?", appIDs, "disabled").Count(&disabledCount) - database.DB.Model(&model.AppUser{}).Where("application_id IN ? AND status = ?", appIDs, "banned").Count(&bannedCount) + database.DB.Model(&model.AppUser{}).Where("id IN ? AND status = ?", appUserIDs, "active").Count(&activeCount) + database.DB.Model(&model.AppUser{}).Where("id IN ? AND status = ?", appUserIDs, "disabled").Count(&disabledCount) + database.DB.Model(&model.AppUser{}).Where("id IN ? AND status = ?", appUserIDs, "banned").Count(&bannedCount) var users []model.AppUser offset := 0 @@ -449,7 +472,7 @@ func handleGetUsers(c *gin.Context) { limit = pageSizeInt } - database.DB.Where("application_id IN ?", appIDs).Order("created_at DESC").Limit(limit).Offset(offset).Find(&users) + database.DB.Where("id IN ?", appUserIDs).Order("created_at DESC").Limit(limit).Offset(offset).Find(&users) response.Success(c, gin.H{ "users": users, @@ -710,7 +733,7 @@ func handleExportCards(c *gin.Context) { for _, card := range cards { ct := cardTypeMap[card.CardTypeID] app := appMap[card.ApplicationID] - statusMap := map[string]string{"unused": "未使用", "used": "已使用", "expired": "已过期", "disabled": "已禁用"} + statusMap := map[string]string{"unused": "未使用", "used": "已使用", "expired": "已过期", "banned": "已禁用"} statusText := statusMap[card.Status] if statusText == "" { statusText = card.Status diff --git a/frontend/src/pages/agent/cards/components/columns.ts b/frontend/src/pages/agent/cards/components/columns.ts index b951afd..7373e04 100644 --- a/frontend/src/pages/agent/cards/components/columns.ts +++ b/frontend/src/pages/agent/cards/components/columns.ts @@ -47,7 +47,7 @@ export function getColumns(t: Composer['t']): ColumnDef[] { unused: { label: t('agent.cards.status.unused'), variant: 'default' }, used: { label: t('agent.cards.status.used'), variant: 'secondary' }, expired: { label: t('agent.cards.status.expired'), variant: 'destructive' }, - disabled: { label: t('agent.cards.status.disabled'), variant: 'secondary' }, + banned: { label: t('agent.cards.status.banned'), variant: 'destructive' }, } const { label, variant } = statusMap[status] || { label: status || '-', variant: 'secondary' } return h(Badge, { variant }, () => label) diff --git a/frontend/src/pages/agent/cards/index.vue b/frontend/src/pages/agent/cards/index.vue index 3147a8a..f9613ff 100644 --- a/frontend/src/pages/agent/cards/index.vue +++ b/frontend/src/pages/agent/cards/index.vue @@ -32,7 +32,7 @@ const total = ref(0) const unusedCount = ref(0) const usedCount = ref(0) const expiredCount = ref(0) -const disabledCount = ref(0) +const bannedCount = ref(0) const currentPage = ref(1) const pageSize = ref(20) const tableRef = ref() @@ -74,7 +74,7 @@ const statusOptions = computed(() => [ { label: t('agent.cards.status.unused'), value: 'unused' }, { label: t('agent.cards.status.used'), value: 'used' }, { label: t('agent.cards.status.expired'), value: 'expired' }, - { label: t('agent.cards.status.disabled'), value: 'disabled' }, + { label: t('agent.cards.status.banned'), value: 'banned' }, ]) const serverPagination = computed(() => ({ @@ -152,7 +152,7 @@ async function fetchCards() { unusedCount.value = data.unused_count || 0 usedCount.value = data.used_count || 0 expiredCount.value = data.expired_count || 0 - disabledCount.value = data.disabled_count || 0 + bannedCount.value = data.banned_count || data.disabled_count || 0 } else if (Array.isArray(data)) { cards.value = data total.value = data.length @@ -241,7 +241,7 @@ onMounted(async () => {
-
+
@@ -297,6 +297,20 @@ onMounted(async () => {
+ + + + + {{ t('agent.cards.banned') }} + + + + +
+ {{ bannedCount }} +
+
+
diff --git a/frontend/src/plugins/i18n/en.json b/frontend/src/plugins/i18n/en.json index ff5a080..4ff4dc1 100644 --- a/frontend/src/plugins/i18n/en.json +++ b/frontend/src/plugins/i18n/en.json @@ -2819,7 +2819,7 @@ "unused": "Unused", "used": "Used", "expired": "Expired", - "disabled": "Disabled", + "banned": "Banned", "totalCards": "Total Cards", "searchPlaceholder": "Search card code, app or card type...", "exportBtn": "Export", @@ -2840,7 +2840,7 @@ "unused": "Unused", "used": "Used", "expired": "Expired", - "disabled": "Disabled" + "banned": "Banned" }, "create": { "title": "Generate Cards", diff --git a/frontend/src/plugins/i18n/zh.json b/frontend/src/plugins/i18n/zh.json index 03f06f2..c2ce4a8 100644 --- a/frontend/src/plugins/i18n/zh.json +++ b/frontend/src/plugins/i18n/zh.json @@ -2820,7 +2820,7 @@ "unused": "未使用", "used": "已使用", "expired": "已过期", - "disabled": "已禁用", + "banned": "已禁用", "totalCards": "卡密总数", "searchPlaceholder": "搜索卡号、应用或卡类...", "exportBtn": "导出", @@ -2841,7 +2841,7 @@ "unused": "未使用", "used": "已使用", "expired": "已过期", - "disabled": "已禁用" + "banned": "已禁用" }, "create": { "title": "生成卡密",