这是 gemini 3.1 pro 网页端生成的。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>极简天气 H5</title>
<script src="
https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="
https://cdn.tailwindcss.com"></script>
<style>
/* 隐藏滚动条但保留滚动功能 */
.no-scrollbar::-webkit-scrollbar {
display: none;
}
.no-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
}
</style>
</head>
<body class="bg-gradient-to-br from-blue-100 to-blue-300 min-h-screen flex items-center justify-center p-4">
<div id="app" class="bg-white/80 backdrop-blur-md rounded-3xl shadow-xl w-full max-w-sm p-6 overflow-hidden">
<div class="relative mb-6">
<input
v-model="searchCity"
@
keyup.enter="getWeather"
type="text"
placeholder="输入城市名称,如:北京"
class="w-full bg-white/90 px-4 py-3 rounded-xl shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-400 transition-all text-gray-700"
>
<button
@
click="getWeather"
class="absolute right-2 top-2 bottom-2 bg-blue-500 hover:bg-blue-600 text-white px-4 rounded-lg transition-colors font-medium"
>
查询
</button>
</div>
<div v-if="loading" class="text-center py-10">
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500 mx-auto"></div>
<p class="text-gray-500 mt-3 text-sm">正在获取天气数据...</p>
</div>
<div v-else-if="errorMessage" class="text-center py-8 text-red-500 bg-red-50 rounded-xl">
{{ errorMessage }}
</div>
<div v-else-if="weatherData" class="fade-in">
<div class="text-center mb-6">
<h2 class="text-3xl font-bold text-gray-800 tracking-wider">{{ weatherData.city }}</h2>
<p class="text-gray-500 mt-1">{{
weatherData.date }}</p>
</div>
<div class="flex items-center justify-center mb-6">
<span class="text-6xl mr-4">{{ weatherData.icon }}</span>
<div>
<div class="text-5xl font-black text-gray-800">{{ weatherData.temp }}°C</div>
<div class="text-xl text-gray-600 mt-1 font-medium">{{ weatherData.description }}</div>
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<div class="bg-white/60 p-3 rounded-xl flex items-center">
<span class="text-2xl mr-2">💧</span>
<div>
<div class="text-xs text-gray-500">湿度</div>
<div class="font-bold text-gray-700">{{ weatherData.humidity }}%</div>
</div>
</div>
<div class="bg-white/60 p-3 rounded-xl flex items-center">
<span class="text-2xl mr-2">💨</span>
<div>
<div class="text-xs text-gray-500">风速</div>
<div class="font-bold text-gray-700">{{ weatherData.windSpeed }} km/h</div>
</div>
</div>
<div class="bg-white/60 p-3 rounded-xl flex items-center">
<span class="text-2xl mr-2">🌡️</span>
<div>
<div class="text-xs text-gray-500">体感温度</div>
<div class="font-bold text-gray-700">{{ weatherData.feelsLike }}°C</div>
</div>
</div>
<div class="bg-white/60 p-3 rounded-xl flex items-center">
<span class="text-2xl mr-2">👁️</span>
<div>
<div class="text-xs text-gray-500">能见度</div>
<div class="font-bold text-gray-700">{{ weatherData.visibility }} km</div>
</div>
</div>
</div>
</div>
<div v-else class="text-center py-12 opacity-50">
<span class="text-6xl block mb-4">🌍</span>
<p class="text-gray-500">搜索你关心的城市天气</p>
</div>
</div>
<script>
const { createApp, ref, onMounted } = Vue;
createApp({
setup() {
const searchCity = ref('');
const weatherData = ref(null);
const loading = ref(false);
const errorMessage = ref('');
// 模拟天气数据映射(用于演示)
const mockIcons = { '晴': '☀️', '多云': '⛅', '阴': '☁️', '雨': '🌧️', '雪': '❄️' };
const getWeather = async () => {
if (!searchCity.value.trim()) return;
loading.value = true;
errorMessage.value = '';
weatherData.value = null;
try {
// [开发建议]
// 此处应替换为真实的接口请求,例如和风天气 (QWeather) 或 OpenWeatherMap
// const API_KEY = 'your_api_key';
// const response = await fetch(`
https://devapi.qweather.com/v7/weather/now?location=${searchCity.value}&key=${API_KEY}`);
// const data = await response.json();
// 模拟 API 延迟
await new Promise(resolve => setTimeout(resolve, 800));
// 模拟数据结构拦截与拼装
if (searchCity.value.length > 10) {
throw new Error('未找到该城市信息');
}
const randomTemp = Math.floor(Math.random() * 30) + 5;
const descriptions = ['晴', '多云', '雨', '阴'];
const desc = descriptions[Math.floor(Math.random() * descriptions.length)];
weatherData.value = {
city: searchCity.value,
date: new Date().toLocaleDateString('zh-CN', { month: 'long', day: 'numeric', weekday: 'long' }),
temp: randomTemp,
feelsLike: randomTemp + (Math.floor(Math.random() * 4) - 2),
description: desc,
icon: mockIcons[desc],
humidity: Math.floor(Math.random() * 50) + 30,
windSpeed: Math.floor(Math.random() * 20) + 5,
visibility: Math.floor(Math.random() * 10) + 5
};
} catch (error) {
errorMessage.value = error.message || '获取天气信息失败,请稍后重试';
} finally {
loading.value = false;
}
};
// 初始加载默认城市
onMounted(() => {
searchCity.value = '北京';
getWeather();
});
return {
searchCity,
weatherData,
loading,
errorMessage,
getWeather
};
}
}).mount('#app');
</script>
</body>
</html>