Update project documentation and improve frontend functionality

- Updated the backend documentation in CONTRIBUTING.md and README.md to reflect changes in application structure and API endpoints.
- Enhanced the frontend components in MapView.vue for better handling of context menu actions.
- Added new types and interfaces in TypeScript for improved type safety in the frontend.
- Introduced new utility classes for managing characters and markers in the map.
- Updated .gitignore to include .vscode directory for better development environment management.
This commit is contained in:
2026-02-24 23:32:50 +03:00
parent 605a31567e
commit 82cb8a13f5
39 changed files with 1788 additions and 2631 deletions

188
internal/app/admin_tiles.go Normal file
View File

@@ -0,0 +1,188 @@
package app
import (
"encoding/json"
"net/http"
"strconv"
"time"
"go.etcd.io/bbolt"
)
func (a *App) wipeTile(rw http.ResponseWriter, req *http.Request) {
if a.requireAdmin(rw, req) == nil {
return
}
mraw := req.FormValue("map")
mapid, err := strconv.Atoi(mraw)
if err != nil {
http.Error(rw, "coord parse failed", http.StatusBadRequest)
return
}
xraw := req.FormValue("x")
x, err := strconv.Atoi(xraw)
if err != nil {
http.Error(rw, "coord parse failed", http.StatusBadRequest)
return
}
yraw := req.FormValue("y")
y, err := strconv.Atoi(yraw)
if err != nil {
http.Error(rw, "coord parse failed", http.StatusBadRequest)
return
}
c := Coord{
X: x,
Y: y,
}
a.db.Update(func(tx *bbolt.Tx) error {
grids := tx.Bucket([]byte("grids"))
if grids == nil {
return nil
}
ids := [][]byte{}
err := grids.ForEach(func(k, v []byte) error {
g := GridData{}
err := json.Unmarshal(v, &g)
if err != nil {
return err
}
if g.Coord == c && g.Map == mapid {
ids = append(ids, k)
}
return nil
})
if err != nil {
return err
}
for _, id := range ids {
grids.Delete(id)
}
return nil
})
a.SaveTile(mapid, c, 0, "", -1)
for z := 1; z <= 5; z++ {
c = c.Parent()
a.updateZoomLevel(mapid, c, z)
}
rw.WriteHeader(200)
}
func (a *App) setCoords(rw http.ResponseWriter, req *http.Request) {
if a.requireAdmin(rw, req) == nil {
return
}
mraw := req.FormValue("map")
mapid, err := strconv.Atoi(mraw)
if err != nil {
http.Error(rw, "coord parse failed", http.StatusBadRequest)
return
}
fxraw := req.FormValue("fx")
fx, err := strconv.Atoi(fxraw)
if err != nil {
http.Error(rw, "coord parse failed", http.StatusBadRequest)
return
}
fyraw := req.FormValue("fy")
fy, err := strconv.Atoi(fyraw)
if err != nil {
http.Error(rw, "coord parse failed", http.StatusBadRequest)
return
}
fc := Coord{
X: fx,
Y: fy,
}
txraw := req.FormValue("tx")
tx, err := strconv.Atoi(txraw)
if err != nil {
http.Error(rw, "coord parse failed", http.StatusBadRequest)
return
}
tyraw := req.FormValue("ty")
ty, err := strconv.Atoi(tyraw)
if err != nil {
http.Error(rw, "coord parse failed", http.StatusBadRequest)
return
}
tc := Coord{
X: tx,
Y: ty,
}
diff := Coord{
X: tc.X - fc.X,
Y: tc.Y - fc.Y,
}
tds := []*TileData{}
a.db.Update(func(tx *bbolt.Tx) error {
grids := tx.Bucket([]byte("grids"))
if grids == nil {
return nil
}
tiles := tx.Bucket([]byte("tiles"))
if tiles == nil {
return nil
}
mapZooms := tiles.Bucket([]byte(strconv.Itoa(mapid)))
if mapZooms == nil {
return nil
}
mapTiles := mapZooms.Bucket([]byte("0"))
err := grids.ForEach(func(k, v []byte) error {
g := GridData{}
err := json.Unmarshal(v, &g)
if err != nil {
return err
}
if g.Map == mapid {
g.Coord.X += diff.X
g.Coord.Y += diff.Y
raw, _ := json.Marshal(g)
grids.Put(k, raw)
}
return nil
})
if err != nil {
return err
}
err = mapTiles.ForEach(func(k, v []byte) error {
td := &TileData{}
err := json.Unmarshal(v, &td)
if err != nil {
return err
}
td.Coord.X += diff.X
td.Coord.Y += diff.Y
tds = append(tds, td)
return nil
})
if err != nil {
return err
}
err = tiles.DeleteBucket([]byte(strconv.Itoa(mapid)))
if err != nil {
return err
}
return nil
})
needProcess := map[zoomproc]struct{}{}
for _, td := range tds {
a.SaveTile(td.MapID, td.Coord, td.Zoom, td.File, time.Now().UnixNano())
needProcess[zoomproc{c: Coord{X: td.Coord.X, Y: td.Coord.Y}.Parent(), m: td.MapID}] = struct{}{}
}
for z := 1; z <= 5; z++ {
process := needProcess
needProcess = map[zoomproc]struct{}{}
for p := range process {
a.updateZoomLevel(p.m, p.c, z)
needProcess[zoomproc{p.c.Parent(), p.m}] = struct{}{}
}
}
rw.WriteHeader(200)
}