修复所有分页页面统计从当前页计算的问题,改为服务端统计
This commit is contained in:
@@ -80,6 +80,11 @@ func handleGetAllAnnouncements(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
countQuery.Count(&total)
|
countQuery.Count(&total)
|
||||||
|
|
||||||
|
var activeCount, inactiveCount, topCount int64
|
||||||
|
database.DB.Model(&model.Announcement{}).Where("application_id IN ? AND status = ?", appIDs, "active").Count(&activeCount)
|
||||||
|
database.DB.Model(&model.Announcement{}).Where("application_id IN ? AND status = ?", appIDs, "inactive").Count(&inactiveCount)
|
||||||
|
database.DB.Model(&model.Announcement{}).Where("application_id IN ? AND is_top = ?", appIDs, true).Count(&topCount)
|
||||||
|
|
||||||
query := database.DB.Where("application_id IN ?", appIDs)
|
query := database.DB.Where("application_id IN ?", appIDs)
|
||||||
if applicationIDFilter != "" {
|
if applicationIDFilter != "" {
|
||||||
query = query.Where("application_id = ?", applicationIDFilter)
|
query = query.Where("application_id = ?", applicationIDFilter)
|
||||||
@@ -133,6 +138,9 @@ func handleGetAllAnnouncements(c *gin.Context) {
|
|||||||
response.Success(c, gin.H{
|
response.Success(c, gin.H{
|
||||||
"announcements": result,
|
"announcements": result,
|
||||||
"total": total,
|
"total": total,
|
||||||
|
"active_count": activeCount,
|
||||||
|
"inactive_count": inactiveCount,
|
||||||
|
"top_count": topCount,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,6 +106,9 @@ func handleGetDevices(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
countQuery.Count(&total)
|
countQuery.Count(&total)
|
||||||
|
|
||||||
|
var bannedCount int64
|
||||||
|
database.DB.Model(&model.UserDevice{}).Where("application_id IN ? AND status = ?", appIDs, "banned").Count(&bannedCount)
|
||||||
|
|
||||||
query := database.DB.Preload("User").Preload("Application").Where("application_id IN ?", appIDs)
|
query := database.DB.Preload("User").Preload("Application").Where("application_id IN ?", appIDs)
|
||||||
|
|
||||||
if userIDFilter != "" {
|
if userIDFilter != "" {
|
||||||
@@ -168,11 +171,12 @@ func handleGetDevices(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
response.Success(c, gin.H{
|
response.Success(c, gin.H{
|
||||||
"devices": devicesWithDetails,
|
"devices": devicesWithDetails,
|
||||||
"total": total,
|
"total": total,
|
||||||
"page": page,
|
"page": page,
|
||||||
"page_size": pageSize,
|
"page_size": pageSize,
|
||||||
"total_page": (total + int64(pageSize) - 1) / int64(pageSize),
|
"total_page": (total + int64(pageSize) - 1) / int64(pageSize),
|
||||||
|
"banned_count": bannedCount,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -68,6 +68,11 @@ func handleGetLogs(c *gin.Context) {
|
|||||||
|
|
||||||
query.Count(&total)
|
query.Count(&total)
|
||||||
|
|
||||||
|
var successCount, failedCount, operationCount int64
|
||||||
|
database.DB.Model(&model.ApiUsage{}).Where("application_id IN ? OR user_id = ?", appIDs, userID).Where("status = ?", "success").Count(&successCount)
|
||||||
|
database.DB.Model(&model.ApiUsage{}).Where("application_id IN ? OR user_id = ?", appIDs, userID).Where("status = ?", "failed").Count(&failedCount)
|
||||||
|
database.DB.Model(&model.ApiUsage{}).Where("application_id IN ? OR user_id = ?", appIDs, userID).Where("log_type = ?", "operation").Count(&operationCount)
|
||||||
|
|
||||||
offset := (page - 1) * pageSize
|
offset := (page - 1) * pageSize
|
||||||
if err := query.Preload("User").Preload("Application").Preload("AppUser").Order("created_at DESC").Offset(offset).Limit(pageSize).Find(&logs).Error; err != nil {
|
if err := query.Preload("User").Preload("Application").Preload("AppUser").Order("created_at DESC").Offset(offset).Limit(pageSize).Find(&logs).Error; err != nil {
|
||||||
response.Error(c, 500, "获取日志失败")
|
response.Error(c, 500, "获取日志失败")
|
||||||
@@ -75,10 +80,13 @@ func handleGetLogs(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
response.Success(c, gin.H{
|
response.Success(c, gin.H{
|
||||||
"logs": logs,
|
"logs": logs,
|
||||||
"total": total,
|
"total": total,
|
||||||
"page": page,
|
"page": page,
|
||||||
"page_size": pageSize,
|
"page_size": pageSize,
|
||||||
"total_page": (total + int64(pageSize) - 1) / int64(pageSize),
|
"total_page": (total + int64(pageSize) - 1) / int64(pageSize),
|
||||||
|
"success_count": successCount,
|
||||||
|
"failed_count": failedCount,
|
||||||
|
"operation_count": operationCount,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,6 +88,11 @@ func handleGetTickets(c *gin.Context) {
|
|||||||
var total int64
|
var total int64
|
||||||
query.Count(&total)
|
query.Count(&total)
|
||||||
|
|
||||||
|
var openCount, processingCount, resolvedCount int64
|
||||||
|
database.DB.Model(&model.Ticket{}).Where("user_id = ? OR assigned_to = ?", userID, userID).Where("status = ?", "open").Count(&openCount)
|
||||||
|
database.DB.Model(&model.Ticket{}).Where("user_id = ? OR assigned_to = ?", userID, userID).Where("status = ?", "processing").Count(&processingCount)
|
||||||
|
database.DB.Model(&model.Ticket{}).Where("user_id = ? OR assigned_to = ?", userID, userID).Where("status = ?", "resolved").Count(&resolvedCount)
|
||||||
|
|
||||||
offset := (page - 1) * pageSize
|
offset := (page - 1) * pageSize
|
||||||
|
|
||||||
var tickets []model.Ticket
|
var tickets []model.Ticket
|
||||||
@@ -128,11 +133,14 @@ func handleGetTickets(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
response.Success(c, gin.H{
|
response.Success(c, gin.H{
|
||||||
"tickets": result,
|
"tickets": result,
|
||||||
"total": total,
|
"total": total,
|
||||||
"page": page,
|
"page": page,
|
||||||
"page_size": pageSize,
|
"page_size": pageSize,
|
||||||
"total_page": (total + int64(pageSize) - 1) / int64(pageSize),
|
"total_page": (total + int64(pageSize) - 1) / int64(pageSize),
|
||||||
|
"open_count": openCount,
|
||||||
|
"processing_count": processingCount,
|
||||||
|
"resolved_count": resolvedCount,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -95,6 +95,9 @@ func handleGetAllVersions(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
countQuery.Count(&total)
|
countQuery.Count(&total)
|
||||||
|
|
||||||
|
var forcedCount int64
|
||||||
|
database.DB.Model(&model.Version{}).Where("application_id IN ? AND update_strategy = ?", appIDs, "forced").Count(&forcedCount)
|
||||||
|
|
||||||
query := database.DB.Where("application_id IN ?", appIDs)
|
query := database.DB.Where("application_id IN ?", appIDs)
|
||||||
if applicationIDFilter != "" {
|
if applicationIDFilter != "" {
|
||||||
query = query.Where("application_id = ?", applicationIDFilter)
|
query = query.Where("application_id = ?", applicationIDFilter)
|
||||||
@@ -184,8 +187,9 @@ func handleGetAllVersions(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
response.Success(c, gin.H{
|
response.Success(c, gin.H{
|
||||||
"versions": result,
|
"versions": result,
|
||||||
"total": total,
|
"total": total,
|
||||||
|
"forced_count": forcedCount,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ const searchFilter = ref<string>('')
|
|||||||
const currentPage = ref(1)
|
const currentPage = ref(1)
|
||||||
const pageSize = ref(20)
|
const pageSize = ref(20)
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
|
const activeCount = ref(0)
|
||||||
|
const inactiveCount = ref(0)
|
||||||
|
const topCount = ref(0)
|
||||||
|
|
||||||
const deleteDialogOpen = ref(false)
|
const deleteDialogOpen = ref(false)
|
||||||
const deleteTarget = ref<Announcement | null>(null)
|
const deleteTarget = ref<Announcement | null>(null)
|
||||||
@@ -60,10 +63,6 @@ const statusOptions = computed(() => [
|
|||||||
{ label: t('admin.announcements.statuses.inactive'), value: 'inactive' },
|
{ label: t('admin.announcements.statuses.inactive'), value: 'inactive' },
|
||||||
])
|
])
|
||||||
|
|
||||||
const activeCount = computed(() => announcements.value.filter(a => a.status === 'active').length)
|
|
||||||
const inactiveCount = computed(() => announcements.value.filter(a => a.status === 'inactive').length)
|
|
||||||
const topCount = computed(() => announcements.value.filter(a => a.is_top).length)
|
|
||||||
|
|
||||||
const serverPagination = computed(() => ({
|
const serverPagination = computed(() => ({
|
||||||
page: currentPage.value,
|
page: currentPage.value,
|
||||||
pageSize: pageSize.value,
|
pageSize: pageSize.value,
|
||||||
@@ -107,9 +106,12 @@ async function fetchAnnouncements() {
|
|||||||
params.append('search', searchFilter.value)
|
params.append('search', searchFilter.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await api.get<{ announcements: Announcement[], total: number }>(`/dev/announcements?${params.toString()}`)
|
const data = await api.get<any>(`/dev/announcements?${params.toString()}`)
|
||||||
announcements.value = data?.announcements || []
|
announcements.value = data?.announcements || []
|
||||||
total.value = data?.total || 0
|
total.value = data?.total || 0
|
||||||
|
activeCount.value = data?.active_count || 0
|
||||||
|
inactiveCount.value = data?.inactive_count || 0
|
||||||
|
topCount.value = data?.top_count || 0
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error('加载公告失败:', error)
|
console.error('加载公告失败:', error)
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ const userIdFilter = ref<string>('')
|
|||||||
const currentPage = ref(1)
|
const currentPage = ref(1)
|
||||||
const pageSize = ref(20)
|
const pageSize = ref(20)
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
|
const bannedCount = ref(0)
|
||||||
|
|
||||||
const deleteDialogOpen = ref(false)
|
const deleteDialogOpen = ref(false)
|
||||||
const deleteTarget = ref<Device | null>(null)
|
const deleteTarget = ref<Device | null>(null)
|
||||||
@@ -48,7 +49,6 @@ const forceOfflineTarget = ref<Device | null>(null)
|
|||||||
|
|
||||||
const totalDevices = computed(() => total.value)
|
const totalDevices = computed(() => total.value)
|
||||||
const onlineSessionCount = computed(() => devices.value.reduce((sum, d) => sum + (d.online_sessions || 0), 0))
|
const onlineSessionCount = computed(() => devices.value.reduce((sum, d) => sum + (d.online_sessions || 0), 0))
|
||||||
const bannedCount = computed(() => devices.value.filter(device => device.status === 'banned').length)
|
|
||||||
|
|
||||||
const applicationOptions = computed(() => {
|
const applicationOptions = computed(() => {
|
||||||
return applications.value.map(app => ({
|
return applications.value.map(app => ({
|
||||||
@@ -115,9 +115,10 @@ async function fetchDevices() {
|
|||||||
params.append('user_id', userIdFilter.value)
|
params.append('user_id', userIdFilter.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await api.get<{ devices: Device[], total: number }>(`/dev/devices?${params.toString()}`)
|
const data = await api.get<any>(`/dev/devices?${params.toString()}`)
|
||||||
devices.value = Array.isArray(data?.devices) ? data.devices : []
|
devices.value = Array.isArray(data?.devices) ? data.devices : []
|
||||||
total.value = data?.total || 0
|
total.value = data?.total || 0
|
||||||
|
bannedCount.value = data?.banned_count || 0
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error('获取设备列表失败:', error)
|
console.error('获取设备列表失败:', error)
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ const applications = ref<Application[]>([])
|
|||||||
const currentPage = ref(1)
|
const currentPage = ref(1)
|
||||||
const pageSize = ref(20)
|
const pageSize = ref(20)
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
|
const successCount = ref(0)
|
||||||
|
const failedCount = ref(0)
|
||||||
|
const operationCount = ref(0)
|
||||||
|
|
||||||
const appFilter = ref<string>('')
|
const appFilter = ref<string>('')
|
||||||
const typeFilter = ref<string>('')
|
const typeFilter = ref<string>('')
|
||||||
@@ -31,10 +34,6 @@ const statusFilter = ref<string>('')
|
|||||||
const startDate = ref<string>('')
|
const startDate = ref<string>('')
|
||||||
const endDate = ref<string>('')
|
const endDate = ref<string>('')
|
||||||
|
|
||||||
const successCount = computed(() => logs.value.filter(log => log.status === 'success').length)
|
|
||||||
const failedCount = computed(() => logs.value.filter(log => log.status === 'failed').length)
|
|
||||||
const operationCount = computed(() => logs.value.filter(log => log.log_type === 'operation').length)
|
|
||||||
|
|
||||||
const applicationOptions = computed(() => {
|
const applicationOptions = computed(() => {
|
||||||
return applications.value.map(app => ({
|
return applications.value.map(app => ({
|
||||||
label: app.name,
|
label: app.name,
|
||||||
@@ -86,9 +85,12 @@ async function fetchLogs() {
|
|||||||
params.append('end_date', endDate.value.split('T')[0])
|
params.append('end_date', endDate.value.split('T')[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await api.get<{ logs: Log[], total: number }>(`/dev/logs?${params.toString()}`)
|
const data = await api.get<any>(`/dev/logs?${params.toString()}`)
|
||||||
logs.value = data?.logs || []
|
logs.value = data?.logs || []
|
||||||
total.value = data?.total || 0
|
total.value = data?.total || 0
|
||||||
|
successCount.value = data?.success_count || 0
|
||||||
|
failedCount.value = data?.failed_count || 0
|
||||||
|
operationCount.value = data?.operation_count || 0
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error('获取日志记录失败:', error)
|
console.error('获取日志记录失败:', error)
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ const tableRef = ref()
|
|||||||
const currentPage = ref(1)
|
const currentPage = ref(1)
|
||||||
const pageSize = ref(20)
|
const pageSize = ref(20)
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
|
const openCount = ref(0)
|
||||||
|
const pendingCount = ref(0)
|
||||||
|
const resolvedCount = ref(0)
|
||||||
|
|
||||||
const statusFilter = ref<string>('')
|
const statusFilter = ref<string>('')
|
||||||
const priorityFilter = ref<string>('')
|
const priorityFilter = ref<string>('')
|
||||||
@@ -38,10 +41,6 @@ const deleteTarget = ref<Ticket | null>(null)
|
|||||||
const batchDeleteDialogOpen = ref(false)
|
const batchDeleteDialogOpen = ref(false)
|
||||||
const batchDeleteIds = ref<(string | number)[]>([])
|
const batchDeleteIds = ref<(string | number)[]>([])
|
||||||
|
|
||||||
const openCount = computed(() => tickets.value.filter(t => t.status === 'open').length)
|
|
||||||
const pendingCount = computed(() => tickets.value.filter(t => t.status === 'processing').length)
|
|
||||||
const resolvedCount = computed(() => tickets.value.filter(t => t.status === 'resolved').length)
|
|
||||||
|
|
||||||
const statusOptions = computed(() => [
|
const statusOptions = computed(() => [
|
||||||
{ label: t('admin.tickets.status.open'), value: 'open' },
|
{ label: t('admin.tickets.status.open'), value: 'open' },
|
||||||
{ label: t('admin.tickets.status.processing'), value: 'processing' },
|
{ label: t('admin.tickets.status.processing'), value: 'processing' },
|
||||||
@@ -90,9 +89,12 @@ async function fetchTickets() {
|
|||||||
params.append('updated_end_date', updatedEndDate.value.split('T')[0])
|
params.append('updated_end_date', updatedEndDate.value.split('T')[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await api.get<{ tickets: Ticket[], total: number }>(`/dev/tickets?${params.toString()}`)
|
const data = await api.get<any>(`/dev/tickets?${params.toString()}`)
|
||||||
tickets.value = data?.tickets || []
|
tickets.value = data?.tickets || []
|
||||||
total.value = data?.total || 0
|
total.value = data?.total || 0
|
||||||
|
openCount.value = data?.open_count || 0
|
||||||
|
pendingCount.value = data?.processing_count || 0
|
||||||
|
resolvedCount.value = data?.resolved_count || 0
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error('获取工单列表失败:', error)
|
console.error('获取工单列表失败:', error)
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ const createdEndDate = ref<string>('')
|
|||||||
const currentPage = ref(1)
|
const currentPage = ref(1)
|
||||||
const pageSize = ref(20)
|
const pageSize = ref(20)
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
|
const onlineCount = ref(0)
|
||||||
|
const offlineCount = ref(0)
|
||||||
|
const bannedCount = ref(0)
|
||||||
|
|
||||||
const deleteDialogOpen = ref(false)
|
const deleteDialogOpen = ref(false)
|
||||||
const deleteTarget = ref<User | null>(null)
|
const deleteTarget = ref<User | null>(null)
|
||||||
@@ -89,10 +92,6 @@ const filteredUsers = computed(() => {
|
|||||||
return result
|
return result
|
||||||
})
|
})
|
||||||
|
|
||||||
const onlineCount = computed(() => users.value.filter(user => user.online_status === 'online').length)
|
|
||||||
const offlineCount = computed(() => users.value.filter(user => user.online_status === 'offline').length)
|
|
||||||
const bannedCount = computed(() => users.value.filter(user => user.status === 'banned').length)
|
|
||||||
|
|
||||||
const serverPagination = computed(() => ({
|
const serverPagination = computed(() => ({
|
||||||
page: currentPage.value,
|
page: currentPage.value,
|
||||||
pageSize: pageSize.value,
|
pageSize: pageSize.value,
|
||||||
@@ -147,9 +146,12 @@ async function fetchUsers() {
|
|||||||
params.append('status', accountStatusFilter.value)
|
params.append('status', accountStatusFilter.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await api.get<{ users: User[], total: number }>(`/dev/app-users?${params.toString()}`)
|
const data = await api.get<any>(`/dev/app-users?${params.toString()}`)
|
||||||
users.value = Array.isArray(data?.users) ? data.users : []
|
users.value = Array.isArray(data?.users) ? data.users : []
|
||||||
total.value = data?.total || 0
|
total.value = data?.total || 0
|
||||||
|
onlineCount.value = data?.online_count || 0
|
||||||
|
offlineCount.value = data?.offline_count || 0
|
||||||
|
bannedCount.value = data?.banned_count || 0
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error('获取用户列表失败:', error)
|
console.error('获取用户列表失败:', error)
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ const searchFilter = ref<string>('')
|
|||||||
const currentPage = ref(1)
|
const currentPage = ref(1)
|
||||||
const pageSize = ref(20)
|
const pageSize = ref(20)
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
|
const forcedCount = ref(0)
|
||||||
|
|
||||||
const deleteDialogOpen = ref(false)
|
const deleteDialogOpen = ref(false)
|
||||||
const deleteTarget = ref<Version | null>(null)
|
const deleteTarget = ref<Version | null>(null)
|
||||||
@@ -71,8 +72,6 @@ const totalSize = computed(() => {
|
|||||||
return versions.value.reduce((sum, v) => sum + (v.file_size || 0), 0)
|
return versions.value.reduce((sum, v) => sum + (v.file_size || 0), 0)
|
||||||
})
|
})
|
||||||
|
|
||||||
const forcedCount = computed(() => versions.value.filter(v => v.update_strategy === 'forced').length)
|
|
||||||
|
|
||||||
const serverPagination = computed(() => ({
|
const serverPagination = computed(() => ({
|
||||||
page: currentPage.value,
|
page: currentPage.value,
|
||||||
pageSize: pageSize.value,
|
pageSize: pageSize.value,
|
||||||
@@ -128,9 +127,10 @@ async function fetchVersions() {
|
|||||||
params.append('search', searchFilter.value)
|
params.append('search', searchFilter.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await api.get<{ versions: Version[], total: number }>(`/dev/versions?${params.toString()}`)
|
const data = await api.get<any>(`/dev/versions?${params.toString()}`)
|
||||||
versions.value = data?.versions || []
|
versions.value = data?.versions || []
|
||||||
total.value = data?.total || 0
|
total.value = data?.total || 0
|
||||||
|
forcedCount.value = data?.forced_count || 0
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error('加载版本列表失败:', error)
|
console.error('加载版本列表失败:', error)
|
||||||
|
|||||||
Reference in New Issue
Block a user