feat: add map feature to city show page

- Implement MapController for displaying city maps
- Add map rendering in the city show view
- Include weather arts in the city show controller
- Update asset pipeline to include Leaflet CSS and JS

This commit introduces a map feature that allows users to view
geographical information related to cities. The map is integrated
with weather arts data, enhancing the overall functionality of
the city show page.
This commit is contained in:
songtianlun 2025-02-14 18:05:03 +08:00
parent 95f94cb73b
commit df456d1031
10 changed files with 89 additions and 2 deletions

View File

@ -1,4 +1,5 @@
@import "photoswipe/dist/photoswipe.css";
/*@import "leaflet/dist/leaflet.css";*/
@tailwind base;
@tailwind components;

View File

@ -35,6 +35,7 @@ class CitiesController < ApplicationController
def show
@city = City.friendly.find(params[:id])
@arts = @city.weather_arts.order(weather_date: :desc).includes([ :image_attachment ])
ahoy.track "View City", {
city_id: @city.id,
name: @city.name,

View File

@ -8,9 +8,12 @@ import PhotoSwipeLightBoxController from "./photo_swipe_lightbox_controller"
import FlashMessageController from "./flash_controller"
import SearchController from "./search_controller"
import PageLoadTimeController from "./page_load_time_controller"
import MapController from "./map_controller"
application.register("hello", HelloController)
application.register("photo-swipe-lightbox", PhotoSwipeLightBoxController)
application.register("flash", FlashMessageController)
application.register("search", SearchController)
application.register("page-load-time", PageLoadTimeController)
application.register("map", MapController)

View File

@ -0,0 +1,58 @@
import { Controller } from "@hotwired/stimulus"
import L from 'leaflet'
import 'leaflet/dist/leaflet.css'
import iconUrl from 'leaflet/dist/images/marker-icon.png';
import iconRetinaUrl from 'leaflet/dist/images/marker-icon-2x.png';
// import iconRetinaUrl from '../images/leaflet/marker-icon-2x.png';
import shadowUrl from 'leaflet/dist/images/marker-shadow.png';
export default class extends Controller {
static values = {
latitude: Number,
longitude: Number
}
init() {
}
connect() {
delete L.Icon.Default.prototype._getIconUrl
L.Icon.Default.mergeOptions({
// iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
// iconUrl: require('leaflet/dist/images/marker-icon.png'),
// shadowUrl: require('leaflet/dist/images/marker-shadow.png')
iconRetinaUrl: iconRetinaUrl,
iconUrl: iconUrl,
shadowUrl: shadowUrl,
});
this.initializeMap()
}
initializeMap() {
// 创建地图实例
this.map = L.map(this.element).setView(
[this.latitudeValue, this.longitudeValue],
4 // 缩放级别
)
// 添加地图图层
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(this.map)
// 添加标记
L.marker([this.latitudeValue, this.longitudeValue])
.addTo(this.map)
.bindPopup(document.querySelector('h1').textContent)
.openPopup()
}
disconnect() {
if (this.map) {
this.map.remove()
}
}
}

View File

@ -0,0 +1,8 @@
<div class="mt-8">
<div
data-controller="map"
data-map-latitude-value="<%= city.latitude %>"
data-map-longitude-value="<%= city.longitude %>"
class="w-full h-[400px] rounded-lg shadow-lg">
</div>
</div>

View File

@ -61,6 +61,8 @@
], as: :stat %>
</div>
<%= render 'cities/map', city: @city %>
<%= render 'cities/admin_panel' %>
</div>
</div>
@ -86,7 +88,7 @@
<!-- 天气艺术卡片网格 -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<%= render partial: 'weather_arts/card', collection: @city.weather_arts.order(weather_date: :desc), as: :weather_art %>
<%= render partial: 'weather_arts/card', collection: @arts, as: :weather_art %>
</div>
</div>
</div>

View File

@ -79,4 +79,6 @@ Rails.application.configure do
# Apply autocorrection by RuboCop to files generated by `bin/rails generate`.
# config.generators.apply_rubocop_autocorrect_after_generate!
config.serve_static_assets = true
end

View File

@ -5,3 +5,9 @@ Rails.application.config.assets.version = "1.0"
# Add additional assets to the asset load path.
# Rails.application.config.assets.paths << Emoji.images_path
# Rails.application.config.assets.paths << Rails.root.join("app/assets/builds")
# Rails.application.config.assets.paths << Rails.root.join("node_modules")
# Rails.application.config.assets.precompile += %w( *.png *.jpg *.jpeg *.gif )
# Rails.application.config.assets.paths << Rails.root.join("app/assets/builds")
# Rails.application.config.assets.precompile += %w( *.png *.jpg *.jpeg *.gif )

View File

@ -6,7 +6,7 @@
"esbuild": "^0.24.2"
},
"scripts": {
"build": "esbuild app/javascript/*.* --bundle --sourcemap --format=esm --outdir=app/assets/builds --public-path=/assets --loader:.woff=file --loader:.woff2=file --loader:.ttf=file --loader:.eot=file --asset-names=[name]-[hash]",
"build": "esbuild app/javascript/*.* --bundle --sourcemap --format=esm --outdir=app/assets/builds --public-path=/assets --loader:.woff=file --loader:.woff2=file --loader:.ttf=file --loader:.eot=file --loader:.png=file --asset-names=[name]-[hash].digested --chunk-names=[name]-[hash].digested",
"build:css": "tailwindcss -i ./app/assets/stylesheets/application.tailwind.css -o ./app/assets/builds/application.css && sass ./app/assets/stylesheets/active_admin.scss:./app/assets/builds/active_admin.css --no-source-map --load-path=node_modules"
},
"dependencies": {
@ -18,6 +18,7 @@
"autoprefixer": "^10.4.20",
"jquery": "^3.7.1",
"jquery-ui": "^1.14.1",
"leaflet": "^1.9.4",
"photoswipe": "^5.4.4",
"postcss": "^8.5.1",
"sass": "^1.83.4",

View File

@ -739,6 +739,11 @@ jquery-ujs@^1.2.2:
resolved "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz"
integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==
leaflet@^1.9.4:
version "1.9.4"
resolved "https://registry.yarnpkg.com/leaflet/-/leaflet-1.9.4.tgz#23fae724e282fa25745aff82ca4d394748db7d8d"
integrity sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==
lilconfig@^3.0.0, lilconfig@^3.1.3:
version "3.1.3"
resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz"