mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-08 00:26:37 +08:00
feat(web): add zone-based website management
以稳定 Zone ID 替换旧托管域名详情页:列表展示根域与域名计数,详情提供 概览/域名/路由/证书/设置 Tabs,并补齐 ZoneService 与 vitest 行为测试。 Zone 列表 API 返回 domain_count;同步 Swagger 与重构计划进度。
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Rain-kl/Wavelet/internal/db"
|
||||
"github.com/Rain-kl/Wavelet/internal/model"
|
||||
@@ -34,6 +35,16 @@ type Overview struct {
|
||||
Domains []model.ZoneDomain `json:"domains"`
|
||||
}
|
||||
|
||||
// ListItem is a Zone list row with denormalized domain count for the UI.
|
||||
type ListItem struct {
|
||||
ID uint `json:"id"`
|
||||
Domain string `json:"domain"`
|
||||
Remark string `json:"remark"`
|
||||
DomainCount int64 `json:"domain_count"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
func zoneRoot(domain string) (string, error) {
|
||||
return publicsuffix.EffectiveTLDPlusOne(strings.ToLower(strings.TrimSpace(domain)))
|
||||
}
|
||||
@@ -99,11 +110,41 @@ func Update(ctx context.Context, id uint, input Input) (*model.Zone, error) {
|
||||
return &zone, nil
|
||||
}
|
||||
|
||||
// List returns all Zones in stable domain order.
|
||||
func List(ctx context.Context) ([]model.Zone, error) {
|
||||
// List returns all Zones in stable domain order, with domain counts for list cards.
|
||||
func List(ctx context.Context) ([]ListItem, error) {
|
||||
var zones []model.Zone
|
||||
err := db.DB(ctx).Order("domain asc").Find(&zones).Error
|
||||
return zones, err
|
||||
if err := db.DB(ctx).Order("domain asc").Find(&zones).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
type countRow struct {
|
||||
ZoneID uint `gorm:"column:zone_id"`
|
||||
Count int64 `gorm:"column:count"`
|
||||
}
|
||||
var rows []countRow
|
||||
if err := db.DB(ctx).Model(&model.ZoneDomain{}).
|
||||
Select("zone_id, count(*) as count").
|
||||
Group("zone_id").
|
||||
Scan(&rows).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
counts := make(map[uint]int64, len(rows))
|
||||
for _, row := range rows {
|
||||
counts[row.ZoneID] = row.Count
|
||||
}
|
||||
|
||||
items := make([]ListItem, 0, len(zones))
|
||||
for _, zone := range zones {
|
||||
items = append(items, ListItem{
|
||||
ID: zone.ID,
|
||||
Domain: zone.Domain,
|
||||
Remark: zone.Remark,
|
||||
DomainCount: counts[zone.ID],
|
||||
CreatedAt: zone.CreatedAt,
|
||||
UpdatedAt: zone.UpdatedAt,
|
||||
})
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
// GetOverview returns a Zone and its domains.
|
||||
|
||||
@@ -33,7 +33,7 @@ func abort(c *gin.Context, err error, missing string) bool {
|
||||
// @Tags openflare-zone
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} response.Any{data=[]model.Zone}
|
||||
// @Success 200 {object} response.Any{data=[]zone.ListItem}
|
||||
// @Router /api/v1/d/zones [get]
|
||||
func ListHandler(c *gin.Context) {
|
||||
items, err := List(c.Request.Context())
|
||||
|
||||
Reference in New Issue
Block a user