feat(inbounds): add multi-select and bulk delete

Mirror the clients page: checkbox selection on the desktop table and on
mobile cards, with a danger Delete button in the toolbar that removes all
selected inbounds in one call.

Backend adds POST /panel/api/inbounds/bulkDel, which loops the existing
DelInbound per id (xray restarts at most once) and returns {deleted,
skipped}. Frontend shows a confirm modal plus a result toast, clears the
selection on success, adds bulk-delete i18n keys across all 13 languages,
and documents the endpoint in the in-panel API docs.
This commit is contained in:
MHSanaei
2026-05-31 00:29:24 +02:00
parent 6bb5a3b56b
commit cf50952921
21 changed files with 315 additions and 4 deletions
+31
View File
@@ -617,6 +617,37 @@ func (s *InboundService) DelInbound(id int) (bool, error) {
return needRestart, db.Delete(model.Inbound{}, id).Error
}
type BulkDelInboundResult struct {
Deleted int `json:"deleted"`
Skipped []BulkDelInboundReport `json:"skipped,omitempty"`
}
type BulkDelInboundReport struct {
Id int `json:"id"`
Reason string `json:"reason"`
}
// DelInbounds removes every inbound in the list, reusing the single-delete
// path per id. Failures are recorded in Skipped and processing continues for
// the rest; the aggregated needRestart is returned so the caller restarts
// xray at most once.
func (s *InboundService) DelInbounds(ids []int) (BulkDelInboundResult, bool, error) {
result := BulkDelInboundResult{}
needRestart := false
for _, id := range ids {
r, err := s.DelInbound(id)
if err != nil {
result.Skipped = append(result.Skipped, BulkDelInboundReport{Id: id, Reason: err.Error()})
continue
}
result.Deleted++
if r {
needRestart = true
}
}
return result, needRestart, nil
}
func (s *InboundService) GetInbound(id int) (*model.Inbound, error) {
db := database.GetDB()
inbound := &model.Inbound{}