- go.mod module path matches repo zkcoi/Meshray-Manager (case-distinct from zkcoi/Meshray/core)
- rewrite internal imports meshray/{internal,web,pkg} -> Meshray-Manager/... (core refs kept)
- sync README.md / install.sh repo URLs; add CHANGELOG entry
146 lines
3.5 KiB
Go
146 lines
3.5 KiB
Go
package handler
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"time"
|
|
|
|
"git.zkcoi.com/zkcoi/Meshray-Manager/internal/model"
|
|
"github.com/gin-gonic/gin"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// DDNSStatsHandler DDNS 统计处理器
|
|
type DDNSStatsHandler struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
// NewDDNSStatsHandler 创建 DDNS 统计处理器
|
|
func NewDDNSStatsHandler(db *gorm.DB) *DDNSStatsHandler {
|
|
return &DDNSStatsHandler{
|
|
db: db,
|
|
}
|
|
}
|
|
|
|
// DDNSServiceInfo DDNS 服务信息(返回给前端)
|
|
type DDNSServiceInfo struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
FullDomain string `json:"full_domain"` // 完整域名:subdomain.domain
|
|
CurrentIP string `json:"current_ip"` // 当前 IP
|
|
RecordType string `json:"record_type"` // A/AAAA/TXT/CNAME
|
|
Enabled bool `json:"enabled"` // 是否启用
|
|
Status string `json:"status"` // active/disabled
|
|
LastUpdated string `json:"last_updated"` // 最后更新时间
|
|
}
|
|
|
|
// GetDDNSStats 获取 DDNS 统计数据
|
|
// @Summary 获取 DDNS 服务统计
|
|
// @Tags DDNS
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Success 200 {object} map[string]interface{}
|
|
// @Router /api/v1/services/ddns/stats [get]
|
|
func (h *DDNSStatsHandler) GetDDNSStats(c *gin.Context) {
|
|
// 查询所有 DDNS 全功能模式服务
|
|
var services []model.Service
|
|
if err := h.db.Where("type = ? AND config_mode = ?", "DDNS", "fullservice").Find(&services).Error; err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
"code": 500,
|
|
"message": "查询 DDNS 服务失败:" + err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
// 统计数据
|
|
total := len(services)
|
|
active := 0
|
|
|
|
// 构建服务列表
|
|
serviceList := make([]DDNSServiceInfo, 0, len(services))
|
|
for _, svc := range services {
|
|
// 判断是否活跃
|
|
status := "disabled"
|
|
if svc.Enabled {
|
|
status = "active"
|
|
active++
|
|
}
|
|
|
|
// 构建完整域名
|
|
fullDomain := ""
|
|
rootDomain := h.getDDNSDomain(svc.DDNSConfigID)
|
|
switch svc.RecordType {
|
|
case "A", "AAAA":
|
|
if svc.Subdomain != "" && rootDomain != "" {
|
|
fullDomain = svc.Subdomain + "." + rootDomain
|
|
}
|
|
case "TXT":
|
|
if svc.TXTRecordName != "" && rootDomain != "" {
|
|
fullDomain = svc.TXTRecordName + "." + rootDomain
|
|
}
|
|
case "CNAME":
|
|
if svc.Subdomain != "" && rootDomain != "" {
|
|
fullDomain = svc.Subdomain + "." + rootDomain
|
|
}
|
|
}
|
|
|
|
// 当前 IP
|
|
currentIP := svc.TargetIP
|
|
if svc.RecordType == "TXT" {
|
|
currentIP = "-"
|
|
}
|
|
|
|
// 格式化时间
|
|
lastUpdated := ""
|
|
if !svc.UpdatedAt.IsZero() {
|
|
lastUpdated = svc.UpdatedAt.Format(time.RFC3339)
|
|
}
|
|
|
|
serviceList = append(serviceList, DDNSServiceInfo{
|
|
ID: svc.ID,
|
|
Name: svc.Name,
|
|
FullDomain: fullDomain,
|
|
CurrentIP: currentIP,
|
|
RecordType: svc.RecordType,
|
|
Enabled: svc.Enabled,
|
|
Status: status,
|
|
LastUpdated: lastUpdated,
|
|
})
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"code": 0,
|
|
"data": gin.H{
|
|
"total": total,
|
|
"active": active,
|
|
"services": serviceList,
|
|
},
|
|
"message": "获取成功",
|
|
})
|
|
}
|
|
|
|
// getDDNSDomain 获取 DDNS 配置中的根域名(辅助方法)
|
|
func (h *DDNSStatsHandler) getDDNSDomain(ddnsConfigID string) string {
|
|
if ddnsConfigID == "" {
|
|
return ""
|
|
}
|
|
|
|
// 从 ExternalService 表查询 DDNS 配置
|
|
var extService model.ExternalService
|
|
if err := h.db.Where("id = ?", ddnsConfigID).First(&extService).Error; err != nil {
|
|
return ""
|
|
}
|
|
|
|
// 解析 Config JSON 获取 root_domain
|
|
var config map[string]interface{}
|
|
if err := json.Unmarshal([]byte(extService.Config), &config); err != nil {
|
|
return ""
|
|
}
|
|
|
|
if rootDomain, ok := config["root_domain"].(string); ok {
|
|
return rootDomain
|
|
}
|
|
|
|
return ""
|
|
}
|