feat: refine proxy export and toolbar layout

This commit is contained in:
LLLLLLiulei
2026-02-05 18:35:00 +08:00
parent ce9a247a9d
commit 0c660f8335
9 changed files with 186 additions and 64 deletions

View File

@@ -259,6 +259,12 @@ func (s *stubAdminService) GetAllProxiesWithAccountCount(ctx context.Context) ([
}
func (s *stubAdminService) GetProxy(ctx context.Context, id int64) (*service.Proxy, error) {
for i := range s.proxies {
proxy := s.proxies[i]
if proxy.ID == id {
return &proxy, nil
}
}
proxy := service.Proxy{ID: id, Name: "proxy", Status: service.StatusActive}
return &proxy, nil
}

View File

@@ -2,6 +2,8 @@ package admin
import (
"context"
"fmt"
"strconv"
"strings"
"time"
@@ -14,17 +16,32 @@ import (
func (h *ProxyHandler) ExportData(c *gin.Context) {
ctx := c.Request.Context()
protocol := c.Query("protocol")
status := c.Query("status")
search := strings.TrimSpace(c.Query("search"))
if len(search) > 100 {
search = search[:100]
selectedIDs, err := parseProxyIDs(c)
if err != nil {
response.BadRequest(c, err.Error())
return
}
proxies, err := h.listProxiesFiltered(ctx, protocol, status, search)
if err != nil {
response.ErrorFrom(c, err)
return
var proxies []service.Proxy
if len(selectedIDs) > 0 {
proxies, err = h.getProxiesByIDs(ctx, selectedIDs)
if err != nil {
response.ErrorFrom(c, err)
return
}
} else {
protocol := c.Query("protocol")
status := c.Query("status")
search := strings.TrimSpace(c.Query("search"))
if len(search) > 100 {
search = search[:100]
}
proxies, err = h.listProxiesFiltered(ctx, protocol, status, search)
if err != nil {
response.ErrorFrom(c, err)
return
}
}
dataProxies := make([]DataProxy, 0, len(proxies))
@@ -168,6 +185,50 @@ func (h *ProxyHandler) ImportData(c *gin.Context) {
response.Success(c, result)
}
func (h *ProxyHandler) getProxiesByIDs(ctx context.Context, ids []int64) ([]service.Proxy, error) {
out := make([]service.Proxy, 0, len(ids))
for _, id := range ids {
proxy, err := h.adminService.GetProxy(ctx, id)
if err != nil {
return nil, err
}
if proxy == nil {
continue
}
out = append(out, *proxy)
}
return out, nil
}
func parseProxyIDs(c *gin.Context) ([]int64, error) {
values := c.QueryArray("ids")
if len(values) == 0 {
raw := strings.TrimSpace(c.Query("ids"))
if raw != "" {
values = []string{raw}
}
}
if len(values) == 0 {
return nil, nil
}
ids := make([]int64, 0, len(values))
for _, item := range values {
for _, part := range strings.Split(item, ",") {
part = strings.TrimSpace(part)
if part == "" {
continue
}
id, err := strconv.ParseInt(part, 10, 64)
if err != nil || id <= 0 {
return nil, fmt.Errorf("invalid proxy id: %s", part)
}
ids = append(ids, id)
}
}
return ids, nil
}
func (h *ProxyHandler) listProxiesFiltered(ctx context.Context, protocol, status, search string) ([]service.Proxy, error) {
page := 1
pageSize := dataPageCap

View File

@@ -75,6 +75,45 @@ func TestProxyExportDataRespectsFilters(t *testing.T) {
require.Equal(t, "https", resp.Data.Proxies[0].Protocol)
}
func TestProxyExportDataWithSelectedIDs(t *testing.T) {
router, adminSvc := setupProxyDataRouter()
adminSvc.proxies = []service.Proxy{
{
ID: 1,
Name: "proxy-a",
Protocol: "http",
Host: "127.0.0.1",
Port: 8080,
Username: "user",
Password: "pass",
Status: service.StatusActive,
},
{
ID: 2,
Name: "proxy-b",
Protocol: "https",
Host: "10.0.0.2",
Port: 443,
Username: "u",
Password: "p",
Status: service.StatusDisabled,
},
}
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/api/v1/admin/proxies/data?ids=2", nil)
router.ServeHTTP(rec, req)
require.Equal(t, http.StatusOK, rec.Code)
var resp proxyDataResponse
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp))
require.Equal(t, 0, resp.Code)
require.Len(t, resp.Data.Proxies, 1)
require.Equal(t, "https", resp.Data.Proxies[0].Protocol)
require.Equal(t, "10.0.0.2", resp.Data.Proxies[0].Host)
}
func TestProxyImportDataReusesAndTriggersLatencyProbe(t *testing.T) {
router, adminSvc := setupProxyDataRouter()