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