Merge branch 'main' of http://113.45.67.59:3003/qiuchenfan/test
This commit is contained in:
commit
dea7e9349b
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { WeathersearchForm } from "./WeatherSearchForm.tsx";
|
||||||
|
import { WeatherDisplay } from "./WeatherDisplay.tsx";
|
||||||
|
import { WeatherDetailsGrid } from "./WeatherDetailsGrid.tsx";
|
||||||
|
import { useWeatherStore } from "./WeatherStore.tsx";
|
||||||
|
import Cloud from "../../../assets/cloud.svg";
|
||||||
|
|
||||||
|
export function WeatherCard() {
|
||||||
|
const { currentWeather } = useWeatherStore();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<WeathersearchForm />
|
||||||
|
{currentWeather ? (
|
||||||
|
<div className="P-4">
|
||||||
|
<WeatherDisplay />
|
||||||
|
<WeatherDetailsGrid />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="flex flex-col items-center justify-center h-full">
|
||||||
|
<div className="animate-spin">
|
||||||
|
<div className="h-10 w-10 border-t-2 border-b-2 border-gray-900 rounded-full"></div>
|
||||||
|
<div className="h-10 w-10">
|
||||||
|
<Cloud/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h3 className="text-2xl font-bold text-slate-700 dark:text-slate-200 mb-2">暂无天气数据</h3>
|
||||||
|
<p className="text-sm text-slate-500 dark:text-slate-400">请搜索城市查看实时天气信息</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
import { Droplets,Wind,Gauge,Cloud,Eye,ThermometerSun} from "lucide-react";
|
||||||
|
import React from "react";
|
||||||
|
import { getWindDirection } from "@/lib/utils";
|
||||||
|
import {useWeatherStore} from "@/store/weatherStore";
|
||||||
|
|
||||||
|
interface WeatherInfoItemProps {
|
||||||
|
icon: React.ReactNode;
|
||||||
|
label: string;
|
||||||
|
value: string;
|
||||||
|
subtitle?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function WeatherInfoItem({ icon, label, value, subtitle }: WeatherInfoItemProps) {
|
||||||
|
return (
|
||||||
|
<div className="group rounded-xl bg-slate-50/50 border border-slate-200/50 p-3 hover:bg-slate-100/50 hover:border-slate-300 transition duration-200 ">
|
||||||
|
<div className="flex items-start gap-2">
|
||||||
|
<div className="flex-shrink-0 w-9 h-9 rounded-full bg-white flex items-center justify-center group-hover:scale-100 transition-transform duration-200">{icon}</div>
|
||||||
|
<div className="flex-1 min-w-0">
|
||||||
|
<p className="text-xs text-slate-500">{label}</p>
|
||||||
|
<p className="text-sm font-semibold text-slate-900">{value}</p>
|
||||||
|
{subtitle && <p className="text-xs text-slate-500">{subtitle}</p>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function WeatherDetailsGrid() {
|
||||||
|
|
||||||
|
<>
|
||||||
|
<div className="grid grids-cols-2 md:grids-cols-3 gap-3 mb-4">
|
||||||
|
<WeatherInfoItem
|
||||||
|
icon={<Droplets className="w-4 h-4 text-blue-500"/>}
|
||||||
|
label="湿度"
|
||||||
|
value={'${currentWeather.current.humidity}%'}/>
|
||||||
|
|
||||||
|
<WeatherInfoItem
|
||||||
|
icon={<Wind className="w-4 h-4 text-green-500"/>}
|
||||||
|
label="风速"
|
||||||
|
value={'${currentWeather.current.wind_speed}%'}
|
||||||
|
subtitle={getWindDirection(currentWeather.current.wind_dir)}/>
|
||||||
|
|
||||||
|
<WeatherInfoItem
|
||||||
|
icon={<Gauge className="w-4 h-4 text-purple-500"/>}
|
||||||
|
label="气压"
|
||||||
|
value={'${currentWeather.current.humidity}%'}/>
|
||||||
|
|
||||||
|
|
||||||
|
<WeatherInfoItem
|
||||||
|
icon={<Cloud className="w-4 h-4 text-gray-500"/>}
|
||||||
|
label="云量"
|
||||||
|
value={'${currentWeather.current.cloudcover}%'}/>
|
||||||
|
|
||||||
|
|
||||||
|
<WeatherInfoItem
|
||||||
|
icon={<ThermometerSun className="w-4 h-4 text-orange-500"/>}
|
||||||
|
label="紫外线"
|
||||||
|
value={'${currentWeather.current.uv_index}%'}/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="pt-4 border-t border-slate-200">
|
||||||
|
<div className="flex items-center justify-center text-sm mb-2">
|
||||||
|
<div className="flex items-center gap-2 text-slate-600">
|
||||||
|
<Droplets className="w-4 h-4 text-blue-500"/>
|
||||||
|
<span>降水量:<span className="font-semibold">{currentWeather.current.precip}mm</span></span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<span className="text-xs text-center text-slate-500">{currentWeather.current.is_day==="yes"?'白天':'夜晚'}</span>
|
||||||
|
</div>
|
||||||
|
<p>观测时间:{currentWeather.current.observation_time}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
import REACT, { use, useEffect } from 'react'
|
||||||
|
import { Loader2 } from 'lucide-react';
|
||||||
|
import { WeatherCard } from './WeatherCard'
|
||||||
|
import { useWeatherstore } from './WeatherStore'
|
||||||
|
import { toast } from 'sonner'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export function meta() {
|
||||||
|
return [
|
||||||
|
{ title: "天气查询页面" },
|
||||||
|
{ name: "description", content: "查询天气信息" }
|
||||||
|
]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Weather() {
|
||||||
|
const { currentWeather, isLoading, error, seterror } = useWeatherstore()
|
||||||
|
useEffect(() => {
|
||||||
|
if (error) {
|
||||||
|
toast.error(error)
|
||||||
|
seterror("")
|
||||||
|
}
|
||||||
|
}, [error, seterror])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col items-center justify-center h-screen">
|
||||||
|
<div className="flex flex-col items-center justify-center">
|
||||||
|
<header className="flex flex-col items-center justify-center">
|
||||||
|
<h1 className="text-4xl font-bold">天气查询</h1>
|
||||||
|
<p className="text-sm">实时天气</p>
|
||||||
|
</header>
|
||||||
|
{isLoading && !currentWeather && (
|
||||||
|
<div className="flex flex-col items-center justify-center">
|
||||||
|
<div className="flex flex-col items-center justify-center">
|
||||||
|
<div className='flex flex-col items-center justify-center'>
|
||||||
|
<div className="animate-spin rounded-full h-20 w-20 border-t-2 border-b-2 border-gray-900">
|
||||||
|
</div>
|
||||||
|
<div className="text-gray-900 text-lg font-bold">
|
||||||
|
<Loader2 className="h-10 w-10 animate-spin" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-900 text-lg font-bold"> 加载中...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!isLoading || currentWeather ? (
|
||||||
|
<div className="flex flex-col items-center justify-center">
|
||||||
|
<WeatherCard />
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue