新增了针对 mac 地址屏蔽webui 导航栏的接口

This commit is contained in:
eafonyang
2026-10-10 17:11:54 +08:00
parent 0aad0f9c1d
commit 4711c262c9
9 changed files with 298 additions and 1 deletions
+69
View File
@@ -0,0 +1,69 @@
package handler
import (
"net/http"
"strings"
"github.com/gin-gonic/gin"
"github.com/luxsin/app-api/internal/repository"
"github.com/luxsin/app-api/internal/response"
"go.uber.org/zap"
)
type NavConfigHandler struct {
repo *repository.NavConfigRepository
log *zap.Logger
}
func NewNavConfigHandler(repo *repository.NavConfigRepository, log *zap.Logger) *NavConfigHandler {
return &NavConfigHandler{repo: repo, log: log}
}
// GetNavConfig 获取导航栏隐藏配置
//
// @Summary 获取导航栏隐藏配置
// @Description 根据设备 MAC 查询需要隐藏的导航入口(nav key: community|hpEq|home|effects|myAi)。未命中返回空数组,前端应默认全部显示。
// @Tags NavConfig
// @Produce json
// @Param mac query string true "设备 MAC 地址"
// @Success 200 {object} object "成功返回 hidden 列表"
// @Failure 400 {object} object
// @Failure 500 {object} object
// @Router /audio/getNavConfig [get]
func (h *NavConfigHandler) GetNavConfig(c *gin.Context) {
mac := strings.TrimSpace(c.Query("mac"))
if mac == "" {
response.BadRequest(c, "mac参数不能为空")
return
}
ctx := c.Request.Context()
cfg, err := h.repo.FindByMac(ctx, mac)
if err != nil {
h.log.Error("query nav config failed", zap.String("mac", mac), zap.Error(err))
response.InternalError(c, "查询导航配置失败")
return
}
hidden := make([]string, 0)
if cfg != nil {
for _, key := range strings.Split(cfg.HiddenKeys, ",") {
if k := strings.TrimSpace(key); k != "" {
hidden = append(hidden, k)
}
}
if len(hidden) > 0 {
h.log.Info("mac命中导航隐藏配置",
zap.String("mac", repository.NormalizeMac(mac)),
zap.Strings("hidden", hidden),
)
}
}
c.JSON(http.StatusOK, gin.H{
"code": 200,
"msg": "操作成功",
"data": gin.H{"hidden": hidden},
})
}
+13
View File
@@ -0,0 +1,13 @@
package model
import "time"
// NavHiddenConfig 描述某个 MAC 命中后要隐藏的导航入口。
// HiddenKeys 为逗号分隔的 nav key(community|hpEq|home|effects|myAi)。
type NavHiddenConfig struct {
ID int
Mac string
HiddenKeys string
Model *string
CreateAt time.Time
}
+66
View File
@@ -0,0 +1,66 @@
package repository
import (
"context"
"database/sql"
"fmt"
"strings"
"github.com/luxsin/app-api/internal/model"
)
type NavConfigRepository struct {
db *sql.DB
}
func NewNavConfigRepository(db *sql.DB) *NavConfigRepository {
return &NavConfigRepository{db: db}
}
// NormalizeMac 将各种格式的 MAC 统一为大写冒号分隔格式(如 40:D9:5A:D8:06:9C)。
// 兼容设备可能上报的小写、无分隔符(40d95ad8069c)、或短横线分隔(40-d9-5a-...)等形式。
// 无法识别为 12 位十六进制时,返回去除首尾空白并大写后的原值,保证匹配行为可预期。
func NormalizeMac(raw string) string {
trimmed := strings.TrimSpace(raw)
if trimmed == "" {
return ""
}
hexOnly := strings.ToUpper(strings.NewReplacer(":", "", "-", "", ".", "", " ", "").Replace(trimmed))
if len(hexOnly) != 12 {
return strings.ToUpper(trimmed)
}
for _, c := range hexOnly {
if !((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
return strings.ToUpper(trimmed)
}
}
parts := make([]string, 0, 6)
for i := 0; i < 12; i += 2 {
parts = append(parts, hexOnly[i:i+2])
}
return strings.Join(parts, ":")
}
// FindByMac 按归一化后的 MAC 查询隐藏配置,未命中返回 (nil, nil)。
func (r *NavConfigRepository) FindByMac(ctx context.Context, mac string) (*model.NavHiddenConfig, error) {
const query = `SELECT id, mac, hidden_keys, model, create_at FROM nav_hidden_config WHERE mac = ? LIMIT 1`
normalized := NormalizeMac(mac)
if normalized == "" {
return nil, nil
}
var cfg model.NavHiddenConfig
var mdl sql.NullString
err := r.db.QueryRowContext(ctx, query, normalized).Scan(&cfg.ID, &cfg.Mac, &cfg.HiddenKeys, &mdl, &cfg.CreateAt)
if err == sql.ErrNoRows {
return nil, nil
}
if err != nil {
return nil, fmt.Errorf("query nav_hidden_config: %w", err)
}
if mdl.Valid {
cfg.Model = &mdl.String
}
return &cfg, nil
}
+3
View File
@@ -36,6 +36,7 @@ func New(log *zap.Logger, db *sql.DB, searchClient *search.Client, rdb *redis.Cl
modelRepo := repository.NewModelRepository(db, modelCache)
otaRepo := repository.NewOTARepository(db)
curveRepo := repository.NewCurveRepository(db)
navConfigRepo := repository.NewNavConfigRepository(db)
shareCodeCache := cache.NewShareCodeCache(rdb, shareCodeTTL)
@@ -50,6 +51,7 @@ func New(log *zap.Logger, db *sql.DB, searchClient *search.Client, rdb *redis.Cl
curve := handler.NewCurveHandler(curveRepo, curveCache, eqCfg, s3, log)
modelCSV := handler.NewModelCSVHandler(s3, log)
shareCode := handler.NewShareCodeHandler(shareCodeCache, log, shareCodeMaxPerMac)
navConfig := handler.NewNavConfigHandler(navConfigRepo, log)
v1 := r.Group("/api/v1")
{
@@ -78,6 +80,7 @@ func New(log *zap.Logger, db *sql.DB, searchClient *search.Client, rdb *redis.Cl
audio.GET("/shareQuery", shareCode.QueryShareCode)
audio.GET("/shareAccept", shareCode.ImportShareCode)
audio.GET("/shareDelete", shareCode.DeleteShareCode)
audio.GET("/getNavConfig", navConfig.GetNavConfig)
}
return r