Compare commits
4
Commits
0046b3a87f
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6979104b6 | ||
|
|
8e9663350d | ||
|
|
f12974b4a2 | ||
|
|
3d641c87f4 |
+11
-4
@@ -48,8 +48,9 @@ const showHero = computed(
|
|||||||
<layout v-if="isLogin" :layoutData="layoutData" />
|
<layout v-if="isLogin" :layoutData="layoutData" />
|
||||||
<div v-if="isLogin" class="base-wrap-main alone-page">
|
<div v-if="isLogin" class="base-wrap-main alone-page">
|
||||||
<div class="main-wrapper">
|
<div class="main-wrapper">
|
||||||
<!-- 方案D · 蓝天校园:hero 刊头(首页/全校列表)+ 栏目条 + 页面内容 -->
|
<!-- 方案D · 蓝天校园:hero 刊头(首页/全校列表)+ 栏目条 + 页面内容;
|
||||||
<div class="app-frame">
|
no-hero:无刊头页由 body 顶部留白让出固定顶栏,刊头页靠 hero 负 margin 压入顶栏玻璃之下 -->
|
||||||
|
<div class="app-frame" :class="{ 'no-hero': !showHero }">
|
||||||
<HomeHero v-if="showHero"></HomeHero>
|
<HomeHero v-if="showHero"></HomeHero>
|
||||||
<ModuleBar></ModuleBar>
|
<ModuleBar></ModuleBar>
|
||||||
<div class="app-frame-body">
|
<div class="app-frame-body">
|
||||||
@@ -77,13 +78,19 @@ body {
|
|||||||
max-width: 1180px;
|
max-width: 1180px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
/* hero 顶入玻璃顶栏之下(对齐原型 topbar margin-bottom:-51px 的叠压效果) */
|
/* hero 刊头从视口顶起步:base-wrap-main 零 padding 后无需再抵消旧留白,
|
||||||
|
fixed 玻璃顶栏(z30)直接叠压刊头顶部,即原型 topbar margin-bottom:-51px 的效果 */
|
||||||
.app-frame .hero {
|
.app-frame .hero {
|
||||||
margin-top: -50px;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
.app-frame-body {
|
.app-frame-body {
|
||||||
padding: 12px 0 56px;
|
padding: 12px 0 56px;
|
||||||
}
|
}
|
||||||
|
/* 无刊头页(记录/成长足迹/区域等):base-wrap-main 已零 padding,固定顶栏(51px)悬在内容上方,
|
||||||
|
这里补回让位(51px 栏高 + 12px 原间隙),栏目条(module-bar)不致压入顶栏之下 */
|
||||||
|
.app-frame.no-hero {
|
||||||
|
padding-top: 63px;
|
||||||
|
}
|
||||||
/* 全站页脚:固定窗口底部始终可见,玻璃质感与顶栏呼应;滚动内容以上留白防遮挡 */
|
/* 全站页脚:固定窗口底部始终可见,玻璃质感与顶栏呼应;滚动内容以上留白防遮挡 */
|
||||||
.app-footer {
|
.app-footer {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
|||||||
@@ -31,8 +31,16 @@ body { font-family: var(--font-b); background: linear-gradient(180deg, #aecfee 0
|
|||||||
body::before, body::after { content: ""; position: fixed; z-index: -1; top: -50px; width: 620px; height: 300px; pointer-events: none; background: radial-gradient(closest-side, rgba(255,255,255,.95), rgba(255,255,255,0) 76%); }
|
body::before, body::after { content: ""; position: fixed; z-index: -1; top: -50px; width: 620px; height: 300px; pointer-events: none; background: radial-gradient(closest-side, rgba(255,255,255,.95), rgba(255,255,255,0) 76%); }
|
||||||
body::before { left: -140px; }
|
body::before { left: -140px; }
|
||||||
body::after { right: -160px; }
|
body::after { right: -160px; }
|
||||||
/* 老壳白底不再遮挡 body 的天空渐变(layout.css 的 .base-wrap-main{background:#fff}) */
|
/* 老壳白底(layout.css)与主题通道皮肤(base.layout.css .base-wrap-main{background:var(--page-bg)},
|
||||||
.base-wrap-main { background: transparent; }
|
晚于本样式注入)均不得遮挡 body 的天空渐变:html 前缀提到 (0,1,1) 与加载顺序无关地稳赢。
|
||||||
|
背景透出是本应用对皮肤声明的唯一越权缝,其余外观仍交皮肤管控 */
|
||||||
|
html .base-wrap-main { background: transparent; }
|
||||||
|
/* 布局壳纠正(老壳 layout.css 的 56px 顶留白 + 线上皮肤 base.layout.css 的
|
||||||
|
padding:calc(var(--topbar-h) + var(--crumb-h)) 0 0 var(--side-w) 均不适用本应用):
|
||||||
|
本应用自渲染 fixed 玻璃顶栏、1180px 居中单列,内容从视口顶全宽起步(刊头以负 margin 压入顶栏玻璃之下),
|
||||||
|
外壳不得再加 padding;高度占满视口。html 前缀提到 (0,1,1),与加载顺序无关地压过两者。
|
||||||
|
固定顶栏(51px)的让位由 .app-frame.no-hero .app-frame-body 按页处理,见 App.vue */
|
||||||
|
html .base-wrap-main { padding: 0; height: 100%; }
|
||||||
a { text-decoration: none; color: inherit; }
|
a { text-decoration: none; color: inherit; }
|
||||||
ul, ol { list-style: none; }
|
ul, ol { list-style: none; }
|
||||||
.container { width: 1180px; margin: 0 auto; }
|
.container { width: 1180px; margin: 0 auto; }
|
||||||
@@ -152,7 +160,8 @@ ul, ol { list-style: none; }
|
|||||||
.htxt b { font-family: var(--font-b); font-size: 21px; font-weight: 800; display: block; color: #1e63c8; line-height: 1.2; }
|
.htxt b { font-family: var(--font-b); font-size: 21px; font-weight: 800; display: block; color: #1e63c8; line-height: 1.2; }
|
||||||
.htxt span { display: block; margin-top: 2px; font-size: 11px; color: #5b7ba1; letter-spacing: .5px; }
|
.htxt span { display: block; margin-top: 2px; font-size: 11px; color: #5b7ba1; letter-spacing: .5px; }
|
||||||
.hero-grid { display: none; }
|
.hero-grid { display: none; }
|
||||||
.hero-illo { position: absolute; right: 200px; top: 55px; height: 250px; object-fit: contain; mix-blend-mode: multiply; z-index: 1; -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 22%, #000 84%, transparent 100%); mask-image: linear-gradient(180deg, transparent 0, #000 22%, #000 84%, transparent 100%); }
|
/* 插画锚定 1180px 内容列右缘(right:50%-590px),位置不随窗口宽度漂移 */
|
||||||
|
.hero-illo { position: absolute; right: calc(50% - 590px); top: 55px; height: 250px; object-fit: contain; mix-blend-mode: multiply; z-index: 1; -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 22%, #000 84%, transparent 100%); mask-image: linear-gradient(180deg, transparent 0, #000 22%, #000 84%, transparent 100%); }
|
||||||
|
|
||||||
/* ===== 栏目条:现代胶囊式 ===== */
|
/* ===== 栏目条:现代胶囊式 ===== */
|
||||||
.module-bar { margin-top: 14px; display: flex; align-items: center; border-radius: 10px; background: var(--card); box-shadow: var(--shadow-sm); padding: 4px 6px; }
|
.module-bar { margin-top: 14px; display: flex; align-items: center; border-radius: 10px; background: var(--card); box-shadow: var(--shadow-sm); padding: 4px 6px; }
|
||||||
|
|||||||
@@ -12,9 +12,10 @@ const temp = ref("");
|
|||||||
const desc = ref("");
|
const desc = ref("");
|
||||||
const kind = ref<"sun" | "cloud" | "overcast" | "rain" | "snow" | "fog" | "storm">("sun");
|
const kind = ref<"sun" | "cloud" | "overcast" | "rain" | "snow" | "fog" | "storm">("sun");
|
||||||
|
|
||||||
/** WWO weatherCode → 中文天气名(wttr.in j1 格式不随 lang 翻译,本地映射) */
|
/** WWO weatherCode → 中文天气名。wttr.in 的 lang_zh 对新代码不再翻译(英文透传),
|
||||||
|
* 且上游已出现旧表之外的扩展码(如 149 烟霾),故本地映射 + 英文描述关键词兜底(DESC_ZH)。 */
|
||||||
const CODE_ZH: Record<number, string> = {
|
const CODE_ZH: Record<number, string> = {
|
||||||
113: "晴", 116: "多云", 119: "阴", 122: "阴", 143: "薄雾", 248: "雾", 260: "冻雾",
|
113: "晴", 116: "多云", 119: "阴", 122: "阴", 143: "薄雾", 149: "烟霾", 248: "雾", 260: "冻雾",
|
||||||
176: "零星小雨", 263: "零星毛毛雨", 266: "毛毛雨", 281: "冻毛毛雨", 284: "冻毛毛雨",
|
176: "零星小雨", 263: "零星毛毛雨", 266: "毛毛雨", 281: "冻毛毛雨", 284: "冻毛毛雨",
|
||||||
293: "零星小雨", 296: "小雨", 299: "零星阵雨", 302: "阵雨", 305: "零星大雨", 308: "大雨",
|
293: "零星小雨", 296: "小雨", 299: "零星阵雨", 302: "阵雨", 305: "零星大雨", 308: "大雨",
|
||||||
311: "冻雨", 314: "冻雨", 350: "冰雹", 353: "零星阵雨", 356: "阵雨", 359: "暴雨", 362: "零星阵雨", 365: "阵雨",
|
311: "冻雨", 314: "冻雨", 350: "冰雹", 353: "零星阵雨", 356: "阵雨", 359: "暴雨", 362: "零星阵雨", 365: "阵雨",
|
||||||
@@ -24,13 +25,62 @@ const CODE_ZH: Record<number, string> = {
|
|||||||
227: "吹雪", 230: "暴风雪",
|
227: "吹雪", 230: "暴风雪",
|
||||||
};
|
};
|
||||||
|
|
||||||
function kindOf(code: number): typeof kind.value {
|
/** 英文描述 → 中文(顺序敏感:特称在前,兜底泛称在后;覆盖上表未收录的新代码) */
|
||||||
|
const DESC_ZH: Array<[RegExp, string]> = [
|
||||||
|
[/thundery|thunder|storm/i, "雷阵雨"],
|
||||||
|
[/torrential/i, "暴雨"],
|
||||||
|
[/heavy rain/i, "大雨"],
|
||||||
|
[/moderate rain|rain at times/i, "中雨"],
|
||||||
|
[/(light|patchy) rain/i, "小雨"],
|
||||||
|
[/rain shower/i, "阵雨"],
|
||||||
|
[/sleet/i, "雨夹雪"],
|
||||||
|
[/freezing drizzle/i, "冻毛毛雨"],
|
||||||
|
[/drizzle/i, "毛毛雨"],
|
||||||
|
[/freezing rain/i, "冻雨"],
|
||||||
|
[/ice pellet/i, "冰雹"],
|
||||||
|
[/blizzard/i, "暴风雪"],
|
||||||
|
[/blowing snow/i, "吹雪"],
|
||||||
|
[/heavy snow/i, "大雪"],
|
||||||
|
[/moderate snow/i, "中雪"],
|
||||||
|
[/(light|patchy) snow/i, "小雪"],
|
||||||
|
[/snow shower/i, "阵雪"],
|
||||||
|
[/rain/i, "雨"],
|
||||||
|
[/snow/i, "雪"],
|
||||||
|
[/smoke|haze/i, "烟霾"],
|
||||||
|
[/freezing fog/i, "冻雾"],
|
||||||
|
[/mist|fog/i, "雾"],
|
||||||
|
[/overcast/i, "阴"],
|
||||||
|
[/cloud/i, "多云"],
|
||||||
|
[/clear|sunny/i, "晴"],
|
||||||
|
];
|
||||||
|
|
||||||
|
function zhFromDesc(en: string): string {
|
||||||
|
if (!en) return "";
|
||||||
|
for (const [re, zh] of DESC_ZH) {
|
||||||
|
if (re.test(en)) return zh;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 未知码返回 undefined,由描述关键词接棒定图标 */
|
||||||
|
function kindOf(code: number): typeof kind.value | undefined {
|
||||||
if ([200, 386, 389].includes(code)) return "storm";
|
if ([200, 386, 389].includes(code)) return "storm";
|
||||||
if ([179, 182, 185, 227, 320, 323, 326, 350, 368, 371, 374, 377].includes(code)) return "snow";
|
if ([179, 182, 185, 227, 320, 323, 326, 350, 368, 371, 374, 377].includes(code)) return "snow";
|
||||||
if ([176, 263, 266, 281, 284, 293, 296, 299, 302, 305, 308, 311, 314, 353, 356, 359, 362, 365].includes(code)) return "rain";
|
if ([176, 263, 266, 281, 284, 293, 296, 299, 302, 305, 308, 311, 314, 353, 356, 359, 362, 365].includes(code)) return "rain";
|
||||||
if ([143, 248, 260].includes(code)) return "fog";
|
if ([143, 149, 248, 260].includes(code)) return "fog";
|
||||||
if ([119, 122].includes(code)) return "overcast";
|
if ([119, 122].includes(code)) return "overcast";
|
||||||
if ([116].includes(code)) return "cloud";
|
if ([116].includes(code)) return "cloud";
|
||||||
|
if ([113].includes(code)) return "sun";
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function kindFromDesc(en: string): typeof kind.value {
|
||||||
|
if (/thunder|storm/i.test(en)) return "storm";
|
||||||
|
if (/snow|sleet|blizzard/i.test(en)) return "snow";
|
||||||
|
if (/rain|drizzle|shower/i.test(en)) return "rain";
|
||||||
|
if (/smoke|haze|mist|fog/i.test(en)) return "fog";
|
||||||
|
if (/overcast/i.test(en)) return "overcast";
|
||||||
|
if (/cloud/i.test(en)) return "cloud";
|
||||||
return "sun";
|
return "sun";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,8 +89,9 @@ function apply(j: any) {
|
|||||||
if (!cur) return;
|
if (!cur) return;
|
||||||
temp.value = cur.temp_C;
|
temp.value = cur.temp_C;
|
||||||
const code = Number(cur.weatherCode) || 0;
|
const code = Number(cur.weatherCode) || 0;
|
||||||
desc.value = CODE_ZH[code] || cur.lang_zh?.[0]?.value || cur.weatherDesc?.[0]?.value || "";
|
const en = cur.weatherDesc?.[0]?.value || "";
|
||||||
kind.value = kindOf(code);
|
desc.value = CODE_ZH[code] || zhFromDesc(en);
|
||||||
|
kind.value = kindOf(code) ?? kindFromDesc(en);
|
||||||
visible.value = true;
|
visible.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user