refactor: video_sources使用整数ID主键,名字可自由修改
This commit is contained in:
parent
a4e0d1316f
commit
c817b42ff7
@ -108,6 +108,7 @@ type AlarmServiceConfig struct {
|
||||
}
|
||||
|
||||
type ConfigVideoSourceAsset struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
SourceType string `json:"source_type"`
|
||||
@ -824,7 +825,7 @@ func (s *ConfigPreviewService) GetVideoSource(name string) (*ConfigVideoSourceAs
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func (s *ConfigPreviewService) SaveVideoSourceAsset(asset ConfigVideoSourceAsset) error {
|
||||
func (s *ConfigPreviewService) SaveVideoSourceAsset(asset ConfigVideoSourceAsset, originalName string) error {
|
||||
if s == nil || s.assets == nil {
|
||||
return fmt.Errorf("基础配置仓库未初始化")
|
||||
}
|
||||
@ -836,8 +837,7 @@ func (s *ConfigPreviewService) SaveVideoSourceAsset(asset ConfigVideoSourceAsset
|
||||
if sourceType == "" {
|
||||
return fmt.Errorf("视频源类型不能为空")
|
||||
}
|
||||
urlValue := strings.TrimSpace(asset.Config.URL)
|
||||
if urlValue == "" {
|
||||
if strings.TrimSpace(asset.Config.URL) == "" {
|
||||
return fmt.Errorf("视频源地址不能为空")
|
||||
}
|
||||
raw := map[string]any{
|
||||
@ -860,7 +860,22 @@ func (s *ConfigPreviewService) SaveVideoSourceAsset(asset ConfigVideoSourceAsset
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.assets.SaveVideoSource(name, sourceType, strings.TrimSpace(asset.Area), strings.TrimSpace(asset.Description), string(body))
|
||||
if err := s.assets.SaveVideoSource(asset.ID, name, sourceType, strings.TrimSpace(asset.Area), strings.TrimSpace(asset.Description), string(body)); err != nil {
|
||||
return err
|
||||
}
|
||||
// If renaming, update recognition units
|
||||
originalName = strings.TrimSpace(originalName)
|
||||
if originalName != "" && originalName != name {
|
||||
units, _ := s.ListRecognitionUnits()
|
||||
for _, u := range units {
|
||||
if u.VideoSourceRef == originalName {
|
||||
u.VideoSourceRef = name
|
||||
ref := recognitionUnitRef(u.SceneTemplateName, u.Name)
|
||||
s.SaveRecognitionUnit(u, ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ConfigPreviewService) RenameVideoSource(oldName, newName string) error {
|
||||
@ -1708,6 +1723,7 @@ func videoSourceAssetFromRecord(record storage.VideoSourceRecord) (*ConfigVideoS
|
||||
sourceMap = configMap
|
||||
}
|
||||
item := &ConfigVideoSourceAsset{
|
||||
ID: record.ID,
|
||||
Name: firstString(raw["name"], record.Name),
|
||||
Path: repoAssetPath("video_sources", record.Name),
|
||||
SourceType: firstString(record.SourceType, stringValue(raw["source_type"])),
|
||||
|
||||
@ -29,6 +29,7 @@ type IntegrationServiceRecord struct {
|
||||
}
|
||||
|
||||
type VideoSourceRecord struct {
|
||||
ID int
|
||||
Name string
|
||||
SourceType string
|
||||
Area string
|
||||
@ -113,21 +114,23 @@ ON CONFLICT(name) DO UPDATE SET
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *AssetsRepo) SaveVideoSource(name string, sourceType string, area string, description string, bodyJSON string) error {
|
||||
func (r *AssetsRepo) SaveVideoSource(id int, name string, sourceType string, area string, description string, bodyJSON string) error {
|
||||
if r == nil || r.db == nil {
|
||||
return nil
|
||||
}
|
||||
now := time.Now().Format(time.RFC3339)
|
||||
if id > 0 {
|
||||
// Update existing by ID
|
||||
_, err := r.db.Exec(`
|
||||
UPDATE video_sources SET name=?, source_type=?, area=?, description=?, body_json=?, updated_at=?
|
||||
WHERE id=?`, name, sourceType, area, description, bodyJSON, now, id)
|
||||
return err
|
||||
}
|
||||
// Insert new
|
||||
_, err := r.db.Exec(`
|
||||
INSERT INTO video_sources(name, source_type, area, description, body_json, created_at, updated_at)
|
||||
VALUES(?, ?, ?, ?, ?, COALESCE((SELECT created_at FROM video_sources WHERE name = ?), ?), ?)
|
||||
ON CONFLICT(name) DO UPDATE SET
|
||||
source_type=excluded.source_type,
|
||||
area=excluded.area,
|
||||
description=excluded.description,
|
||||
body_json=excluded.body_json,
|
||||
updated_at=excluded.updated_at
|
||||
`, name, sourceType, area, description, bodyJSON, name, now, now)
|
||||
VALUES(?, ?, ?, ?, ?, ?, ?)
|
||||
`, name, sourceType, area, description, bodyJSON, now, now)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -211,7 +214,7 @@ func (r *AssetsRepo) ListVideoSources() ([]VideoSourceRecord, error) {
|
||||
return nil, nil
|
||||
}
|
||||
rows, err := r.db.Query(`
|
||||
SELECT name, source_type, area, description, body_json, created_at, updated_at
|
||||
SELECT id, name, source_type, area, description, body_json, created_at, updated_at
|
||||
FROM video_sources
|
||||
ORDER BY updated_at DESC, name ASC
|
||||
`)
|
||||
@ -223,7 +226,7 @@ ORDER BY updated_at DESC, name ASC
|
||||
var out []VideoSourceRecord
|
||||
for rows.Next() {
|
||||
var item VideoSourceRecord
|
||||
if err := rows.Scan(&item.Name, &item.SourceType, &item.Area, &item.Description, &item.BodyJSON, &item.CreatedAt, &item.UpdatedAt); err != nil {
|
||||
if err := rows.Scan(&item.ID, &item.Name, &item.SourceType, &item.Area, &item.Description, &item.BodyJSON, &item.CreatedAt, &item.UpdatedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, item)
|
||||
@ -317,10 +320,10 @@ func (r *AssetsRepo) GetVideoSource(name string) (*VideoSourceRecord, error) {
|
||||
}
|
||||
var item VideoSourceRecord
|
||||
err := r.db.QueryRow(`
|
||||
SELECT name, source_type, area, description, body_json, created_at, updated_at
|
||||
SELECT id, name, source_type, area, description, body_json, created_at, updated_at
|
||||
FROM video_sources
|
||||
WHERE name = ?
|
||||
`, name).Scan(&item.Name, &item.SourceType, &item.Area, &item.Description, &item.BodyJSON, &item.CreatedAt, &item.UpdatedAt)
|
||||
`, name).Scan(&item.ID, &item.Name, &item.SourceType, &item.Area, &item.Description, &item.BodyJSON, &item.CreatedAt, &item.UpdatedAt)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@ -1488,7 +1488,7 @@ func (u *UI) actionWizardCreateSource(w http.ResponseWriter, r *http.Request) {
|
||||
FPS: "25",
|
||||
},
|
||||
}
|
||||
if err := u.preview.SaveVideoSourceAsset(asset); err != nil {
|
||||
if err := u.preview.SaveVideoSourceAsset(asset, ""); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
@ -3745,7 +3745,7 @@ func (u *UI) actionAssetVideoSourceSave(w http.ResponseWriter, r *http.Request)
|
||||
MountAngle: strings.TrimSpace(r.FormValue("mount_angle")),
|
||||
},
|
||||
}
|
||||
if err := u.preview.SaveVideoSourceAsset(asset); err != nil {
|
||||
if err := u.preview.SaveVideoSourceAsset(asset, ""); err != nil {
|
||||
data := u.assetPageData("video-sources")
|
||||
data.Title = "资产管理"
|
||||
data.Error = err.Error()
|
||||
@ -3755,16 +3755,23 @@ func (u *UI) actionAssetVideoSourceSave(w http.ResponseWriter, r *http.Request)
|
||||
u.render(w, r, "assets", data)
|
||||
return
|
||||
}
|
||||
// Handle rename
|
||||
originalName := strings.TrimSpace(r.FormValue("original_name"))
|
||||
if originalName != "" && originalName != asset.Name {
|
||||
if err := u.preview.RenameVideoSource(originalName, asset.Name); err != nil {
|
||||
data := u.assetPageData("video-sources")
|
||||
data.Error = err.Error()
|
||||
u.render(w, r, "assets", data)
|
||||
return
|
||||
// Pass ID for update (0 = new)
|
||||
if idStr := strings.TrimSpace(r.FormValue("id")); idStr != "" {
|
||||
if id, err := strconv.Atoi(idStr); err == nil {
|
||||
asset.ID = id
|
||||
}
|
||||
}
|
||||
originalName := strings.TrimSpace(r.FormValue("original_name"))
|
||||
if err := u.preview.SaveVideoSourceAsset(asset, originalName); err != nil {
|
||||
data := u.assetPageData("video-sources")
|
||||
data.Title = "资产管理"
|
||||
data.Error = err.Error()
|
||||
data.AssetVideoSource = &asset
|
||||
data.AssetVideoSource.SourceTypeLabel = serviceVideoSourceTypeLabel(asset.SourceType)
|
||||
data.AssetVideoSourceEditing = true
|
||||
u.render(w, r, "assets", data)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, "/assets/video-sources?msg="+urlQueryEscape("视频源已保存")+"&name="+url.PathEscape(asset.Name), http.StatusFound)
|
||||
}
|
||||
|
||||
@ -3887,7 +3894,7 @@ func (u *UI) actionVideoSourceCSVImport(w http.ResponseWriter, r *http.Request)
|
||||
FPS: fps,
|
||||
},
|
||||
}
|
||||
if err := u.preview.SaveVideoSourceAsset(asset); err != nil {
|
||||
if err := u.preview.SaveVideoSourceAsset(asset, ""); err != nil {
|
||||
skipped++
|
||||
continue
|
||||
}
|
||||
|
||||
@ -232,7 +232,7 @@ toggleIntegrationFields('{{.AssetIntegration.Type}}');
|
||||
</div>
|
||||
{{if .AssetVideoSource}}
|
||||
<form method="post" action="/assets/video-sources">
|
||||
{{if .AssetVideoSource.Name}}<input type="hidden" name="original_name" value="{{.AssetVideoSource.Name}}">{{end}}
|
||||
{{if .AssetVideoSource}}<input type="hidden" name="id" value="{{.AssetVideoSource.ID}}"><input type="hidden" name="original_name" value="{{.AssetVideoSource.Name}}">{{end}}
|
||||
<div class="card editor-state {{if .AssetVideoSourceEditing}}editing{{else}}readonly{{end}}">
|
||||
<div class="section-title">
|
||||
<div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user