diff --git a/backend/internal/handler/dto/mappers.go b/backend/internal/handler/dto/mappers.go index d2ccb8d6..2f18c64e 100644 --- a/backend/internal/handler/dto/mappers.go +++ b/backend/internal/handler/dto/mappers.go @@ -21,6 +21,8 @@ func UserFromServiceShallow(u *service.User) *User { Concurrency: u.Concurrency, Status: u.Status, AllowedGroups: u.AllowedGroups, + LastLoginAt: u.LastLoginAt, + LastActiveAt: u.LastActiveAt, CreatedAt: u.CreatedAt, UpdatedAt: u.UpdatedAt, BalanceNotifyEnabled: u.BalanceNotifyEnabled, diff --git a/backend/internal/handler/dto/types.go b/backend/internal/handler/dto/types.go index 8c1e166f..72fce1fe 100644 --- a/backend/internal/handler/dto/types.go +++ b/backend/internal/handler/dto/types.go @@ -7,16 +7,18 @@ import ( ) type User struct { - ID int64 `json:"id"` - Email string `json:"email"` - Username string `json:"username"` - Role string `json:"role"` - Balance float64 `json:"balance"` - Concurrency int `json:"concurrency"` - Status string `json:"status"` - AllowedGroups []int64 `json:"allowed_groups"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` + ID int64 `json:"id"` + Email string `json:"email"` + Username string `json:"username"` + Role string `json:"role"` + Balance float64 `json:"balance"` + Concurrency int `json:"concurrency"` + Status string `json:"status"` + AllowedGroups []int64 `json:"allowed_groups"` + LastLoginAt *time.Time `json:"last_login_at,omitempty"` + LastActiveAt *time.Time `json:"last_active_at,omitempty"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` // 余额不足通知 BalanceNotifyEnabled bool `json:"balance_notify_enabled"` diff --git a/backend/internal/handler/dto/user_mapper_activity_test.go b/backend/internal/handler/dto/user_mapper_activity_test.go new file mode 100644 index 00000000..668f886c --- /dev/null +++ b/backend/internal/handler/dto/user_mapper_activity_test.go @@ -0,0 +1,32 @@ +package dto + +import ( + "testing" + "time" + + "github.com/Wei-Shaw/sub2api/internal/service" + "github.com/stretchr/testify/require" +) + +func TestUserFromServiceAdmin_MapsActivityTimestamps(t *testing.T) { + t.Parallel() + + lastLoginAt := time.Date(2026, time.April, 20, 10, 0, 0, 0, time.UTC) + lastActiveAt := lastLoginAt.Add(15 * time.Minute) + + out := UserFromServiceAdmin(&service.User{ + ID: 42, + Email: "admin@example.com", + Username: "admin", + Role: service.RoleAdmin, + Status: service.StatusActive, + LastLoginAt: &lastLoginAt, + LastActiveAt: &lastActiveAt, + }) + + require.NotNil(t, out) + require.NotNil(t, out.LastLoginAt) + require.NotNil(t, out.LastActiveAt) + require.WithinDuration(t, lastLoginAt, *out.LastLoginAt, time.Second) + require.WithinDuration(t, lastActiveAt, *out.LastActiveAt, time.Second) +} diff --git a/frontend/src/i18n/locales/en.ts b/frontend/src/i18n/locales/en.ts index d1def45c..684c196f 100644 --- a/frontend/src/i18n/locales/en.ts +++ b/frontend/src/i18n/locales/en.ts @@ -1391,6 +1391,8 @@ export default { usage: 'Usage', concurrency: 'Concurrency', status: 'Status', + lastLogin: 'Last Login', + lastActive: 'Last Active', created: 'Created', actions: 'Actions' }, diff --git a/frontend/src/i18n/locales/zh.ts b/frontend/src/i18n/locales/zh.ts index 6f57ab3e..2a4c69a5 100644 --- a/frontend/src/i18n/locales/zh.ts +++ b/frontend/src/i18n/locales/zh.ts @@ -1417,6 +1417,8 @@ export default { usage: '用量', concurrency: '并发数', status: '状态', + lastLogin: '最后登录', + lastActive: '最后使用', created: '创建时间', actions: '操作' }, diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts index 529eff55..9c9722a9 100644 --- a/frontend/src/types/index.ts +++ b/frontend/src/types/index.ts @@ -47,6 +47,8 @@ export interface User { balance_notify_threshold: number | null balance_notify_extra_emails: NotifyEmailEntry[] subscriptions?: UserSubscription[] // User's active subscriptions + last_login_at?: string | null + last_active_at?: string | null created_at: string updated_at: string } diff --git a/frontend/src/views/admin/UsersView.vue b/frontend/src/views/admin/UsersView.vue index 8b072d7a..55a8f2d8 100644 --- a/frontend/src/views/admin/UsersView.vue +++ b/frontend/src/views/admin/UsersView.vue @@ -455,6 +455,18 @@ {{ formatDateTime(value) }} + + + +