代理与否可控
This commit is contained in:
+23
-17
@@ -10,12 +10,13 @@ import (
|
||||
)
|
||||
|
||||
type mapTileSourceRequest struct {
|
||||
Name string `json:"name"`
|
||||
URLTemplate string `json:"url_template"`
|
||||
Attribution string `json:"attribution"`
|
||||
MaxZoom int `json:"max_zoom"`
|
||||
Enabled bool `json:"enabled"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
Name string `json:"name"`
|
||||
URLTemplate string `json:"url_template"`
|
||||
Attribution string `json:"attribution"`
|
||||
MaxZoom int `json:"max_zoom"`
|
||||
Enabled bool `json:"enabled"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
ProxyEnabled bool `json:"proxy_enabled"`
|
||||
}
|
||||
|
||||
func registerMapSourceRoutes(r gin.IRouter, store *store) {
|
||||
@@ -96,12 +97,13 @@ func registerAdminMapSourceRoutes(r gin.IRouter, store *store) {
|
||||
|
||||
func mapTileSourceInputFromRequest(req mapTileSourceRequest) mapTileSourceInput {
|
||||
return mapTileSourceInput{
|
||||
Name: req.Name,
|
||||
URLTemplate: req.URLTemplate,
|
||||
Attribution: req.Attribution,
|
||||
MaxZoom: req.MaxZoom,
|
||||
Enabled: req.Enabled,
|
||||
IsDefault: req.IsDefault,
|
||||
Name: req.Name,
|
||||
URLTemplate: req.URLTemplate,
|
||||
Attribution: req.Attribution,
|
||||
MaxZoom: req.MaxZoom,
|
||||
Enabled: req.Enabled,
|
||||
IsDefault: req.IsDefault,
|
||||
ProxyEnabled: req.ProxyEnabled,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,13 +153,17 @@ func writeMapTileSourceDeleteResponse(c *gin.Context, err error) {
|
||||
}
|
||||
|
||||
func mapTileSourceDTO(row mapTileSourceRecord) gin.H {
|
||||
return gin.H{"id": row.ID, "name": row.Name, "url_template": row.URLTemplate, "attribution": row.Attribution, "max_zoom": row.MaxZoom, "enabled": row.Enabled, "is_default": row.IsDefault, "created_at": row.CreatedAt, "updated_at": row.UpdatedAt}
|
||||
return gin.H{"id": row.ID, "name": row.Name, "url_template": row.URLTemplate, "attribution": row.Attribution, "max_zoom": row.MaxZoom, "enabled": row.Enabled, "is_default": row.IsDefault, "proxy_enabled": row.ProxyEnabled, "created_at": row.CreatedAt, "updated_at": row.UpdatedAt}
|
||||
}
|
||||
|
||||
func publicMapTileSourceDTO(row mapTileSourceRecord) gin.H {
|
||||
hash := row.URLTemplateHash
|
||||
if hash == "" {
|
||||
hash = mapTileSourceHash(row.URLTemplate)
|
||||
urlTemplate := row.URLTemplate
|
||||
if row.ProxyEnabled {
|
||||
hash := row.URLTemplateHash
|
||||
if hash == "" {
|
||||
hash = mapTileSourceHash(row.URLTemplate)
|
||||
}
|
||||
urlTemplate = "/api/map/" + hash + "?x={x}&y={y}&z={z}"
|
||||
}
|
||||
return gin.H{"id": row.ID, "name": row.Name, "url_template": "/api/map/" + hash + "?x={x}&y={y}&z={z}", "attribution": row.Attribution, "max_zoom": row.MaxZoom}
|
||||
return gin.H{"id": row.ID, "name": row.Name, "url_template": urlTemplate, "attribution": row.Attribution, "max_zoom": row.MaxZoom}
|
||||
}
|
||||
|
||||
@@ -124,6 +124,7 @@ type mapTileSourceRecord struct {
|
||||
MaxZoom int `gorm:"column:max_zoom;not null"`
|
||||
Enabled bool `gorm:"column:enabled;not null;index"`
|
||||
IsDefault bool `gorm:"column:is_default;not null;index"`
|
||||
ProxyEnabled bool `gorm:"column:proxy_enabled;not null;index"`
|
||||
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime;index"`
|
||||
}
|
||||
@@ -472,6 +473,15 @@ func (s *store) migrate() error {
|
||||
}
|
||||
|
||||
func migrateMapTileSourceHash(tx *gorm.DB, migrator gorm.Migrator, driver string) error {
|
||||
if !migrator.HasColumn(&mapTileSourceRecord{}, "ProxyEnabled") {
|
||||
if driver == databaseDriverSQLite {
|
||||
if err := tx.Exec("ALTER TABLE map_tile_sources ADD COLUMN proxy_enabled numeric NOT NULL DEFAULT true").Error; err != nil {
|
||||
return fmt.Errorf("migrate map_tile_sources proxy_enabled column: %w", err)
|
||||
}
|
||||
} else if err := migrator.AddColumn(&mapTileSourceRecord{}, "ProxyEnabled"); err != nil {
|
||||
return fmt.Errorf("migrate map_tile_sources proxy_enabled column: %w", err)
|
||||
}
|
||||
}
|
||||
if !migrator.HasColumn(&mapTileSourceRecord{}, "URLTemplateHash") {
|
||||
if driver == databaseDriverSQLite {
|
||||
if err := tx.Exec("ALTER TABLE map_tile_sources ADD COLUMN url_template_hash TEXT NOT NULL DEFAULT ''").Error; err != nil {
|
||||
|
||||
+11
-7
@@ -29,12 +29,13 @@ var (
|
||||
)
|
||||
|
||||
type mapTileSourceInput struct {
|
||||
Name string
|
||||
URLTemplate string
|
||||
Attribution string
|
||||
MaxZoom int
|
||||
Enabled bool
|
||||
IsDefault bool
|
||||
Name string
|
||||
URLTemplate string
|
||||
Attribution string
|
||||
MaxZoom int
|
||||
Enabled bool
|
||||
IsDefault bool
|
||||
ProxyEnabled bool
|
||||
}
|
||||
|
||||
func (s *store) ListMapTileSources(opts listOptions) ([]mapTileSourceRecord, error) {
|
||||
@@ -85,7 +86,7 @@ func (s *store) GetDefaultMapTileSource() (*mapTileSourceRecord, error) {
|
||||
|
||||
func (s *store) GetEnabledMapTileSourceByHash(hash string) (*mapTileSourceRecord, error) {
|
||||
var row mapTileSourceRecord
|
||||
if err := s.db.Where("enabled = ? AND url_template_hash = ?", true, hash).Take(&row).Error; err != nil {
|
||||
if err := s.db.Where("enabled = ? AND proxy_enabled = ? AND url_template_hash = ?", true, true, hash).Take(&row).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &row, nil
|
||||
@@ -154,6 +155,7 @@ func (s *store) UpdateMapTileSource(id uint64, input mapTileSourceInput) (*mapTi
|
||||
"max_zoom": row.MaxZoom,
|
||||
"enabled": row.Enabled,
|
||||
"is_default": row.IsDefault,
|
||||
"proxy_enabled": row.ProxyEnabled,
|
||||
"updated_at": time.Now(),
|
||||
}
|
||||
if err := tx.Model(&mapTileSourceRecord{}).Where("id = ?", id).Updates(updates).Error; err != nil {
|
||||
@@ -269,6 +271,7 @@ func defaultMapTileSourceRecord() mapTileSourceRecord {
|
||||
MaxZoom: defaultMapTileSourceMaxZoom,
|
||||
Enabled: true,
|
||||
IsDefault: true,
|
||||
ProxyEnabled: true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,6 +299,7 @@ func mapTileSourceFromInput(input mapTileSourceInput) (*mapTileSourceRecord, err
|
||||
MaxZoom: maxZoom,
|
||||
Enabled: input.Enabled,
|
||||
IsDefault: input.IsDefault,
|
||||
ProxyEnabled: input.ProxyEnabled,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
+47
-10
@@ -25,13 +25,13 @@ func TestCreateMapTileSourceValidation(t *testing.T) {
|
||||
st := openTestStore(t)
|
||||
defer st.Close()
|
||||
|
||||
if _, err := st.CreateMapTileSource(mapTileSourceInput{Name: "bad", URLTemplate: "https://tiles.example.com/{z}/{x}.png", MaxZoom: 19, Enabled: true}); err == nil {
|
||||
if _, err := st.CreateMapTileSource(mapTileSourceInput{Name: "bad", URLTemplate: "https://tiles.example.com/{z}/{x}.png", MaxZoom: 19, Enabled: true, ProxyEnabled: true}); err == nil {
|
||||
t.Fatal("CreateMapTileSource() missing placeholder error = nil, want error")
|
||||
}
|
||||
if _, err := st.CreateMapTileSource(mapTileSourceInput{Name: "bad", URLTemplate: "javascript:alert(1)/{z}/{x}/{y}", MaxZoom: 19, Enabled: true}); err == nil {
|
||||
if _, err := st.CreateMapTileSource(mapTileSourceInput{Name: "bad", URLTemplate: "javascript:alert(1)/{z}/{x}/{y}", MaxZoom: 19, Enabled: true, ProxyEnabled: true}); err == nil {
|
||||
t.Fatal("CreateMapTileSource() invalid scheme error = nil, want error")
|
||||
}
|
||||
if _, err := st.CreateMapTileSource(mapTileSourceInput{Name: "bad", URLTemplate: "https://user:pass@tiles.example.com/{z}/{x}/{y}.png", MaxZoom: 19, Enabled: true}); err == nil {
|
||||
if _, err := st.CreateMapTileSource(mapTileSourceInput{Name: "bad", URLTemplate: "https://user:pass@tiles.example.com/{z}/{x}/{y}.png", MaxZoom: 19, Enabled: true, ProxyEnabled: true}); err == nil {
|
||||
t.Fatal("CreateMapTileSource() credentials error = nil, want error")
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ func TestListEnabledMapTileSources(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("CreateMapTileSource(disabled) error = %v", err)
|
||||
}
|
||||
custom, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Custom", URLTemplate: "https://custom.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true})
|
||||
custom, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Custom", URLTemplate: "https://custom.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: true})
|
||||
if err != nil {
|
||||
t.Fatalf("CreateMapTileSource(custom) error = %v", err)
|
||||
}
|
||||
@@ -76,14 +76,14 @@ func TestMapTileSourceDuplicateAndDefaultRules(t *testing.T) {
|
||||
st := openTestStore(t)
|
||||
defer st.Close()
|
||||
|
||||
first, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Custom", URLTemplate: "https://tiles.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true})
|
||||
first, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Custom", URLTemplate: "https://tiles.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: true})
|
||||
if err != nil {
|
||||
t.Fatalf("CreateMapTileSource() error = %v", err)
|
||||
}
|
||||
if _, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Custom", URLTemplate: "https://tiles2.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true}); !errors.Is(err, errMapTileSourceAlreadyExists) {
|
||||
if _, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Custom", URLTemplate: "https://tiles2.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: true}); !errors.Is(err, errMapTileSourceAlreadyExists) {
|
||||
t.Fatalf("duplicate name error = %v, want errMapTileSourceAlreadyExists", err)
|
||||
}
|
||||
if _, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Custom 2", URLTemplate: first.URLTemplate, MaxZoom: 18, Enabled: true}); !errors.Is(err, errMapTileSourceAlreadyExists) {
|
||||
if _, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Custom 2", URLTemplate: first.URLTemplate, MaxZoom: 18, Enabled: true, ProxyEnabled: true}); !errors.Is(err, errMapTileSourceAlreadyExists) {
|
||||
t.Fatalf("duplicate url error = %v, want errMapTileSourceAlreadyExists", err)
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ func TestMapTileSourceHashIsSetOnCreate(t *testing.T) {
|
||||
st := openTestStore(t)
|
||||
defer st.Close()
|
||||
|
||||
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Hashed", URLTemplate: "https://test.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true})
|
||||
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Hashed", URLTemplate: "https://test.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: true})
|
||||
if err != nil {
|
||||
t.Fatalf("CreateMapTileSource() error = %v", err)
|
||||
}
|
||||
@@ -122,6 +122,9 @@ func TestMapTileSourceHashIsSetOnCreate(t *testing.T) {
|
||||
if row.URLTemplateHash != want {
|
||||
t.Fatalf("URLTemplateHash = %q, want %q", row.URLTemplateHash, want)
|
||||
}
|
||||
if !row.ProxyEnabled {
|
||||
t.Fatal("ProxyEnabled = false, want true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapTileSourceDefaultHasHash(t *testing.T) {
|
||||
@@ -142,7 +145,7 @@ func TestGetEnabledMapTileSourceByHash(t *testing.T) {
|
||||
st := openTestStore(t)
|
||||
defer st.Close()
|
||||
|
||||
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "HashLookup", URLTemplate: "https://lookup.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true})
|
||||
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "HashLookup", URLTemplate: "https://lookup.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: true})
|
||||
if err != nil {
|
||||
t.Fatalf("CreateMapTileSource() error = %v", err)
|
||||
}
|
||||
@@ -171,6 +174,21 @@ func TestGetEnabledMapTileSourceByHashDisabled(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetEnabledMapTileSourceByHashProxyDisabled(t *testing.T) {
|
||||
st := openTestStore(t)
|
||||
defer st.Close()
|
||||
|
||||
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "ProxyDisabledHash", URLTemplate: "https://proxy-disabled.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: false})
|
||||
if err != nil {
|
||||
t.Fatalf("CreateMapTileSource() error = %v", err)
|
||||
}
|
||||
|
||||
_, err = st.GetEnabledMapTileSourceByHash(row.URLTemplateHash)
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
t.Fatalf("GetEnabledMapTileSourceByHash(proxy disabled) = %v, want gorm.ErrRecordNotFound", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetEnabledMapTileSourceByHashUnknown(t *testing.T) {
|
||||
st := openTestStore(t)
|
||||
defer st.Close()
|
||||
@@ -185,7 +203,7 @@ func TestPublicMapTileSourceDTOProxyURL(t *testing.T) {
|
||||
st := openTestStore(t)
|
||||
defer st.Close()
|
||||
|
||||
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "ProxyTest", URLTemplate: "https://proxy.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true})
|
||||
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "ProxyTest", URLTemplate: "https://proxy.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: true})
|
||||
if err != nil {
|
||||
t.Fatalf("CreateMapTileSource() error = %v", err)
|
||||
}
|
||||
@@ -204,6 +222,25 @@ func TestPublicMapTileSourceDTOProxyURL(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPublicMapTileSourceDTORawURLWhenProxyDisabled(t *testing.T) {
|
||||
st := openTestStore(t)
|
||||
defer st.Close()
|
||||
|
||||
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "RawTest", URLTemplate: "https://raw.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: false})
|
||||
if err != nil {
|
||||
t.Fatalf("CreateMapTileSource() error = %v", err)
|
||||
}
|
||||
|
||||
dto := publicMapTileSourceDTO(*row)
|
||||
urlTemplate, ok := dto["url_template"].(string)
|
||||
if !ok {
|
||||
t.Fatal("url_template is not a string")
|
||||
}
|
||||
if urlTemplate != row.URLTemplate {
|
||||
t.Fatalf("url_template = %q, want raw %q", urlTemplate, row.URLTemplate)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapTileSourceHashFunction(t *testing.T) {
|
||||
hash1 := mapTileSourceHash("https://tile.openstreetmap.jp/{z}/{x}/{y}.png")
|
||||
hash2 := mapTileSourceHash("https://tile.openstreetmap.jp/{z}/{x}/{y}.png")
|
||||
|
||||
@@ -24,7 +24,7 @@ func TestMapTileProxyFetchesAndCaches(t *testing.T) {
|
||||
}))
|
||||
defer upstream.Close()
|
||||
|
||||
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Tiles", URLTemplate: upstream.URL + "/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true})
|
||||
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Tiles", URLTemplate: upstream.URL + "/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: true})
|
||||
if err != nil {
|
||||
t.Fatalf("CreateMapTileSource() error = %v", err)
|
||||
}
|
||||
@@ -62,7 +62,7 @@ func TestMapTileProxyRejectsInvalidCoordinates(t *testing.T) {
|
||||
st := openTestStore(t)
|
||||
defer st.Close()
|
||||
|
||||
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Tiles", URLTemplate: "https://tiles.example.com/{z}/{x}/{y}.png", MaxZoom: 3, Enabled: true})
|
||||
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Tiles", URLTemplate: "https://tiles.example.com/{z}/{x}/{y}.png", MaxZoom: 3, Enabled: true, ProxyEnabled: true})
|
||||
if err != nil {
|
||||
t.Fatalf("CreateMapTileSource() error = %v", err)
|
||||
}
|
||||
@@ -91,7 +91,11 @@ func TestMapTileProxyUnknownAndDisabledSource(t *testing.T) {
|
||||
|
||||
disabled, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Disabled", URLTemplate: "https://disabled.example.com/{z}/{x}/{y}.png", MaxZoom: 3, Enabled: false})
|
||||
if err != nil {
|
||||
t.Fatalf("CreateMapTileSource() error = %v", err)
|
||||
t.Fatalf("CreateMapTileSource(disabled) error = %v", err)
|
||||
}
|
||||
proxyDisabled, err := st.CreateMapTileSource(mapTileSourceInput{Name: "ProxyDisabled", URLTemplate: "https://proxy-disabled.example.com/{z}/{x}/{y}.png", MaxZoom: 3, Enabled: true, ProxyEnabled: false})
|
||||
if err != nil {
|
||||
t.Fatalf("CreateMapTileSource(proxy disabled) error = %v", err)
|
||||
}
|
||||
|
||||
router := newRouter(webConfig{StaticDir: t.TempDir(), MapTileCacheDir: t.TempDir()}, st, nil, nil, nil, nil, nil)
|
||||
@@ -100,8 +104,9 @@ func TestMapTileProxyUnknownAndDisabledSource(t *testing.T) {
|
||||
"/api/map/not-a-hash?x=0&y=0&z=0",
|
||||
"/api/map/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa?x=0&y=0&z=0",
|
||||
"/api/map/" + disabled.URLTemplateHash + "?x=0&y=0&z=0",
|
||||
"/api/map/" + proxyDisabled.URLTemplateHash + "?x=0&y=0&z=0",
|
||||
}
|
||||
wantStatus := []int{http.StatusBadRequest, http.StatusNotFound, http.StatusNotFound}
|
||||
wantStatus := []int{http.StatusBadRequest, http.StatusNotFound, http.StatusNotFound, http.StatusNotFound}
|
||||
for i, url := range cases {
|
||||
recorder := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(http.MethodGet, url, nil)
|
||||
@@ -125,11 +130,11 @@ func TestMapTileProxyUpstreamStatus(t *testing.T) {
|
||||
}))
|
||||
defer upstream.Close()
|
||||
|
||||
row404, err := st.CreateMapTileSource(mapTileSourceInput{Name: "NotFoundTiles", URLTemplate: upstream.URL + "/404/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true})
|
||||
row404, err := st.CreateMapTileSource(mapTileSourceInput{Name: "NotFoundTiles", URLTemplate: upstream.URL + "/404/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: true})
|
||||
if err != nil {
|
||||
t.Fatalf("CreateMapTileSource(404) error = %v", err)
|
||||
}
|
||||
row500, err := st.CreateMapTileSource(mapTileSourceInput{Name: "StatusTiles", URLTemplate: upstream.URL + "/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true})
|
||||
row500, err := st.CreateMapTileSource(mapTileSourceInput{Name: "StatusTiles", URLTemplate: upstream.URL + "/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: true})
|
||||
if err != nil {
|
||||
t.Fatalf("CreateMapTileSource(500) error = %v", err)
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ const newSource = ref<MapTileSourcePayload>({
|
||||
max_zoom: 19,
|
||||
enabled: true,
|
||||
is_default: false,
|
||||
proxy_enabled: true,
|
||||
})
|
||||
|
||||
const canPrev = () => page.value > 1
|
||||
@@ -32,6 +33,7 @@ function editableCopy(item: MapTileSource): MapTileSourcePayload {
|
||||
max_zoom: item.max_zoom,
|
||||
enabled: item.enabled,
|
||||
is_default: item.is_default,
|
||||
proxy_enabled: item.proxy_enabled,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +47,7 @@ function resetNewSource() {
|
||||
max_zoom: 19,
|
||||
enabled: true,
|
||||
is_default: false,
|
||||
proxy_enabled: true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,6 +217,7 @@ onMounted(refreshItems)
|
||||
<label class="field zoom-field">最大缩放<input v-model.number="newSource.max_zoom" type="number" min="1" max="30" /></label>
|
||||
<label class="switch-card"><input v-model="newSource.enabled" type="checkbox" /> <span>启用</span></label>
|
||||
<label class="switch-card"><input v-model="newSource.is_default" type="checkbox" /> <span>设为默认</span></label>
|
||||
<label class="switch-card"><input v-model="newSource.proxy_enabled" type="checkbox" /> <span>是否代理</span></label>
|
||||
<div class="form-actions">
|
||||
<button class="admin-button" type="submit" :disabled="loading">添加图源</button>
|
||||
</div>
|
||||
@@ -254,6 +258,7 @@ onMounted(refreshItems)
|
||||
<label class="field attribution-field">Attribution<input v-model="drafts[item.id].attribution" /></label>
|
||||
<label class="field zoom-field">最大缩放<input v-model.number="drafts[item.id].max_zoom" type="number" min="1" max="30" /></label>
|
||||
<label class="switch-card"><input v-model="drafts[item.id].enabled" type="checkbox" :disabled="item.is_default" /> <span>启用图源</span></label>
|
||||
<label class="switch-card"><input v-model="drafts[item.id].proxy_enabled" type="checkbox" /> <span>是否代理</span></label>
|
||||
</div>
|
||||
|
||||
<div class="source-meta">
|
||||
|
||||
@@ -87,6 +87,7 @@ export interface PublicMapTileSource {
|
||||
export interface MapTileSource extends PublicMapTileSource {
|
||||
enabled: boolean
|
||||
is_default: boolean
|
||||
proxy_enabled: boolean
|
||||
created_at: string
|
||||
updated_at: string
|
||||
}
|
||||
@@ -98,6 +99,7 @@ export interface MapTileSourcePayload {
|
||||
max_zoom: number
|
||||
enabled: boolean
|
||||
is_default: boolean
|
||||
proxy_enabled: boolean
|
||||
}
|
||||
|
||||
export interface MapTileSourceResponse {
|
||||
|
||||
Reference in New Issue
Block a user