From d931e8ffdbafe5f55e0a7eeebfe6f9b0fb4be32e Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 22 Oct 2025 16:24:53 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=A4=A9=E6=B0=94=E5=8D=A1=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/CommunityPage.vue | 297 +++++++++++++++++- 1 file changed, 292 insertions(+), 5 deletions(-) diff --git a/src/oc-community-frontend/src/components/CommunityPage.vue b/src/oc-community-frontend/src/components/CommunityPage.vue index 30800aa..aceb635 100644 --- a/src/oc-community-frontend/src/components/CommunityPage.vue +++ b/src/oc-community-frontend/src/components/CommunityPage.vue @@ -8,9 +8,42 @@
- 社区背景 +
+ +
+
+
+ +
+ + + +
+ +
{{ weatherInfo.temperature }}°C
+
{{ weatherInfo.condition }}
+
{{ weatherInfo.province }}{{ weatherInfo.city !== weatherInfo.province ? weatherInfo.city : '' }}
+
+ 湿度: {{ weatherInfo.humidity }}% + 风速: {{ weatherInfo.windSpeed }}级 +
+
+
+
- +
{ + return { + imageUrl: '/photo/map1.png', + coordinates: + locationCoords + } +} + +//更新天气函数 +const updateWeather = async () => { + if (inputLocation.value.trim()) { + weatherLoading.value = true + currentLocation.value = inputLocation.value.trim() + try { + const weatherData = await getWeatherData(currentLocation.value) + weatherInfo.value = weatherData + } catch (error) { + console.error('更新天气失败:', error) + } finally { + weatherLoading.value = false + } + } +} + +const getWeatherData = async (location) => { + try { + const API_KEY = '7d1e2dfdd86a45c64e4178c0ad321fcd' + + // 第一步:通过地理编码API获取城市编码 + const geoResponse = await fetch(`https://restapi.amap.com/v3/geocode/geo?address=${encodeURIComponent(location)}&key=${API_KEY}`) + const geoData = await geoResponse.json() + + if (geoData.status !== '1' || !geoData.geocodes || geoData.geocodes.length === 0) { + throw new Error(`找不到地点: ${location}`) + } + + // 获取第一个匹配的城市编码 + const adcode = geoData.geocodes[0].adcode + + // 第二步:使用城市编码获取天气 + const weatherResponse = await fetch(`https://restapi.amap.com/v3/weather/weatherInfo?city=${adcode}&key=${API_KEY}&extensions=base`) + const weatherData = await weatherResponse.json() + + if (weatherData.status === '1' && weatherData.lives && weatherData.lives.length > 0) { + const live = weatherData.lives[0] + + return { + temperature: live.temperature, + condition: live.weather, + humidity: live.humidity, + windSpeed: live.windpower, + windDir: live.winddirection, + reportTime: live.reporttime, + province: live.province, + city: live.city + } + } else { + throw new Error('获取天气数据失败') + } + } catch (error) { + console.error('获取真实天气失败:', error) + return getMockWeatherData(location) + } +} + +// 添加模拟数据作为后备函数 +const getMockWeatherData = (location) => { + // 生成随机的天气数据 + const conditions = ['晴', '多云', '阴', '小雨', '中雨', '大雨', '阵雨', '雷阵雨', '雪', '雾', '霾'] + const randomCondition = conditions[Math.floor(Math.random() * conditions.length)] + + // 根据季节生成合理温度 + const now = new Date() + const month = now.getMonth() + 1 + let baseTemp = 20 + + if (month >= 3 && month <= 5) baseTemp = 18 // 春季 + else if (month >= 6 && month <= 8) baseTemp = 28 // 夏季 + else if (month >= 9 && month <= 11) baseTemp = 15 // 秋季 + else baseTemp = 5 // 冬季 + + const temperature = baseTemp + Math.floor(Math.random() * 15) - 5 + + return { + temperature: temperature, + condition: randomCondition, + humidity: 30 + Math.floor(Math.random() * 50), + windSpeed: (1 + Math.random() * 6).toFixed(1), + province: '未知省份', + city: location + } +} + // 默认头像 const defaultAvatar = 'https://i.pravatar.cc/100?img=1' @@ -121,6 +251,10 @@ const locationCoords = { '宠物店': { x: 35, y: 75 } } +const currentMap = ref('') +const weatherInfo = ref(null) +const weatherLoading = ref(false) + // 计算OC当前位置(基于其 schedule) const ocPositions = ref([]) // 每个地点的实时状态(位置、在场人数、对应 oc 列表) @@ -166,6 +300,7 @@ onMounted(() => { computePositions() posTimer = setInterval(computePositions, 60 * 1000) document.addEventListener('click', closePopoverOnClickOutside) + initMapAndWeather() }) onUnmounted(() => { if (posTimer) clearInterval(posTimer) @@ -224,6 +359,27 @@ const closePopoverOnClickOutside = (event) => { closeLocationPopover() } } + +const initMapAndWeather = async () => { + try { + // 获取地图(始终使用本地图片) + const mapData = await getRealMap(currentLocation.value) + currentMap +.value = mapData. +imageUrl + + // 获取天气信息 + const weatherData = await getWeatherData(currentLocation.value) + weatherInfo +.value = + weatherData + } catch (error) { + console +.error('初始化天气失败:', error) + currentMap +.value = '/photo/map1.png' + } +} \ No newline at end of file From 2fad89a507bfd73a648c2336091862c30beb0981 Mon Sep 17 00:00:00 2001 From: psnci6hgk <1747918662@qq.com> Date: Wed, 5 Nov 2025 16:54:12 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=A4=A9=E6=B0=94=E5=8D=A1=E7=89=87?= =?UTF-8?q?=E6=8B=89=E5=8F=96=E6=88=90=E5=8A=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/CommunityPage.vue | 120 +++++++++++++++++- 1 file changed, 116 insertions(+), 4 deletions(-) diff --git a/src/oc-community-frontend/src/components/CommunityPage.vue b/src/oc-community-frontend/src/components/CommunityPage.vue index 57a1bf6..de5b7e3 100644 --- a/src/oc-community-frontend/src/components/CommunityPage.vue +++ b/src/oc-community-frontend/src/components/CommunityPage.vue @@ -9,6 +9,8 @@
+ +
@@ -261,6 +263,18 @@ const currentMap = ref('') const weatherInfo = ref(null) const weatherLoading = ref(false) +// 根据 weatherInfo.condition 映射到 CSS 类名 +const weatherClass = computed(() => { + if (!weatherInfo.value || !weatherInfo.value.condition) return '' + const c = String(weatherInfo.value.condition).toLowerCase() + if (/晴|clear|sunny/.test(c)) return 'wb-sunny' + if (/云|clouds|cloud/.test(c)) return 'wb-cloudy' + if (/雨|drizzle|rain|雷|thunder/.test(c)) return 'wb-rain' + if (/雪|snow/.test(c)) return 'wb-snow' + if (/雾|霾|fog|haze|mist|smoke|dust/.test(c)) return 'wb-haze' + return 'wb-default' +}) + // 计算OC当前位置(基于其 schedule) const ocPositions = ref([]) // 每个地点的实时状态(位置、在场人数、对应 oc 列表) @@ -936,16 +950,16 @@ imageUrl /* 天气组件样式 */ .weather-widget { position: absolute; - top: 20px; - right: 20px; + top: 0px; + right: 0px; background: rgba(255, 255, 255, 0.95); backdrop-filter: blur(10px); border-radius: 12px; padding: 10px; /* 减少内边距 */ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); z-index: 30; - min-width: 120px; /* 减小最小宽度 */ - max-width: 140px; /* 添加最大宽度限制 */ + min-width: 50px; /* 减小最小宽度 */ + max-width: 120px; /* 添加最大宽度限制 */ } .weather-content { @@ -1017,4 +1031,102 @@ imageUrl display: block; line-height: 1.2; } + +/* 天气覆盖层样式 */ +.weather-overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 2; /* 位于背景(map)之上、地点图标之下(地点图标 z-index:10) */ + pointer-events: none; + transition: opacity 0.6s ease; +} + +/* 晴天:暖色渐变 + 太阳光环 */ +.weather-overlay.wb-sunny { + background: linear-gradient(180deg, rgba(255,240,160,0.12), rgba(255,210,120,0.05)); +} +.weather-overlay.wb-sunny::before { + content: ""; + position: absolute; + right: 8%; + top: 8%; + width: 160px; + height: 160px; + background: radial-gradient(circle at 30% 30%, rgba(255,245,200,0.9) 0%, rgba(255,220,120,0.6) 30%, rgba(255,200,80,0.15) 60%, transparent 70%); + border-radius: 50%; + filter: blur(12px); + transform: translateZ(0); + animation: sunSlowRotate 12s linear infinite; +} + +@keyframes sunSlowRotate { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} + +/* 多云:灰白云层覆盖(使用伪元素叠加多个模糊圆形) */ +.weather-overlay.wb-cloudy { + background: linear-gradient(180deg, rgba(200,210,220,0.06), rgba(160,170,180,0.06)); +} +.weather-overlay.wb-cloudy::before, +.weather-overlay.wb-cloudy::after { + content: ""; + position: absolute; + left: 10%; + top: 5%; + width: 420px; + height: 120px; + background: radial-gradient(ellipse at center, rgba(255,255,255,0.85) 0%, rgba(240,240,240,0.9) 35%, rgba(220,220,220,0.95) 60%, rgba(200,200,200,0.95) 100%); + border-radius: 50%; + filter: blur(18px); + transform: translateX(0); + animation: cloudFloat 18s linear infinite; +} +.weather-overlay.wb-cloudy::after { + left: 48%; + top: 18%; + width: 360px; + height: 110px; + animation-duration: 22s; +} + +@keyframes cloudFloat { + 0% { transform: translateX(-6%); } + 50% { transform: translateX(6%); } + 100% { transform: translateX(-6%); } +} + +/* 雨天:深色背景 + 动态雨线(用重复渐变模拟雨丝) */ +.weather-overlay.wb-rain { + background: linear-gradient(180deg, rgba(30,40,50,0.18), rgba(20,25,30,0.2)); +} +.weather-overlay.wb-rain::before { + content: ""; + position: absolute; + inset: 0; + background-image: linear-gradient(transparent 70%, rgba(255,255,255,0.06) 70%); + background-size: 4px 40px; + opacity: 0.9; + animation: rainFall 0.8s linear infinite; + mix-blend-mode: screen; +} + +@keyframes rainFall { + from { background-position: 0 -10px; } + to { background-position: 0 40px; } +} + +/* 霾/雾:浅灰覆盖 + 模糊 */ +.weather-overlay.wb-haze { + background: rgba(200,200,200,0.25); + backdrop-filter: blur(4px) saturate(0.9); +} + +/* 默认轻微蒙层 */ +.weather-overlay.wb-default { + background: rgba(0,0,0,0.02); +} \ No newline at end of file