Compare commits
17 Commits
7612dd6bd9
...
c37a93bcdf
Author | SHA1 | Date | |
---|---|---|---|
c37a93bcdf | |||
7ebf9cefae | |||
dd37e2835b | |||
4e1fb58abf | |||
5bc06007b2 | |||
84c224cf8d | |||
032ff0552a | |||
3203face6b | |||
8364d42759 | |||
9ce473dddb | |||
fe55437c96 | |||
ec3669249f | |||
f6270b1ad4 | |||
9dd7044a77 | |||
dd6bb9972c | |||
23fc14af59 | |||
fedb954d34 |
@ -36,18 +36,17 @@ ActiveAdmin.register City do
|
|||||||
|
|
||||||
filter :name
|
filter :name
|
||||||
filter :active
|
filter :active
|
||||||
|
filter :country, as: :select
|
||||||
|
|
||||||
form do |f|
|
form do |f|
|
||||||
f.inputs do
|
f.inputs do
|
||||||
f.input :active
|
f.input :active
|
||||||
f.input :name
|
f.input :name
|
||||||
|
f.input :country
|
||||||
f.input :latitude
|
f.input :latitude
|
||||||
f.input :longitude
|
f.input :longitude
|
||||||
f.input :priority
|
f.input :priority
|
||||||
f.input :timezone
|
f.input :timezone
|
||||||
f.input :region
|
|
||||||
f.input :last_weather_fetch
|
|
||||||
f.input :last_image_generation
|
|
||||||
end
|
end
|
||||||
f.actions
|
f.actions
|
||||||
end
|
end
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
ActiveAdmin.register Country do
|
ActiveAdmin.register Country do
|
||||||
|
controller do
|
||||||
|
def find_resource
|
||||||
|
scoped_collection.friendly.find(params[:id])
|
||||||
|
end
|
||||||
|
end
|
||||||
# See permitted parameters documentation:
|
# See permitted parameters documentation:
|
||||||
# https://github.com/activeadmin/activeadmin/blob/master/docs/2-resource-customization.md#setting-up-strong-parameters
|
# https://github.com/activeadmin/activeadmin/blob/master/docs/2-resource-customization.md#setting-up-strong-parameters
|
||||||
#
|
#
|
||||||
|
@ -1,2 +1,51 @@
|
|||||||
module WeatherArtsHelper
|
module WeatherArtsHelper
|
||||||
|
def weather_description_icon(description)
|
||||||
|
case description&.downcase
|
||||||
|
when /rain/
|
||||||
|
'<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3" />
|
||||||
|
</svg>'.html_safe
|
||||||
|
when /cloud/
|
||||||
|
'<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z" />
|
||||||
|
</svg>'.html_safe
|
||||||
|
when /sun|clear/
|
||||||
|
'<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" />
|
||||||
|
</svg>'.html_safe
|
||||||
|
else
|
||||||
|
'<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
|
</svg>'.html_safe
|
||||||
|
end
|
||||||
|
end
|
||||||
|
def weather_stat_icon(type)
|
||||||
|
case type
|
||||||
|
when "temperature"
|
||||||
|
'<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v3m0 0v3m0-3h3m-3 0H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
|
</svg>'.html_safe
|
||||||
|
when "wind"
|
||||||
|
'<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3" />
|
||||||
|
</svg>'.html_safe
|
||||||
|
when "humidity"
|
||||||
|
'<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19.428 15.428a2 2 0 00-1.022-.547l-2.387-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z" />
|
||||||
|
</svg>'.html_safe
|
||||||
|
when "visibility"
|
||||||
|
'<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
|
||||||
|
</svg>'.html_safe
|
||||||
|
when "pressure"
|
||||||
|
'<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 8v8m-4-5v5m-4-2v2m-2 4h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
||||||
|
</svg>'.html_safe
|
||||||
|
when "cloud"
|
||||||
|
'<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z" />
|
||||||
|
</svg>'.html_safe
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
6
app/javascript/active_admin.js
Normal file
6
app/javascript/active_admin.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
import './add_jquery'
|
||||||
|
import "jquery/dist/jquery"
|
||||||
|
import "jquery-ui/dist/jquery-ui"
|
||||||
|
import "jquery-ujs"
|
||||||
|
import "@activeadmin/activeadmin"
|
4
app/javascript/add_jquery.js
Normal file
4
app/javascript/add_jquery.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import jquery from 'jquery'
|
||||||
|
import $ from 'jquery'
|
||||||
|
window.jQuery = jquery
|
||||||
|
window.$ = $
|
@ -6,3 +6,4 @@ import "@fontsource/raleway/400.css";
|
|||||||
import "@fontsource/raleway/600.css";
|
import "@fontsource/raleway/600.css";
|
||||||
|
|
||||||
import "./controllers"
|
import "./controllers"
|
||||||
|
import "./active_admin"
|
||||||
|
@ -45,7 +45,7 @@ class City < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def self.ransackable_attributes(auth_object = nil)
|
def self.ransackable_attributes(auth_object = nil)
|
||||||
[ "active", "country", "created_at", "id", "id_value", "last_image_generation", "last_weather_fetch", "latitude", "longitude", "name", "priority", "region", "slug", "timezone", "updated_at" ]
|
[ "active", "country_id", "created_at", "id", "id_value", "last_image_generation", "last_weather_fetch", "latitude", "longitude", "name", "priority", "region", "slug", "timezone", "updated_at" ]
|
||||||
end
|
end
|
||||||
|
|
||||||
def last_weather_fetch
|
def last_weather_fetch
|
||||||
|
@ -1,37 +1,53 @@
|
|||||||
<div class="min-h-screen">
|
<div class="min-h-screen bg-base-200">
|
||||||
<!-- 城市头部信息 -->
|
<!-- 城市头部信息 -->
|
||||||
<section class="relative h-[40vh] overflow-hidden">
|
<section class="relative h-[50vh] overflow-hidden">
|
||||||
<% if @city.latest_weather_art&.image&.attached? %>
|
<% if @city.latest_weather_art&.image&.attached? %>
|
||||||
<%= image_tag @city.latest_weather_art.image,
|
<%= image_tag @city.latest_weather_art.image,
|
||||||
class: "w-full h-full object-cover" %>
|
class: "w-full h-full object-cover" %>
|
||||||
<div class="absolute inset-0 bg-gradient-to-t from-base-100 via-base-100/50 to-transparent"></div>
|
<div class="absolute inset-0 bg-gradient-to-t from-base-100 via-base-100/60 to-transparent"></div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<div class="absolute inset-0 flex items-center">
|
<div class="absolute inset-0 flex items-center">
|
||||||
<div class="container mx-auto px-4">
|
<div class="container mx-auto px-4">
|
||||||
<div class="max-w-4xl">
|
<div class="max-w-4xl">
|
||||||
<div class="flex items-center space-x-4 mb-4">
|
<div class="flex items-center space-x-4 mb-6">
|
||||||
<%= link_to cities_path,
|
<%= link_to cities_path,
|
||||||
class: "btn btn-ghost btn-circle" do %>
|
class: "btn btn-ghost btn-circle bg-base-100/50 backdrop-blur-sm hover:bg-base-100/70" do %>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
|
||||||
</svg>
|
</svg>
|
||||||
<% end %>
|
<% end %>
|
||||||
<h1 class="text-4xl md:text-5xl font-display font-bold"><%= @city.localized_name %></h1>
|
<div>
|
||||||
|
<h1 class="text-4xl md:text-5xl font-display font-bold mb-2"><%= @city.localized_name %></h1>
|
||||||
|
<p class="text-lg opacity-80">
|
||||||
|
<%= @city.country.name %>, <%= @city.region %>
|
||||||
|
<span class="mx-2">•</span>
|
||||||
|
<%= Time.current.in_time_zone(@city.timezone).strftime("%Y-%m-%d %H:%M") %>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="stats bg-base-100/80 backdrop-blur-sm shadow">
|
<div class="stats bg-base-100/80 backdrop-blur-sm shadow-lg rounded-box">
|
||||||
<div class="stat">
|
<div class="stat">
|
||||||
<div class="stat-title">Latitude</div>
|
<div class="stat-title">Latest Weather</div>
|
||||||
<div class="stat-value text-2xl"><%= @city.latitude %></div>
|
<div class="stat-value text-2xl">
|
||||||
|
<%= @city.latest_weather_art&.temperature %>°C
|
||||||
|
</div>
|
||||||
|
<div class="stat-desc">
|
||||||
|
<%= @city.latest_weather_art&.description %>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="stat">
|
<div class="stat">
|
||||||
<div class="stat-title">Longitude</div>
|
<div class="stat-title">Coordinates</div>
|
||||||
<div class="stat-value text-2xl"><%= @city.longitude %></div>
|
<div class="stat-value text-xl">
|
||||||
|
<%= @city.latitude %>°N, <%= @city.longitude %>°E
|
||||||
|
</div>
|
||||||
|
<div class="stat-desc">Geographical Location</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="stat">
|
<div class="stat">
|
||||||
<div class="stat-title">Weather Arts</div>
|
<div class="stat-title">Weather Records</div>
|
||||||
<div class="stat-value text-2xl"><%= @city.weather_arts.count %></div>
|
<div class="stat-value text-2xl"><%= @city.weather_arts.count %></div>
|
||||||
|
<div class="stat-desc">Total Entries</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -42,20 +58,39 @@
|
|||||||
<!-- 天气艺术历史记录 -->
|
<!-- 天气艺术历史记录 -->
|
||||||
<section class="container mx-auto px-4 py-16">
|
<section class="container mx-auto px-4 py-16">
|
||||||
<div class="space-y-8">
|
<div class="space-y-8">
|
||||||
<h2 class="text-3xl font-display font-bold">Weather Art History</h2>
|
<div class="flex justify-between items-center">
|
||||||
|
<h2 class="text-3xl font-display font-bold">Weather Art History</h2>
|
||||||
|
<div class="stats shadow inline-flex">
|
||||||
|
<div class="stat">
|
||||||
|
<div class="stat-title">Last Updated</div>
|
||||||
|
<div class="stat-value text-primary text-lg">
|
||||||
|
<%= time_ago_in_words(@city.last_weather_fetch) if @city.last_weather_fetch %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
<% @city.weather_arts.order(weather_date: :desc).each do |art| %>
|
<% @city.weather_arts.order(weather_date: :desc).each do |art| %>
|
||||||
<div class="card bg-base-100 shadow-xl hover:shadow-2xl transition-all duration-300">
|
<div class="card bg-base-100 shadow-xl hover:shadow-2xl transition-all duration-300">
|
||||||
<figure class="relative aspect-[4/3] overflow-hidden">
|
<figure class="relative aspect-video overflow-hidden">
|
||||||
<% if art.image.attached? %>
|
<% if art.image.attached? %>
|
||||||
<%= image_tag art.image,
|
<%= image_tag art.image,
|
||||||
class: "w-full h-full object-cover transform hover:scale-105 transition-transform duration-500" %>
|
class: "w-full h-full object-cover transform hover:scale-105 transition-transform duration-500" %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<div class="absolute bottom-0 left-0 right-0 p-4 bg-gradient-to-t from-black/60 to-transparent">
|
<div class="absolute bottom-0 left-0 right-0 p-4 bg-gradient-to-t from-black/70 to-transparent">
|
||||||
<div class="text-white">
|
<div class="text-white">
|
||||||
<div class="text-2xl font-bold"><%= art.temperature %>°C</div>
|
<div class="flex items-center justify-between">
|
||||||
<div class="text-sm opacity-90"><%= art.weather_date.strftime("%B %d, %Y") %></div>
|
<div class="text-3xl font-bold"><%= art.temperature %>°C</div>
|
||||||
|
<div class="text-right">
|
||||||
|
<div class="text-sm font-semibold">
|
||||||
|
<%= art.weather_date.strftime("%H:%M") %>
|
||||||
|
</div>
|
||||||
|
<div class="text-xs opacity-80">
|
||||||
|
<%= art.weather_date.strftime("%B %d, %Y") %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
</figure>
|
||||||
@ -66,7 +101,7 @@
|
|||||||
<div class="grid grid-cols-2 gap-4 my-4 text-sm">
|
<div class="grid grid-cols-2 gap-4 my-4 text-sm">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 opacity-70" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 opacity-70" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19.5 14.7a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||||
</svg>
|
</svg>
|
||||||
<span>Humidity: <%= art.humidity %>%</span>
|
<span>Humidity: <%= art.humidity %>%</span>
|
||||||
</div>
|
</div>
|
||||||
@ -78,10 +113,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-actions justify-end">
|
<%= link_to city_weather_art_path(@city, art),
|
||||||
<%= link_to "View Details", city_weather_art_path(@city, art),
|
class: "btn btn-primary btn-block" do %>
|
||||||
class: "btn btn-primary btn-outline" %>
|
View Details
|
||||||
</div>
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 ml-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
||||||
|
</svg>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
@ -45,6 +45,9 @@
|
|||||||
gtag('config', 'G-PX1C92V5L7');
|
gtag('config', 'G-PX1C92V5L7');
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-7296634171837358"
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="min-h-screen bg-base-100 font-sans">
|
<body class="min-h-screen bg-base-100 font-sans">
|
||||||
@ -53,7 +56,7 @@
|
|||||||
<div class="container mx-auto">
|
<div class="container mx-auto">
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<%= link_to root_path, class: "text-2xl font-display font-bold hover:text-primary transition-colors" do %>
|
<%= link_to root_path, class: "text-2xl font-display font-bold hover:text-primary transition-colors" do %>
|
||||||
AI Weather Art
|
Today AI Weather
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-none">
|
<div class="flex-none">
|
||||||
|
11
app/views/weather_arts/_weather_stat.html.erb
Normal file
11
app/views/weather_arts/_weather_stat.html.erb
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<!-- app/views/weather_arts/_weather_stat.html.erb -->
|
||||||
|
<div class="stat bg-base-200/50 backdrop-blur-sm rounded-box hover:bg-base-300/50 transition-all duration-300">
|
||||||
|
<div class="flex items-center gap-2 mb-2">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-primary" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="<%= icon %>" />
|
||||||
|
</svg>
|
||||||
|
<div class="stat-title font-medium"><%= title %></div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-value text-2xl"><%= value %></div>
|
||||||
|
<div class="stat-desc mt-1"><%= desc %></div>
|
||||||
|
</div>
|
@ -4,84 +4,152 @@
|
|||||||
</script>
|
</script>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<div class="min-h-screen">
|
<div class="relative min-h-screen bg-base-200">
|
||||||
<!-- 返回导航 -->
|
<!-- 背景图片 -->
|
||||||
<div class="container mx-auto px-4 py-8">
|
<% if @weather_art.image.attached? %>
|
||||||
<%= link_to city_path(@weather_art.city),
|
<div class="fixed inset-0 -z-10">
|
||||||
class: "btn btn-ghost gap-2" do %>
|
<%= image_tag @weather_art.image,
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
class: "absolute w-full h-full object-cover scale-110 filter blur-2xl opacity-25" %>
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
|
<div class="absolute inset-0 bg-gradient-to-b from-base-200/90 to-base-200/70 backdrop-blur-md"></div>
|
||||||
</svg>
|
</div>
|
||||||
Back to <%= @weather_art.city.name %>
|
<% end %>
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 主要内容 -->
|
<!-- 主要内容 -->
|
||||||
<div class="container mx-auto px-4 pb-16">
|
<div class="relative z-10">
|
||||||
<div class="max-w-6xl mx-auto">
|
<!-- 返回导航 -->
|
||||||
<!-- 头部信息 -->
|
<div class="container mx-auto px-4 py-6">
|
||||||
<div class="text-center space-y-4 mb-12">
|
<%= link_to city_path(@weather_art.city),
|
||||||
<h1 class="text-4xl md:text-5xl font-display font-bold">
|
class: "btn btn-ghost btn-lg gap-2 bg-base-100/50 backdrop-blur-sm hover:bg-base-100/70 transition-all duration-300" do %>
|
||||||
<%= @weather_art.city.name %>
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
</h1>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
|
||||||
<p class="text-xl text-base-content/70">
|
</svg>
|
||||||
<%= @weather_art.weather_date.strftime("%B %d, %Y") %>
|
Back to <%= @weather_art.city.name %>
|
||||||
</p>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 主要卡片 -->
|
<div class="container mx-auto px-4 pb-16">
|
||||||
<div class="card lg:card-side bg-base-100 shadow-2xl">
|
<div class="max-w-6xl mx-auto">
|
||||||
<figure class="lg:w-1/2 relative aspect-square lg:aspect-auto">
|
<!-- 头部信息 -->
|
||||||
<% if @weather_art.image.attached? %>
|
<div class="text-center space-y-4 mb-12">
|
||||||
<%= image_tag @weather_art.image,
|
<div class="inline-flex items-center gap-2 text-sm font-medium px-4 py-2 rounded-full bg-base-100/50 backdrop-blur-sm">
|
||||||
class: "w-full h-full object-cover" %>
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<% end %>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
|
||||||
</figure>
|
</svg>
|
||||||
|
<%= @weather_art.city.full_name %>
|
||||||
<div class="card-body lg:w-1/2">
|
|
||||||
<h2 class="card-title font-display text-2xl mb-6">
|
|
||||||
<%= @weather_art.description %>
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<!-- 天气数据网格 -->
|
|
||||||
<div class="grid grid-cols-2 gap-6">
|
|
||||||
<div class="stat bg-base-200 rounded-box">
|
|
||||||
<div class="stat-title">Temperature</div>
|
|
||||||
<div class="stat-value"><%= @weather_art.temperature %>°C</div>
|
|
||||||
<div class="stat-desc">Feels like <%= @weather_art.feeling_temp %>°C</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="stat bg-base-200 rounded-box">
|
|
||||||
<div class="stat-title">Wind</div>
|
|
||||||
<div class="stat-value"><%= @weather_art.wind_scale %></div>
|
|
||||||
<div class="stat-desc"><%= @weather_art.wind_speed %> km/h</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="stat bg-base-200 rounded-box">
|
|
||||||
<div class="stat-title">Humidity</div>
|
|
||||||
<div class="stat-value"><%= @weather_art.humidity %>%</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="stat bg-base-200 rounded-box">
|
|
||||||
<div class="stat-title">Visibility</div>
|
|
||||||
<div class="stat-value"><%= @weather_art.visibility %> km</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="stat bg-base-200 rounded-box">
|
|
||||||
<div class="stat-title">Pressure</div>
|
|
||||||
<div class="stat-value"><%= @weather_art.pressure %> hPa</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="stat bg-base-200 rounded-box">
|
|
||||||
<div class="stat-title">Cloud Cover</div>
|
|
||||||
<div class="stat-value"><%= @weather_art.cloud %>%</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- AI Prompt -->
|
<h1 class="text-4xl md:text-6xl font-display font-bold">
|
||||||
<div class="mt-8 bg-base-200 p-6 rounded-box">
|
<span class="bg-gradient-to-r from-primary to-secondary bg-clip-text text-transparent">
|
||||||
<h3 class="font-display font-bold text-lg mb-3">AI Prompt</h3>
|
Weather Art
|
||||||
<p class="text-base-content/70"><%= @weather_art.prompt %></p>
|
</span>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<div class="flex flex-wrap justify-center items-center gap-3">
|
||||||
|
<div class="badge badge-lg badge-primary gap-2">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
||||||
|
</svg>
|
||||||
|
<%= @weather_art.weather_date.strftime("%B %d, %Y") %>
|
||||||
|
</div>
|
||||||
|
<div class="badge badge-lg badge-secondary gap-2">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
|
</svg>
|
||||||
|
<%= @weather_art.weather_date.strftime("%H:%M") %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 主要卡片 -->
|
||||||
|
<div class="card lg:card-side bg-base-100/80 backdrop-blur-md shadow-2xl">
|
||||||
|
<figure class="lg:w-1/2 relative aspect-square lg:aspect-auto group">
|
||||||
|
<% if @weather_art.image.attached? %>
|
||||||
|
<%= image_tag @weather_art.image,
|
||||||
|
class: "w-full h-full object-cover transition-transform duration-500 group-hover:scale-105" %>
|
||||||
|
<div class="absolute inset-0 bg-gradient-to-t from-base-100/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||||
|
<% end %>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
<div class="card-body lg:w-1/2">
|
||||||
|
<div class="prose max-w-none mb-8">
|
||||||
|
<h2 class="card-title font-display text-3xl mb-4 flex items-center gap-3">
|
||||||
|
<%= weather_description_icon(@weather_art.description) %>
|
||||||
|
<%= @weather_art.description %>
|
||||||
|
</h2>
|
||||||
|
<div class="divider"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 天气数据网格 -->
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
<div class="stat bg-base-200/50 backdrop-blur-sm rounded-box hover:bg-base-300/50 transition-all duration-300">
|
||||||
|
<div class="flex items-center gap-2 mb-2">
|
||||||
|
<%= weather_stat_icon("temperature") %>
|
||||||
|
<div class="stat-title font-medium">Temperature</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-value text-2xl"><%= @weather_art.temperature %>°C</div>
|
||||||
|
<div class="stat-desc mt-1">Feels like <%= @weather_art.feeling_temp %>°C</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat bg-base-200/50 backdrop-blur-sm rounded-box hover:bg-base-300/50 transition-all duration-300">
|
||||||
|
<div class="flex items-center gap-2 mb-2">
|
||||||
|
<%= weather_stat_icon("wind") %>
|
||||||
|
<div class="stat-title font-medium">Wind</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-value text-2xl"><%= @weather_art.wind_scale %></div>
|
||||||
|
<div class="stat-desc mt-1"><%= @weather_art.wind_speed %> km/h</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat bg-base-200/50 backdrop-blur-sm rounded-box hover:bg-base-300/50 transition-all duration-300">
|
||||||
|
<div class="flex items-center gap-2 mb-2">
|
||||||
|
<%= weather_stat_icon("humidity") %>
|
||||||
|
<div class="stat-title font-medium">Humidity</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-value text-2xl"><%= @weather_art.humidity %>%</div>
|
||||||
|
<div class="stat-desc mt-1">Relative humidity</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat bg-base-200/50 backdrop-blur-sm rounded-box hover:bg-base-300/50 transition-all duration-300">
|
||||||
|
<div class="flex items-center gap-2 mb-2">
|
||||||
|
<%= weather_stat_icon("visibility") %>
|
||||||
|
<div class="stat-title font-medium">Visibility</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-value text-2xl"><%= @weather_art.visibility %> km</div>
|
||||||
|
<div class="stat-desc mt-1">Clear view distance</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat bg-base-200/50 backdrop-blur-sm rounded-box hover:bg-base-300/50 transition-all duration-300">
|
||||||
|
<div class="flex items-center gap-2 mb-2">
|
||||||
|
<%= weather_stat_icon("pressure") %>
|
||||||
|
<div class="stat-title font-medium">Pressure</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-value text-2xl"><%= @weather_art.pressure %> hPa</div>
|
||||||
|
<div class="stat-desc mt-1">Atmospheric pressure</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat bg-base-200/50 backdrop-blur-sm rounded-box hover:bg-base-300/50 transition-all duration-300">
|
||||||
|
<div class="flex items-center gap-2 mb-2">
|
||||||
|
<%= weather_stat_icon("cloud") %>
|
||||||
|
<div class="stat-title font-medium">Cloud Cover</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-value text-2xl"><%= @weather_art.cloud %>%</div>
|
||||||
|
<div class="stat-desc mt-1">Sky coverage</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- AI Prompt -->
|
||||||
|
<div class="mt-8">
|
||||||
|
<div class="bg-base-200/50 backdrop-blur-sm p-6 rounded-box border border-base-300">
|
||||||
|
<div class="flex items-center gap-3 mb-4">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-primary" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
|
||||||
|
</svg>
|
||||||
|
<h3 class="font-display font-bold text-lg">AI Prompt</h3>
|
||||||
|
</div>
|
||||||
|
<p class="text-base-content/70 leading-relaxed">
|
||||||
|
<%= @weather_art.prompt %>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
class BatchGenerateWeatherArtsWorker
|
class BatchGenerateWeatherArtsWorker
|
||||||
include Sidekiq::Worker
|
include Sidekiq::Worker
|
||||||
|
|
||||||
GENERATION_INTERVAL = 6.hours
|
GENERATION_INTERVAL = 24.hours
|
||||||
MAX_DURATION = 50.minutes
|
MAX_DURATION = 50.minutes
|
||||||
SLEEP_DURATION = 3.seconds
|
SLEEP_DURATION = 120.seconds
|
||||||
|
|
||||||
def perform(*args)
|
def perform(*args)
|
||||||
start_time = Time.current
|
start_time = Time.current
|
||||||
|
21
config/initializers/schedule_tasks.rb
Normal file
21
config/initializers/schedule_tasks.rb
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# config/initializers/schedule_tasks.rb
|
||||||
|
Rails.application.config.after_initialize do
|
||||||
|
if Rails.env.production? && !ENV["RAILS_BUILD"]
|
||||||
|
begin
|
||||||
|
redis_key = "startup_task_running"
|
||||||
|
unless Sidekiq.redis { |conn| conn.get(redis_key) }
|
||||||
|
Sidekiq.redis do |conn|
|
||||||
|
conn.setex(redis_key, 1.hour.to_i, "1")
|
||||||
|
end
|
||||||
|
|
||||||
|
RefreshSitemapWorker.perform_async
|
||||||
|
|
||||||
|
Rails.logger.info "Startup task (RefreshSitemapWorker) scheduled successfully"
|
||||||
|
end
|
||||||
|
rescue => e
|
||||||
|
Rails.logger.error "Error scheduling startup task: #{e.message}"
|
||||||
|
ensure
|
||||||
|
Sidekiq.redis { |conn| conn.del(redis_key) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -80,7 +80,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Xi'an",
|
name: "Xi'an",
|
||||||
@ -89,7 +89,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Hangzhou',
|
name: 'Hangzhou',
|
||||||
@ -98,7 +98,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Foshan',
|
name: 'Foshan',
|
||||||
@ -107,7 +107,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Nanjing',
|
name: 'Nanjing',
|
||||||
@ -116,7 +116,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Hong Kong',
|
name: 'Hong Kong',
|
||||||
@ -125,7 +125,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Hong_Kong',
|
timezone: 'Asia/Hong_Kong',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Shenyang',
|
name: 'Shenyang',
|
||||||
@ -134,7 +134,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Zhengzhou',
|
name: 'Zhengzhou',
|
||||||
@ -143,7 +143,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Qingdao',
|
name: 'Qingdao',
|
||||||
@ -152,7 +152,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Suzhou',
|
name: 'Suzhou',
|
||||||
@ -161,7 +161,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Changsha',
|
name: 'Changsha',
|
||||||
@ -170,7 +170,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Jinan',
|
name: 'Jinan',
|
||||||
@ -179,7 +179,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Kunming',
|
name: 'Kunming',
|
||||||
@ -188,7 +188,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Harbin',
|
name: 'Harbin',
|
||||||
@ -197,7 +197,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Shijiazhuang',
|
name: 'Shijiazhuang',
|
||||||
@ -206,7 +206,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Hefei',
|
name: 'Hefei',
|
||||||
@ -215,7 +215,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Dalian',
|
name: 'Dalian',
|
||||||
@ -224,7 +224,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Xiamen',
|
name: 'Xiamen',
|
||||||
@ -233,7 +233,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Nanning',
|
name: 'Nanning',
|
||||||
@ -242,7 +242,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Changchun',
|
name: 'Changchun',
|
||||||
@ -251,7 +251,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Taiyuan',
|
name: 'Taiyuan',
|
||||||
@ -260,7 +260,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'New Taipei City',
|
name: 'New Taipei City',
|
||||||
@ -269,7 +269,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Taipei',
|
timezone: 'Asia/Taipei',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Guiyang',
|
name: 'Guiyang',
|
||||||
@ -278,7 +278,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Wuxi',
|
name: 'Wuxi',
|
||||||
@ -287,7 +287,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Shantou',
|
name: 'Shantou',
|
||||||
@ -296,7 +296,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Ürümqi',
|
name: 'Ürümqi',
|
||||||
@ -305,7 +305,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Zhongshan',
|
name: 'Zhongshan',
|
||||||
@ -314,7 +314,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Ningbo',
|
name: 'Ningbo',
|
||||||
@ -323,7 +323,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Fuzhou',
|
name: 'Fuzhou',
|
||||||
@ -332,7 +332,7 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Nanchang',
|
name: 'Nanchang',
|
||||||
@ -341,6 +341,6 @@ City.create!([
|
|||||||
country: china,
|
country: china,
|
||||||
timezone: 'Asia/Shanghai',
|
timezone: 'Asia/Shanghai',
|
||||||
active: true,
|
active: true,
|
||||||
priority: 100,
|
priority: 100
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
"@hotwired/stimulus": "^3.2.2",
|
"@hotwired/stimulus": "^3.2.2",
|
||||||
"@hotwired/turbo-rails": "^8.0.12",
|
"@hotwired/turbo-rails": "^8.0.12",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
|
"jquery": "^3.7.1",
|
||||||
|
"jquery-ui": "^1.14.1",
|
||||||
"postcss": "^8.5.1",
|
"postcss": "^8.5.1",
|
||||||
"sass": "^1.83.4",
|
"sass": "^1.83.4",
|
||||||
"tailwindcss": "^3.4.17"
|
"tailwindcss": "^3.4.17"
|
||||||
|
1
public/ads.txt
Normal file
1
public/ads.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
google.com, pub-7296634171837358, DIRECT, f08c47fec0942fa0
|
@ -729,12 +729,19 @@ jquery-ui@^1.13.3:
|
|||||||
dependencies:
|
dependencies:
|
||||||
jquery ">=1.12.0 <5.0.0"
|
jquery ">=1.12.0 <5.0.0"
|
||||||
|
|
||||||
|
jquery-ui@^1.14.1:
|
||||||
|
version "1.14.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/jquery-ui/-/jquery-ui-1.14.1.tgz#ba342ea3ffff662b787595391f607d923313e040"
|
||||||
|
integrity sha512-DhzsYH8VeIvOaxwi+B/2BCsFFT5EGjShdzOcm5DssWjtcpGWIMsn66rJciDA6jBruzNiLf1q0KvwMoX1uGNvnQ==
|
||||||
|
dependencies:
|
||||||
|
jquery ">=1.12.0 <5.0.0"
|
||||||
|
|
||||||
jquery-ujs@^1.2.2:
|
jquery-ujs@^1.2.2:
|
||||||
version "1.2.3"
|
version "1.2.3"
|
||||||
resolved "https://registry.npmjs.org/jquery-ujs/-/jquery-ujs-1.2.3.tgz"
|
resolved "https://registry.npmjs.org/jquery-ujs/-/jquery-ujs-1.2.3.tgz"
|
||||||
integrity sha512-59wvfx5vcCTHMeQT1/OwFiAj+UffLIwjRIoXdpO7Z7BCFGepzq9T9oLVeoItjTqjoXfUrHJvV7QU6pUR+UzOoA==
|
integrity sha512-59wvfx5vcCTHMeQT1/OwFiAj+UffLIwjRIoXdpO7Z7BCFGepzq9T9oLVeoItjTqjoXfUrHJvV7QU6pUR+UzOoA==
|
||||||
|
|
||||||
"jquery@>=1.12.0 <5.0.0", jquery@^3.4.1:
|
"jquery@>=1.12.0 <5.0.0", jquery@^3.4.1, jquery@^3.7.1:
|
||||||
version "3.7.1"
|
version "3.7.1"
|
||||||
resolved "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz"
|
resolved "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz"
|
||||||
integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==
|
integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==
|
||||||
|
Loading…
Reference in New Issue
Block a user