diff --git a/go.mod b/go.mod index 098f6c8..49b021c 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module safesight-control -go 1.23.3 +go 1.25.0 require ( github.com/go-chi/chi/v5 v5.2.3 @@ -14,6 +14,7 @@ require ( github.com/ncruces/go-strftime v0.1.9 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.40.0 // indirect modernc.org/libc v1.55.3 // indirect modernc.org/mathutil v1.6.0 // indirect modernc.org/memory v1.8.0 // indirect diff --git a/go.sum b/go.sum index 5be4d0b..fa1e0f8 100644 --- a/go.sum +++ b/go.sum @@ -15,6 +15,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qq golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs= +golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY= modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U= modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= diff --git a/internal/web/ui.go b/internal/web/ui.go index 4696280..e2a7efd 100644 --- a/internal/web/ui.go +++ b/internal/web/ui.go @@ -21,11 +21,13 @@ import ( "strconv" "strings" "time" + "unicode/utf8" "safesight-control/internal/models" "safesight-control/internal/service" "safesight-control/internal/storage" "github.com/go-chi/chi/v5" + "golang.org/x/text/encoding/simplifiedchinese" ) type UI struct { @@ -3538,11 +3540,14 @@ func (u *UI) pageAssetVideoSources(w http.ResponseWriter, r *http.Request) { } } if data.AssetVideoSource == nil { - data.AssetVideoSource = &service.ConfigVideoSourceAsset{ - SourceType: "rtsp", - SourceTypeLabel: "RTSP", + if newMode { + data.AssetVideoSource = &service.ConfigVideoSourceAsset{ + SourceType: "rtsp", + SourceTypeLabel: "RTSP", + } + data.AssetVideoSourceEditing = true } - data.AssetVideoSourceEditing = true + // otherwise just leave nil → nothing selected, no editor shown } else { data.AssetVideoSourceEditing = newMode || editMode } @@ -3622,7 +3627,25 @@ func (u *UI) actionVideoSourceCSVImport(w http.ResponseWriter, r *http.Request) } defer file.Close() - reader := csv.NewReader(file) + // Read raw bytes for encoding detection + rawBytes, err := io.ReadAll(file) + if err != nil { + http.Redirect(w, r, "/assets/video-sources?error="+urlQueryEscape("读取文件失败: "+err.Error()), http.StatusFound) + return + } + // Strip UTF-8 BOM if present + rawBytes = bytes.TrimPrefix(rawBytes, []byte("\xef\xbb\xbf")) + // Try UTF-8 first; if invalid, try GBK + if !utf8.Valid(rawBytes) { + decoder := simplifiedchinese.GBK.NewDecoder() + decoded, err := decoder.Bytes(rawBytes) + if err != nil { + http.Redirect(w, r, "/assets/video-sources?error="+urlQueryEscape("文件编码不支持,请保存为 UTF-8 格式"), http.StatusFound) + return + } + rawBytes = decoded + } + reader := csv.NewReader(bytes.NewReader(rawBytes)) reader.LazyQuotes = true records, err := reader.ReadAll() if err != nil { diff --git a/internal/web/ui/templates/assets.html b/internal/web/ui/templates/assets.html index a1cba41..3b1d489 100644 --- a/internal/web/ui/templates/assets.html +++ b/internal/web/ui/templates/assets.html @@ -220,9 +220,14 @@ toggleIntegrationFields('{{.AssetIntegration.Type}}'); {{if .Config.Resolution}}{{.Config.Resolution}}{{else}}-{{end}} {{if .Config.FPS}}{{.Config.FPS}}{{else}}-{{end}} {{.RefCount}} + +
+ +
+ {{else}} -
还没有视频源
+
还没有视频源
{{end}}