feat(teams): fix checkbox multi-select and improve batch operations UI
- Fix checkbox binding using :model-value instead of :checked - Change selectedIds from Set to reactive array for proper Vue reactivity - Move batch refresh/delete buttons to top bar (matching CardKeysPage layout) - Buttons show selection count like 'Refresh (2)' when items selected - Swap position of 'Add Team' and 'Random Invite' buttons - Remove unused isIndeterminate computed property
This commit is contained in:
@@ -15,13 +15,15 @@ import (
|
||||
// ChatGPTAccountHandler ChatGPT 账号处理器
|
||||
type ChatGPTAccountHandler struct {
|
||||
repo *repository.ChatGPTAccountRepository
|
||||
invitationRepo *repository.InvitationRepository
|
||||
chatgptService *service.ChatGPTService
|
||||
}
|
||||
|
||||
// NewChatGPTAccountHandler 创建处理器
|
||||
func NewChatGPTAccountHandler(repo *repository.ChatGPTAccountRepository, chatgptService *service.ChatGPTService) *ChatGPTAccountHandler {
|
||||
func NewChatGPTAccountHandler(repo *repository.ChatGPTAccountRepository, invitationRepo *repository.InvitationRepository, chatgptService *service.ChatGPTService) *ChatGPTAccountHandler {
|
||||
return &ChatGPTAccountHandler{
|
||||
repo: repo,
|
||||
invitationRepo: invitationRepo,
|
||||
chatgptService: chatgptService,
|
||||
}
|
||||
}
|
||||
@@ -307,10 +309,19 @@ func (h *ChatGPTAccountHandler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// 先删除相关的邀请记录,避免外键约束失败
|
||||
if err := h.invitationRepo.DeleteByAccountID(id); err != nil {
|
||||
respondJSON(w, http.StatusInternalServerError, AccountResponse{
|
||||
Success: false,
|
||||
Message: "Failed to delete related invitations: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.repo.Delete(id); err != nil {
|
||||
respondJSON(w, http.StatusInternalServerError, AccountResponse{
|
||||
Success: false,
|
||||
Message: "Failed to delete account",
|
||||
Message: "Failed to delete account: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -320,3 +331,150 @@ func (h *ChatGPTAccountHandler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
Message: "Account deleted successfully",
|
||||
})
|
||||
}
|
||||
|
||||
// BatchDeleteRequest 批量删除请求
|
||||
type BatchDeleteAccountRequest struct {
|
||||
IDs []int `json:"ids"`
|
||||
}
|
||||
|
||||
// BatchDeleteResponse 批量操作响应
|
||||
type BatchOperationResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
SuccessCount int `json:"success_count"`
|
||||
FailedCount int `json:"failed_count"`
|
||||
}
|
||||
|
||||
// BatchDelete 批量删除账号
|
||||
func (h *ChatGPTAccountHandler) BatchDelete(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodDelete {
|
||||
respondJSON(w, http.StatusMethodNotAllowed, BatchOperationResponse{
|
||||
Success: false,
|
||||
Message: "Method not allowed",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var req BatchDeleteAccountRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
respondJSON(w, http.StatusBadRequest, BatchOperationResponse{
|
||||
Success: false,
|
||||
Message: "Invalid request body",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if len(req.IDs) == 0 {
|
||||
respondJSON(w, http.StatusBadRequest, BatchOperationResponse{
|
||||
Success: false,
|
||||
Message: "No accounts selected",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
successCount := 0
|
||||
failedCount := 0
|
||||
|
||||
for _, id := range req.IDs {
|
||||
// 先删除相关的邀请记录
|
||||
if err := h.invitationRepo.DeleteByAccountID(id); err != nil {
|
||||
failedCount++
|
||||
continue
|
||||
}
|
||||
// 再删除账号
|
||||
if err := h.repo.Delete(id); err != nil {
|
||||
failedCount++
|
||||
continue
|
||||
}
|
||||
successCount++
|
||||
}
|
||||
|
||||
respondJSON(w, http.StatusOK, BatchOperationResponse{
|
||||
Success: failedCount == 0,
|
||||
Message: "Batch delete completed",
|
||||
SuccessCount: successCount,
|
||||
FailedCount: failedCount,
|
||||
})
|
||||
}
|
||||
|
||||
// BatchRefreshRequest 批量刷新请求
|
||||
type BatchRefreshRequest struct {
|
||||
IDs []int `json:"ids"`
|
||||
}
|
||||
|
||||
// BatchRefresh 批量刷新账号
|
||||
func (h *ChatGPTAccountHandler) BatchRefresh(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
respondJSON(w, http.StatusMethodNotAllowed, BatchOperationResponse{
|
||||
Success: false,
|
||||
Message: "Method not allowed",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var req BatchRefreshRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
respondJSON(w, http.StatusBadRequest, BatchOperationResponse{
|
||||
Success: false,
|
||||
Message: "Invalid request body",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if len(req.IDs) == 0 {
|
||||
respondJSON(w, http.StatusBadRequest, BatchOperationResponse{
|
||||
Success: false,
|
||||
Message: "No accounts selected",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
successCount := 0
|
||||
failedCount := 0
|
||||
|
||||
for _, id := range req.IDs {
|
||||
account, err := h.repo.FindByID(id)
|
||||
if err != nil || account == nil {
|
||||
failedCount++
|
||||
continue
|
||||
}
|
||||
|
||||
// 调用 ChatGPT API 获取订阅信息
|
||||
subInfo, err := h.chatgptService.GetSubscription(account.TeamAccountID, account.AuthToken)
|
||||
if err != nil {
|
||||
account.ConsecutiveFailures++
|
||||
account.IsActive = false
|
||||
account.LastCheck = sql.NullTime{Time: time.Now(), Valid: true}
|
||||
h.repo.Update(account)
|
||||
failedCount++
|
||||
continue
|
||||
}
|
||||
|
||||
// 更新账号信息
|
||||
if subInfo.IsValid {
|
||||
account.SeatsInUse = subInfo.SeatsInUse
|
||||
account.SeatsEntitled = subInfo.SeatsEntitled
|
||||
account.ActiveStart = sql.NullTime{Time: subInfo.ActiveStart, Valid: !subInfo.ActiveStart.IsZero()}
|
||||
account.ActiveUntil = sql.NullTime{Time: subInfo.ActiveUntil, Valid: !subInfo.ActiveUntil.IsZero()}
|
||||
account.IsActive = true
|
||||
account.ConsecutiveFailures = 0
|
||||
} else {
|
||||
account.IsActive = false
|
||||
account.ConsecutiveFailures++
|
||||
}
|
||||
account.LastCheck = sql.NullTime{Time: time.Now(), Valid: true}
|
||||
|
||||
if err := h.repo.Update(account); err != nil {
|
||||
failedCount++
|
||||
continue
|
||||
}
|
||||
successCount++
|
||||
}
|
||||
|
||||
respondJSON(w, http.StatusOK, BatchOperationResponse{
|
||||
Success: failedCount == 0,
|
||||
Message: "Batch refresh completed",
|
||||
SuccessCount: successCount,
|
||||
FailedCount: failedCount,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user