修复 curve 接口的一些问题
This commit is contained in:
@@ -5,4 +5,8 @@ GIN_MODE=release
|
|||||||
|
|
||||||
# Production uses built-in RDS host when DATABASE_HOST is unset.
|
# Production uses built-in RDS host when DATABASE_HOST is unset.
|
||||||
# Password must be set via environment variable (never commit real password).
|
# Password must be set via environment variable (never commit real password).
|
||||||
|
# jdbc:mysql://database-1.chmuueamo72p.eu-central-1.rds.amazonaws.com:3306/audio?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=Asia/Shanghai
|
||||||
|
# young9#!UJsD219921031
|
||||||
|
# root
|
||||||
|
|
||||||
DATABASE_PASSWORD=your-production-password
|
DATABASE_PASSWORD=your-production-password
|
||||||
|
|||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
FROM golang:1.24-alpine AS builder
|
||||||
|
|
||||||
|
RUN apk add --no-cache git
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY go.mod go.sum ./
|
||||||
|
RUN go mod download
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /server ./cmd/server
|
||||||
|
|
||||||
|
FROM alpine:3.20
|
||||||
|
|
||||||
|
RUN apk add --no-cache ca-certificates tzdata \
|
||||||
|
&& cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
|
||||||
|
&& echo "Asia/Shanghai" > /etc/timezone
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY --from=builder /server .
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
CMD ["./server"]
|
||||||
+8
-4
@@ -69,10 +69,14 @@ func main() {
|
|||||||
// 启动时预热缓存
|
// 启动时预热缓存
|
||||||
warmUpCache(log, db, rdb)
|
warmUpCache(log, db, rdb)
|
||||||
|
|
||||||
// 启动定时刷入任务:每 5 分钟从 Redis 刷入数据库
|
// 启动定时刷入任务:每 5 分钟从 Redis 刷入数据库(仅 ENABLE_PERSIST_TASK=true 的容器运行)
|
||||||
deviceRepo := repository.NewDeviceRepository(db)
|
if cfg.EnablePersistTask {
|
||||||
devicePersistTask := task.NewDevicePersistTask(rdb, deviceRepo, log)
|
deviceRepo := repository.NewDeviceRepository(db)
|
||||||
devicePersistTask.Start(5 * time.Minute)
|
devicePersistTask := task.NewDevicePersistTask(rdb, deviceRepo, log)
|
||||||
|
devicePersistTask.Start(5 * time.Minute)
|
||||||
|
} else {
|
||||||
|
log.Info("device persist task disabled")
|
||||||
|
}
|
||||||
|
|
||||||
engine := router.New(log, db, searchClient, rdb, cfg.Equalize)
|
engine := router.New(log, db, searchClient, rdb, cfg.Equalize)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
services:
|
||||||
|
app:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: app-api
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "8084:8080"
|
||||||
|
environment:
|
||||||
|
- APP_ENV=production
|
||||||
|
- APP_HOST=0.0.0.0
|
||||||
|
- APP_PORT=8080
|
||||||
|
- DATABASE_PASSWORD=${DATABASE_PASSWORD}
|
||||||
|
- REDIS_PASSWORD=${REDIS_PASSWORD:-eafon123!}
|
||||||
|
- MEILISEARCH_API_KEY=${MEILISEARCH_API_KEY:-young9#!UJsD219921031}
|
||||||
|
- ENABLE_PERSIST_TASK=false
|
||||||
|
- MEASUREMENT_BASE_PATH=/app/measurements
|
||||||
|
- TARGET_BASE_PATH=/app/targets
|
||||||
|
volumes:
|
||||||
|
- /data/project/autoeq/measurements:/app/measurements:ro
|
||||||
|
- /data/project/autoeq/targets:/app/targets:ro
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://localhost:8080/api/v1/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 3
|
||||||
|
start_period: 10s
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
+16
-14
@@ -7,13 +7,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Env string
|
Env string
|
||||||
Host string
|
Host string
|
||||||
Port int
|
Port int
|
||||||
Database DatabaseConfig
|
Database DatabaseConfig
|
||||||
Meilisearch MeilisearchConfig
|
Meilisearch MeilisearchConfig
|
||||||
Redis RedisConfig
|
Redis RedisConfig
|
||||||
Equalize EqualizeConfig
|
Equalize EqualizeConfig
|
||||||
|
EnablePersistTask bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func Load() (*Config, error) {
|
func Load() (*Config, error) {
|
||||||
@@ -45,13 +46,14 @@ func Load() (*Config, error) {
|
|||||||
eq := loadEqualize(env)
|
eq := loadEqualize(env)
|
||||||
|
|
||||||
return &Config{
|
return &Config{
|
||||||
Env: env,
|
Env: env,
|
||||||
Host: getEnv("APP_HOST", "0.0.0.0"),
|
Host: getEnv("APP_HOST", "0.0.0.0"),
|
||||||
Port: port,
|
Port: port,
|
||||||
Database: db,
|
Database: db,
|
||||||
Meilisearch: ms,
|
Meilisearch: ms,
|
||||||
Redis: rd,
|
Redis: rd,
|
||||||
Equalize: eq,
|
Equalize: eq,
|
||||||
|
EnablePersistTask: getEnv("ENABLE_PERSIST_TASK", "false") == "true",
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-10
@@ -3,32 +3,32 @@ package config
|
|||||||
import "os"
|
import "os"
|
||||||
|
|
||||||
type EqualizeConfig struct {
|
type EqualizeConfig struct {
|
||||||
APIURL string
|
APIURL string
|
||||||
MeasurementBasePath string
|
MeasurementBasePath string
|
||||||
TargetBasePath string
|
TargetBasePath string
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadEqualize(env string) EqualizeConfig {
|
func loadEqualize(env string) EqualizeConfig {
|
||||||
if os.Getenv("EQ_API_URL") != "" {
|
if os.Getenv("EQ_API_URL") != "" {
|
||||||
return EqualizeConfig{
|
return EqualizeConfig{
|
||||||
APIURL: os.Getenv("EQ_API_URL"),
|
APIURL: os.Getenv("EQ_API_URL"),
|
||||||
MeasurementBasePath: getEnv("MEASUREMENT_BASE_PATH", ""),
|
MeasurementBasePath: getEnv("MEASUREMENT_BASE_PATH", "/app/measurements"),
|
||||||
TargetBasePath: getEnv("TARGET_BASE_PATH", ""),
|
TargetBasePath: getEnv("TARGET_BASE_PATH", "/app/targets"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch env {
|
switch env {
|
||||||
case "production":
|
case "production":
|
||||||
return EqualizeConfig{
|
return EqualizeConfig{
|
||||||
APIURL: "https://autoeq.app/equalize",
|
APIURL: "http://172.31.18.70:8000/equalize",
|
||||||
MeasurementBasePath: getEnv("MEASUREMENT_BASE_PATH", ""),
|
MeasurementBasePath: getEnv("MEASUREMENT_BASE_PATH", "/app/measurements"),
|
||||||
TargetBasePath: getEnv("TARGET_BASE_PATH", ""),
|
TargetBasePath: getEnv("TARGET_BASE_PATH", "/app/targets"),
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return EqualizeConfig{
|
return EqualizeConfig{
|
||||||
APIURL: "https://autoeq.app/equalize",
|
APIURL: "https://autoeq.app/equalize",
|
||||||
MeasurementBasePath: getEnv("MEASUREMENT_BASE_PATH", ""),
|
MeasurementBasePath: getEnv("MEASUREMENT_BASE_PATH", "/app/measurements"),
|
||||||
TargetBasePath: getEnv("TARGET_BASE_PATH", ""),
|
TargetBasePath: getEnv("TARGET_BASE_PATH", "/app/targets"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
_ "github.com/go-sql-driver/mysql"
|
|
||||||
"github.com/go-sql-driver/mysql"
|
"github.com/go-sql-driver/mysql"
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
"github.com/luxsin/app-api/internal/config"
|
"github.com/luxsin/app-api/internal/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -19,9 +19,10 @@ func Open(cfg config.DatabaseConfig) (*sql.DB, error) {
|
|||||||
Addr: fmt.Sprintf("%s:%d", cfg.Host, cfg.Port),
|
Addr: fmt.Sprintf("%s:%d", cfg.Host, cfg.Port),
|
||||||
DBName: cfg.Name,
|
DBName: cfg.Name,
|
||||||
Params: map[string]string{
|
Params: map[string]string{
|
||||||
"charset": "utf8mb4",
|
"charset": "utf8mb4",
|
||||||
"parseTime": "True",
|
"parseTime": "True",
|
||||||
"loc": "Local",
|
"loc": "Local",
|
||||||
|
"allowNativePasswords": "true",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+88
-44
@@ -8,6 +8,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -18,6 +19,7 @@ import (
|
|||||||
"github.com/luxsin/app-api/internal/config"
|
"github.com/luxsin/app-api/internal/config"
|
||||||
"github.com/luxsin/app-api/internal/repository"
|
"github.com/luxsin/app-api/internal/repository"
|
||||||
"github.com/luxsin/app-api/internal/response"
|
"github.com/luxsin/app-api/internal/response"
|
||||||
|
"github.com/luxsin/app-api/pkg/encode"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -33,12 +35,12 @@ func NewCurveHandler(repo *repository.CurveRepository, curveCache *cache.CurveCa
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetCurve 获取目标曲线
|
// GetCurve 获取目标曲线
|
||||||
// GET /audio/getCurve?brand=xxx&name=xxx&target=xxx&includeRaw=false
|
// GET /audio/getCurve?brand=xxx&name=xxx&target=xxx&base64Resp=true
|
||||||
func (h *CurveHandler) GetCurve(c *gin.Context) {
|
func (h *CurveHandler) GetCurve(c *gin.Context) {
|
||||||
brand := strings.TrimSpace(c.Query("brand"))
|
brand := strings.TrimSpace(queryParam(c, "brand"))
|
||||||
name := strings.TrimSpace(c.Query("name"))
|
name := strings.TrimSpace(queryParam(c, "name"))
|
||||||
target := strings.TrimSpace(c.Query("target"))
|
target := strings.TrimSpace(queryParam(c, "target"))
|
||||||
includeRaw := c.Query("includeRaw") == "true" || c.Query("includeRaw") == "1"
|
base64Resp := encode.ParseBase64Param(c)
|
||||||
|
|
||||||
if brand == "" || name == "" || target == "" {
|
if brand == "" || name == "" || target == "" {
|
||||||
response.BadRequest(c, "brand、name和target参数不能为空")
|
response.BadRequest(c, "brand、name和target参数不能为空")
|
||||||
@@ -59,22 +61,33 @@ func (h *CurveHandler) GetCurve(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析 JSON 结果
|
// 解析 JSON 结果,只提取 parametric_eq
|
||||||
var resp map[string]any
|
var resp map[string]any
|
||||||
if err := json.Unmarshal([]byte(result), &resp); err != nil {
|
if err := json.Unmarshal([]byte(result), &resp); err != nil {
|
||||||
response.InternalError(c, "解析曲线数据失败")
|
response.InternalError(c, "解析曲线数据失败")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果 includeRaw 为 false 且 code != 200,移除 fr 字段
|
parametricEq, _ := resp["parametric_eq"]
|
||||||
if !includeRaw {
|
|
||||||
codeVal, _ := resp["code"]
|
resultData := gin.H{
|
||||||
if code, ok := codeVal.(float64); ok && code != 200 {
|
"code": 200,
|
||||||
delete(resp, "fr")
|
"msg": "操作成功",
|
||||||
}
|
"parametric_eq": parametricEq,
|
||||||
}
|
}
|
||||||
|
|
||||||
response.OK(c, resp)
|
if base64Resp {
|
||||||
|
encoded, err := encode.EncodeJSON(resultData)
|
||||||
|
if err != nil {
|
||||||
|
h.log.Error("encode response failed", zap.Error(err))
|
||||||
|
response.InternalError(c, "编码响应失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.String(http.StatusOK, encoded)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, resultData)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getCurvePoint 获取曲线数据:先查缓存,缓存不存在则请求 EQ 接口并缓存结果
|
// getCurvePoint 获取曲线数据:先查缓存,缓存不存在则请求 EQ 接口并缓存结果
|
||||||
@@ -92,6 +105,7 @@ func (h *CurveHandler) getCurvePoint(ctx context.Context, brand, name, target st
|
|||||||
|
|
||||||
// 获取了锁,缓存仍然为空,需要请求 EQ 接口
|
// 获取了锁,缓存仍然为空,需要请求 EQ 接口
|
||||||
if acquired {
|
if acquired {
|
||||||
|
h.log.Info("curve cache miss, requesting eq api", zap.String("brand", brand), zap.String("name", name), zap.String("target", target))
|
||||||
result, eqErr := h.getCurvePointFromPEQ(ctx, brand, name, target)
|
result, eqErr := h.getCurvePointFromPEQ(ctx, brand, name, target)
|
||||||
if eqErr != nil {
|
if eqErr != nil {
|
||||||
// 释放锁
|
// 释放锁
|
||||||
@@ -193,35 +207,35 @@ func (h *CurveHandler) reqEqualize(headPhone string, measurement map[string]any,
|
|||||||
q := floatVal(bassBoost, "q", 0.7)
|
q := floatVal(bassBoost, "q", 0.7)
|
||||||
|
|
||||||
reqBody := map[string]any{
|
reqBody := map[string]any{
|
||||||
"target": target,
|
"target": target,
|
||||||
"sound_signature": nil,
|
"sound_signature": nil,
|
||||||
"sound_signature_smoothing_window_size": 1,
|
"sound_signature_smoothing_window_size": 1,
|
||||||
"bass_boost_gain": gain,
|
"bass_boost_gain": gain,
|
||||||
"bass_boost_fc": fc,
|
"bass_boost_fc": fc,
|
||||||
"bass_boost_q": q,
|
"bass_boost_q": q,
|
||||||
"treble_boost_gain": 0,
|
"treble_boost_gain": 0,
|
||||||
"treble_boost_fc": 10000,
|
"treble_boost_fc": 10000,
|
||||||
"treble_boost_q": 0.7,
|
"treble_boost_q": 0.7,
|
||||||
"tilt": 0,
|
"tilt": 0,
|
||||||
"fs": 48000,
|
"fs": 48000,
|
||||||
"bit_depth": 16,
|
"bit_depth": 16,
|
||||||
"phase": "minimum",
|
"phase": "minimum",
|
||||||
"f_res": 16,
|
"f_res": 16,
|
||||||
"preamp": 0,
|
"preamp": 0,
|
||||||
"max_gain": 12,
|
"max_gain": 12,
|
||||||
"max_slope": 18,
|
"max_slope": 18,
|
||||||
"window_size": 0.08,
|
"window_size": 0.08,
|
||||||
"treble_window_size": 2,
|
"treble_window_size": 2,
|
||||||
"treble_f_lower": 6000,
|
"treble_f_lower": 6000,
|
||||||
"treble_f_upper": 8000,
|
"treble_f_upper": 8000,
|
||||||
"treble_gain_k": 1,
|
"treble_gain_k": 1,
|
||||||
"graphic_eq": false,
|
"graphic_eq": false,
|
||||||
"parametric_eq": true,
|
"parametric_eq": true,
|
||||||
"fixed_band_eq": false,
|
"fixed_band_eq": false,
|
||||||
"convolution_eq": false,
|
"convolution_eq": false,
|
||||||
"source": source,
|
"source": source,
|
||||||
"rig": rig,
|
"rig": rig,
|
||||||
"parametric_eq_config": "MINIDSP_IL_DSP",
|
"parametric_eq_config": "MINIDSP_IL_DSP",
|
||||||
"response": map[string]any{
|
"response": map[string]any{
|
||||||
"fr_f_step": 1.02,
|
"fr_f_step": 1.02,
|
||||||
"base64fp16": false,
|
"base64fp16": false,
|
||||||
@@ -247,9 +261,17 @@ func (h *CurveHandler) reqEqualize(headPhone string, measurement map[string]any,
|
|||||||
}
|
}
|
||||||
httpReq.Header.Set("Content-Type", "application/json")
|
httpReq.Header.Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
client := &http.Client{Timeout: 10 * time.Second}
|
client := &http.Client{Timeout: 10 * time.Second}
|
||||||
httpResp, err := client.Do(httpReq)
|
httpResp, err := client.Do(httpReq)
|
||||||
|
elapsed := time.Since(start)
|
||||||
|
h.log.Info("eq api response",
|
||||||
|
zap.String("headPhone", headPhone),
|
||||||
|
zap.Duration("latency", elapsed),
|
||||||
|
zap.String("url", h.cfg.APIURL),
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
h.log.Error("eq api request failed", zap.Duration("latency", elapsed), zap.Error(err))
|
||||||
return "", fmt.Errorf("call eq api: %w", err)
|
return "", fmt.Errorf("call eq api: %w", err)
|
||||||
}
|
}
|
||||||
defer httpResp.Body.Close()
|
defer httpResp.Body.Close()
|
||||||
@@ -272,8 +294,8 @@ func (h *CurveHandler) reqEqualize(headPhone string, measurement map[string]any,
|
|||||||
parametricEq, _ := eqResp["parametric_eq"].(map[string]any)
|
parametricEq, _ := eqResp["parametric_eq"].(map[string]any)
|
||||||
if parametricEq == nil {
|
if parametricEq == nil {
|
||||||
result := map[string]any{
|
result := map[string]any{
|
||||||
"code": 200,
|
"code": 200,
|
||||||
"msg": "req param error",
|
"msg": "req param error",
|
||||||
"param": reqBody,
|
"param": reqBody,
|
||||||
}
|
}
|
||||||
resultJSON, _ := json.Marshal(result)
|
resultJSON, _ := json.Marshal(result)
|
||||||
@@ -389,4 +411,26 @@ func intVal(m map[string]any, key string, defaultVal int) int {
|
|||||||
default:
|
default:
|
||||||
return defaultVal
|
return defaultVal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// queryParam 从 URL 原始 query 中获取参数,保留 + 为字面量而非空格
|
||||||
|
func queryParam(c *gin.Context, key string) string {
|
||||||
|
vals, ok := c.Request.URL.Query()[key]
|
||||||
|
if !ok || len(vals) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
// c.Query() 会把 + 解码为空格,这里从原始 query 手动解码,+ 保留为 +
|
||||||
|
if strings.Contains(vals[0], " ") {
|
||||||
|
rawQuery := c.Request.URL.RawQuery
|
||||||
|
for _, pair := range strings.Split(rawQuery, "&") {
|
||||||
|
kv := strings.SplitN(pair, "=", 2)
|
||||||
|
if len(kv) == 2 && kv[0] == key {
|
||||||
|
decoded, err := url.PathUnescape(strings.ReplaceAll(kv[1], "+", "%2B"))
|
||||||
|
if err == nil {
|
||||||
|
return decoded
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vals[0]
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,6 +9,12 @@ import (
|
|||||||
|
|
||||||
func Logger(log *zap.Logger) gin.HandlerFunc {
|
func Logger(log *zap.Logger) gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
|
// 跳过 health 检查的日志
|
||||||
|
if c.Request.URL.Path == "/api/v1/health" {
|
||||||
|
c.Next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
path := c.Request.URL.Path
|
path := c.Request.URL.Path
|
||||||
query := c.Request.URL.RawQuery
|
query := c.Request.URL.RawQuery
|
||||||
|
|||||||
@@ -9,5 +9,5 @@ type Target struct {
|
|||||||
ReadCSV BoolInt `json:"readCsv"`
|
ReadCSV BoolInt `json:"readCsv"`
|
||||||
File *string `json:"file,omitempty"`
|
File *string `json:"file,omitempty"`
|
||||||
BassBoost *string `json:"bassBoost,omitempty"`
|
BassBoost *string `json:"bassBoost,omitempty"`
|
||||||
CreateAt time.Time `json:"createAt"`
|
AddTime time.Time `json:"addTime"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ func NewCurveRepository(db *sql.DB) *CurveRepository {
|
|||||||
|
|
||||||
// GetModelByBrandAndName 按 brand_name + name 查询 Model(唯一索引)
|
// GetModelByBrandAndName 按 brand_name + name 查询 Model(唯一索引)
|
||||||
func (r *CurveRepository) GetModelByBrandAndName(ctx context.Context, brandName, name string) (*model.Model, error) {
|
func (r *CurveRepository) GetModelByBrandAndName(ctx context.Context, brandName, name string) (*model.Model, error) {
|
||||||
const query = `SELECT id, brand_name, name, form, rig, source, eq_key, create_at FROM model WHERE brand_name = ? AND name = ?`
|
const query = `SELECT id, brand_name, name, form, rig, source, eq_key, create_at FROM model WHERE BINARY brand_name = ? AND BINARY name = ?`
|
||||||
|
|
||||||
var m model.Model
|
var m model.Model
|
||||||
var form, rig, source, eqKey sql.NullString
|
var form, rig, source, eqKey sql.NullString
|
||||||
@@ -43,13 +43,13 @@ func (r *CurveRepository) GetModelByBrandAndName(ctx context.Context, brandName,
|
|||||||
|
|
||||||
// GetTargetByLabel 按 label 查询 Target
|
// GetTargetByLabel 按 label 查询 Target
|
||||||
func (r *CurveRepository) GetTargetByLabel(ctx context.Context, label string) (*model.Target, error) {
|
func (r *CurveRepository) GetTargetByLabel(ctx context.Context, label string) (*model.Target, error) {
|
||||||
const query = `SELECT id, label, read_csv, file, bass_boost, create_at FROM target WHERE label = ?`
|
const query = `SELECT id, label, read_csv, file, bassBoost, addtime FROM target WHERE BINARY label = ?`
|
||||||
|
|
||||||
var t model.Target
|
var t model.Target
|
||||||
var file, bassBoost sql.NullString
|
var file, bassBoost sql.NullString
|
||||||
|
|
||||||
err := r.db.QueryRowContext(ctx, query, label).Scan(
|
err := r.db.QueryRowContext(ctx, query, label).Scan(
|
||||||
&t.ID, &t.Label, &t.ReadCSV, &file, &bassBoost, &t.CreateAt,
|
&t.ID, &t.Label, &t.ReadCSV, &file, &bassBoost, &t.AddTime,
|
||||||
)
|
)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@@ -62,4 +62,4 @@ func (r *CurveRepository) GetTargetByLabel(ctx context.Context, label string) (*
|
|||||||
t.BassBoost = nullStringPtr(bassBoost)
|
t.BassBoost = nullStringPtr(bassBoost)
|
||||||
|
|
||||||
return &t, nil
|
return &t, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user