---
name: 统计卡片数据来源问题
description: 记录分页列表页面统计卡片显示不正确的原因和解决方案
type: feedback
---

## 问题现象

在管理员后台和代理后台的列表页面（如卡密管理、设备管理、用户管理、工单管理），统计卡片显示的数量不正确。例如：
- 卡密管理页面显示"未使用20张"，但实际数据库中有更多
- 表格只显示当前页的数据，但统计卡片应该显示全局总数

## 根本原因

前端使用 `computed` 从当前页面数据计算统计值：

```typescript
// 错误做法：只统计当前页数据
const unusedCount = computed(() => cards.value.filter(card => card.status === 'unused').length)
```

当使用服务端分页时，`cards.value` 只包含当前页的数据（如20条），而不是全局数据。因此统计值只反映当前页的情况。

## 解决方案

### 后端修改

在 API 响应中添加 `stats` 字段，返回全局统计数据：

```go
// 获取统计数据（无筛选条件时的全局统计）
var statsUnused, statsUsed, statsBanned int64
database.DB.Model(&model.Card{}).Where("status = ?", "unused").Count(&statsUnused)
// ... 其他状态

response.Success(c, gin.H{
    "cards": cards,
    "total": total,
    "stats": gin.H{
        "unused": statsUnused,
        "used":   statsUsed,
        "banned": statsBanned,
    },
})
```

### 前端修改

1. 添加 `stats` ref 变量：
```typescript
const stats = ref({ unused: 0, used: 0, banned: 0 })
```

2. 使用后端返回的统计数据：
```typescript
const unusedCount = computed(() => stats.value.unused)
const usedCount = computed(() => stats.value.used)
const bannedCount = computed(() => stats.value.banned)
```

3. 从 API 响应中提取统计：
```typescript
if (data?.stats) {
  stats.value = data.stats
}
```

## 已修复的页面

- `frontend/src/pages/admin/cards/index.vue` - 卡密管理（管理员）
- `frontend/src/pages/agent/cards/index.vue` - 卡密管理（代理）
- `frontend/src/pages/admin/devices/index.vue` - 设备管理
- `frontend/src/pages/admin/users/index.vue` - 用户管理
- `frontend/src/pages/admin/tickets.vue` - 工单管理

## 相关后端修改

- `backend/internal/router/admin/cards.go` - 添加 stats 返回
- `backend/internal/router/agent/agent.go` - handleGetCards 添加 stats 返回
- `backend/internal/router/admin/devices.go` - handleGetDevices 添加 stats 返回
- `backend/internal/router/admin/users.go` - handleGetUsers 已有统计返回
- `backend/internal/router/admin/tickets.go` - 已有 /tickets/stats 端点

## 设计原则

**Why:** 服务端分页时，前端只能访问当前页数据，无法获取全局统计
**How to apply:** 所有需要显示全局统计的分页列表页面，都应从后端获取统计数据，而不是前端计算
