feat: real photo delete from DB and disk, pass photo IDs to edit modal
This commit is contained in:
parent
0751adb564
commit
cb1ce4deaa
@ -3,6 +3,8 @@ package storage
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -11,6 +13,7 @@ type PersonRecord struct {
|
||||
Name string `json:"name"`
|
||||
PhotoCount int `json:"photo_count"`
|
||||
Photos []string `json:"photos,omitempty"`
|
||||
PhotoIDs []int `json:"photo_ids,omitempty"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
}
|
||||
|
||||
@ -71,14 +74,16 @@ func (r *FaceGalleryRepo) ListPersons() ([]PersonRecord, error) {
|
||||
}
|
||||
// Load photos for each person
|
||||
for i := range out {
|
||||
photoRows, err := db.Query(`SELECT photo_path FROM face_photos WHERE person_id = ? ORDER BY id`, out[i].ID)
|
||||
photoRows, err := db.Query(`SELECT photo_path, id FROM face_photos WHERE person_id = ? ORDER BY id`, out[i].ID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for photoRows.Next() {
|
||||
var path string
|
||||
if photoRows.Scan(&path) == nil {
|
||||
var pid int
|
||||
if photoRows.Scan(&path, &pid) == nil {
|
||||
out[i].Photos = append(out[i].Photos, path)
|
||||
out[i].PhotoIDs = append(out[i].PhotoIDs, pid)
|
||||
}
|
||||
}
|
||||
photoRows.Close()
|
||||
@ -156,3 +161,17 @@ func (r *FaceGalleryRepo) RenamePerson(id int, name string) error {
|
||||
_, err = db.Exec(`UPDATE face_persons SET name = ?, updated_at = ? WHERE id = ?`, name, now, id)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *FaceGalleryRepo) DeletePhoto(photoID int) error {
|
||||
db, err := r.open()
|
||||
if err != nil { return err }
|
||||
defer db.Close()
|
||||
// Get path before deleting
|
||||
var path string
|
||||
db.QueryRow(`SELECT photo_path FROM face_photos WHERE id = ?`, photoID).Scan(&path)
|
||||
_, err = db.Exec(`DELETE FROM face_photos WHERE id = ?`, photoID)
|
||||
if err != nil { return err }
|
||||
// Remove file from disk
|
||||
if path != "" { os.Remove(filepath.Join("dataset", path)) }
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -672,6 +672,7 @@ func (u *UI) Routes() (chi.Router, error) {
|
||||
r.Post("/face-gallery/delete", u.actionFaceGalleryDelete)
|
||||
r.Post("/face-gallery/rename", u.actionFaceGalleryRename)
|
||||
r.Post("/face-gallery/add-photo", u.actionFaceGalleryAddPhoto)
|
||||
r.Post("/face-gallery/delete-photo", u.actionFaceGalleryDeletePhoto)
|
||||
r.Get("/monitor", u.pageMonitor)
|
||||
r.Get("/hls/*", u.proxyHLS)
|
||||
r.Get("/api/monitor/channels", u.apiMonitorChannels)
|
||||
@ -4175,3 +4176,10 @@ func (u *UI) actionFaceGalleryAddPhoto(w http.ResponseWriter, r *http.Request) {
|
||||
repo.AddPhoto(id, personName+"/"+hdr.Filename)
|
||||
http.Redirect(w, r, "/ui/face-gallery", http.StatusFound)
|
||||
}
|
||||
func (u *UI) actionFaceGalleryDeletePhoto(w http.ResponseWriter, r *http.Request) {
|
||||
id, _ := strconv.Atoi(r.FormValue("id"))
|
||||
if id > 0 && strings.TrimSpace(u.dbPath) != "" {
|
||||
storage.NewFaceGalleryRepo(u.dbPath).DeletePhoto(id)
|
||||
}
|
||||
http.Redirect(w, r, "/ui/face-gallery", http.StatusFound)
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
<div style="margin-top:6px;display:flex;justify-content:space-between;align-items:center">
|
||||
<div><span style="font-weight:500;font-size:13px">{{.Name}}</span> <span class="muted small">{{.PhotoCount}}张</span></div>
|
||||
<div class="actions compact" style="gap:2px">
|
||||
<span class="btn-icon ghost edit-btn" title="编辑" data-id="{{.ID}}" data-name="{{.Name}}" data-photos='[{{range $i,$p := .Photos}}{{if $i}},{{end}}"/ui/face-photo/{{$p}}"{{end}}]'>✎</span>
|
||||
<span class="btn-icon ghost edit-btn" title="编辑" data-id="{{.ID}}" data-name="{{.Name}}" data-photos='[{{range $i,$p := .Photos}}{{if $i}},{{end}}{"p":"/ui/face-photo/{{$p}}","id":{{index $.PhotoIDs $i}}}{{end}}]'>✎</span>
|
||||
<form method="post" action="/ui/face-gallery/delete" style="display:inline" onsubmit="return confirm('确定删除 {{.Name}}?')">
|
||||
<input type="hidden" name="id" value="{{.ID}}">
|
||||
<span class="btn-icon ghost" style="color:var(--danger-soft-text)" title="删除" onclick="this.closest('form').requestSubmit()">✕</span>
|
||||
@ -79,7 +79,8 @@ function showEdit(id,name,photos){
|
||||
h+='<button class="btn" type="submit" style="margin-bottom:1px">保存</button></form>';
|
||||
h+='<div style="display:flex;flex-wrap:wrap;gap:8px;margin-bottom:12px">';
|
||||
photos.forEach(function(p){
|
||||
h+='<div style="position:relative;width:80px;height:100px"><img src="'+p+'" style="width:100%;height:100%;object-fit:cover;border-radius:4px"><span class="btn-icon ghost" style="position:absolute;top:2px;right:2px;font-size:10px;color:red;background:rgba(0,0,0,0.5)" onclick="this.parentElement.remove()">×</span></div>';
|
||||
h+='<div style="position:relative;width:80px;height:100px"><img src="'+p.p+'" style="width:100%;height:100%;object-fit:cover;border-radius:4px">';
|
||||
h+='<form method="post" action="/ui/face-gallery/delete-photo" style="position:absolute;top:2px;right:2px"><input type="hidden" name="id" value="'+p.id+'"><span class="btn-icon ghost" style="font-size:10px;color:red;background:rgba(0,0,0,0.5)" onclick="this.closest(\'form\').submit()">×</span></form></div>';
|
||||
});
|
||||
h+='</div>';
|
||||
h+='<form method="post" action="/ui/face-gallery/add-photo" enctype="multipart/form-data" style="display:flex;gap:8px;align-items:flex-end">';
|
||||
|
||||
Loading…
Reference in New Issue
Block a user