Skip to content

Commit eade8e6

Browse files
feat(footer): 首页加 IH 生态社区栏(monitor / mc / openInvest) (#367)
* feat(footer): 加 IH 生态社区栏(monitor / mc / openInvest)+ 艾露猫 首页 Footer 导航区新增'社区 Community'栏目,与 Archives/Resources 同款列表 UI, 依次链接 monitor.involutionhell.com(服务器状态)、mc.involutionhell.com、 openinvest.involutionhell.com;栏目标题带艾露猫像素头像(public/friends/ailumao.png)。 i18n zh/en 双语;umami 埋点 community_click。 本地验证:pnpm typecheck / lint(Footer 无问题) / build 全过;build 表首页 仍为 ● /[locale] SSG,未回归 ƒ Dynamic;prod server 实测 zh/en 两 locale 均 正确渲染三链与顺序。 * refactor(home): 社区版块从 footer 移到首页正文(CTA 与归档之间) 按 UI 反馈:footer 栏目位置不够显眼。改成首页 Hero 里的独立版块, 插在双 CTA 行与 CLASSIFIED ARCHIVES 之间,把归档网格挤下去。 - Hero 新增 Community Network 版块:与归档网格同款报纸设计(border-t-4 + mono 标签栏 + 分栏卡片),3 列列 monitor / mc / openInvest,NET-01~03 编号, Visit → 外链;标签栏带艾露猫像素头像 - Footer 的 community 栏目撤回(恢复 3 列导航原样) - i18n 从 footer.community 迁到 hero.community(zh/en) 本地:typecheck / lint(Hero+Footer 干净) / build 全过;build 表首页仍 ● /[locale] SSG;prod server 实测版块位于 CTA 之后、归档之前,三链齐全。 * fix(home): 社区版块改紧凑横向布局,修复稀疏难读 原版照搬归档的高卡片:3 宽栏配短描述 + flex-1 把链接顶到底,中间大片留白、 阅读性差。改成横向紧凑卡:NET 编号左置基线对齐,标题内联箭头,描述紧跟其下, 去掉强制拉伸和底部空白,描述对比度提到 neutral-300。内容自然高度、不再空旷。 * feat(home): 社区版块改编辑体前哨波段 + 滚动揭示/反色 wipe 动效 反馈:三个并排一样的格子没设计感,想要下滑时的交互变换。改成三条全宽波段 (CommunityNetwork client 组件,motion/react): - 站名超大衬线体做编辑体信号,功能呼号(Live Ops / Game Node / AI Desk) 取代无意义的 01/02/03 序号;monitor 带呼吸红点(它本就是实时状态台) - 滚动进入视口错峰升起(whileInView + stagger),hover 墨色从左漫满整条 并反色(复用站点反色 idiom 做成 wipe) - mounted 门控 + useReducedMotion:SSR/无 JS/reduced-motion 直接可见, 不把内容藏死;呼吸点与 wipe 都 motion-reduce 降级 本地:typecheck / lint(两文件干净) / build 全过;首页仍 ● /[locale] SSG (client 组件只 hydrate 不破坏静态);Playwright 实测静止 + hover 反色两态。 * copy(home): openInvest 明确为开源实验项目、非投资建议 公益教育社区首页不宜出现无限定的金融项目。openInvest 描述加'开源实验项目 … 仅供研究,非投资建议',呼号 AI Desk → AI Lab 去掉交易台意味、强调研究属性。 * fix(home): 去掉 mounted 门控修 CI lint error react-hooks 7 规则禁止 effect 内同步 setState(set-state-in-effect)。 mounted 门控触发该 error 导致 CI build 挂。改为只用 useReducedMotion—— SSR 首渲染与客户端一致(无 hydration 错配),动效行为不变。 --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 5b7e4ce commit eade8e6

5 files changed

Lines changed: 167 additions & 0 deletions

File tree

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
"use client";
2+
3+
import Image from "next/image";
4+
import { ArrowUpRight } from "lucide-react";
5+
import { motion, useReducedMotion } from "motion/react";
6+
import { cn } from "@/lib/utils";
7+
8+
type Outpost = {
9+
key: string;
10+
callsign: string;
11+
title: string;
12+
desc: string;
13+
href: string;
14+
live?: boolean;
15+
};
16+
17+
/**
18+
* 首页"社区网络"版块:三个生态前哨(monitor / mc / openInvest)做成全宽波段,
19+
* 滚动进入视口时错峰升起,hover 时墨色从左漫过整条(反色 wipe)。
20+
* reduced-motion 时跳过入场动画,直接渲染最终可见状态。
21+
*/
22+
export function CommunityNetwork({
23+
label,
24+
outposts,
25+
}: {
26+
label: string;
27+
outposts: Outpost[];
28+
}) {
29+
const reduce = useReducedMotion();
30+
const animate = !reduce;
31+
32+
return (
33+
<div className="mt-16 border-t-4 border-[var(--foreground)] transition-colors duration-300">
34+
<div className="flex items-center gap-2 py-4 font-mono text-xs uppercase tracking-widest border-b border-[var(--foreground)] text-[var(--foreground)]">
35+
<Image
36+
src="/friends/ailumao.png"
37+
alt=""
38+
width={22}
39+
height={22}
40+
className="[image-rendering:pixelated]"
41+
/>
42+
{label}
43+
</div>
44+
45+
<ul>
46+
{outposts.map((o, i) => (
47+
<motion.li
48+
key={o.key}
49+
initial={animate ? { opacity: 0, y: 26 } : false}
50+
whileInView={animate ? { opacity: 1, y: 0 } : undefined}
51+
viewport={{ once: true, amount: 0.4 }}
52+
transition={{
53+
duration: 0.55,
54+
delay: i * 0.12,
55+
ease: [0.22, 1, 0.36, 1],
56+
}}
57+
className={cn(
58+
"group relative overflow-hidden border-[var(--foreground)]",
59+
i < outposts.length - 1 && "border-b",
60+
)}
61+
>
62+
{/* 墨色 wipe 层:hover 时从左漫满整条 */}
63+
<span
64+
aria-hidden
65+
className="pointer-events-none absolute inset-0 origin-left scale-x-0 bg-[var(--foreground)] transition-transform duration-500 ease-[cubic-bezier(0.22,1,0.36,1)] group-hover:scale-x-100 motion-reduce:transition-none"
66+
/>
67+
68+
<a
69+
href={o.href}
70+
target="_blank"
71+
rel="noopener noreferrer"
72+
className="relative flex flex-col gap-3 py-9 px-6 transition-colors duration-500 group-hover:text-[var(--background)] md:flex-row md:items-center md:gap-8"
73+
data-umami-event="community_click"
74+
data-umami-event-target={o.key}
75+
data-umami-event-location="hero"
76+
>
77+
{/* 呼号 */}
78+
<span className="flex w-28 shrink-0 items-center gap-2 font-mono text-[11px] uppercase tracking-[0.2em] text-neutral-400 group-hover:text-[var(--background)]">
79+
{o.live && (
80+
<span className="relative flex h-1.5 w-1.5">
81+
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-[#CC0000] opacity-75 motion-reduce:hidden" />
82+
<span className="relative inline-flex h-1.5 w-1.5 rounded-full bg-[#CC0000]" />
83+
</span>
84+
)}
85+
{o.callsign}
86+
</span>
87+
88+
{/* 站名(超大衬线,编辑体信号) */}
89+
<span className="font-serif text-3xl font-bold uppercase leading-none tracking-tight text-[var(--foreground)] group-hover:text-[var(--background)] md:text-4xl">
90+
{o.title}
91+
</span>
92+
93+
{/* 描述 */}
94+
<span className="font-body text-sm leading-relaxed text-neutral-600 group-hover:text-[var(--background)] dark:text-neutral-300 md:ml-auto md:max-w-xs md:text-right">
95+
{o.desc}
96+
</span>
97+
98+
<ArrowUpRight className="hidden h-6 w-6 shrink-0 text-neutral-400 transition-transform duration-300 group-hover:translate-x-1 group-hover:-translate-y-1 group-hover:text-[var(--background)] md:block" />
99+
</a>
100+
</motion.li>
101+
))}
102+
</ul>
103+
</div>
104+
);
105+
}

app/components/Hero.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import Link from "next/link";
22
import { Suspense } from "react";
33
import { getTranslations } from "next-intl/server";
44
import ZoteroFeedLazy from "@/app/components/ZoteroFeedLazy";
5+
import { CommunityNetwork } from "@/app/components/CommunityNetwork";
56
import { Contribute } from "@/app/components/Contribute";
67
import { ShareLink } from "@/app/components/ShareLink";
78
import Image from "next/image";
@@ -41,6 +42,31 @@ export async function Hero() {
4142
},
4243
];
4344

45+
const communitySites = [
46+
{
47+
key: "monitor",
48+
callsign: "Live Ops",
49+
title: t("community.monitor.title"),
50+
desc: t("community.monitor.desc"),
51+
href: "https://monitor.involutionhell.com/",
52+
live: true,
53+
},
54+
{
55+
key: "mc",
56+
callsign: "Game Node",
57+
title: t("community.mc.title"),
58+
desc: t("community.mc.desc"),
59+
href: "https://mc.involutionhell.com/",
60+
},
61+
{
62+
key: "invest",
63+
callsign: "AI Lab",
64+
title: t("community.invest.title"),
65+
desc: t("community.invest.desc"),
66+
href: "https://openinvest.involutionhell.com/",
67+
},
68+
];
69+
4470
return (
4571
<section className="relative pt-32 pb-16 newsprint-texture transition-colors duration-300">
4672
<div className="container relative mx-auto px-6">
@@ -120,6 +146,12 @@ export async function Hero() {
120146
</div>
121147
</div>
122148

149+
{/* Community Network - IH 生态站点(滚动揭示 + 反色 wipe,见 CommunityNetwork) */}
150+
<CommunityNetwork
151+
label={t("community.label")}
152+
outposts={communitySites}
153+
/>
154+
123155
{/* Top-level directories - Grid with shared borders */}
124156
<div className="mt-16 border-t-4 border-[var(--foreground)] transition-colors duration-300">
125157
<div className="py-4 font-mono text-xs uppercase tracking-widest border-b border-[var(--foreground)] text-[var(--foreground)]">

messages/en.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,21 @@
3737
"title": "Community Posts",
3838
"desc": "Articles written by community members — published instantly, no PR review needed. Topics range from dev notes to technical deep-dives."
3939
}
40+
},
41+
"community": {
42+
"label": "Community Network · Our Ecosystem",
43+
"monitor": {
44+
"title": "Server Status",
45+
"desc": "Live health, load & cert monitoring for every service — guarded by Ailumao."
46+
},
47+
"mc": {
48+
"title": "Minecraft Server",
49+
"desc": "Our self-hosted MC survival server. Hop in and build together."
50+
},
51+
"invest": {
52+
"title": "openInvest",
53+
"desc": "Open-source experiment — a multi-asset AI committee for research. Not investment advice."
54+
}
4055
}
4156
},
4257
"footer": {

messages/zh.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,21 @@
3737
"title": "群友创作",
3838
"desc": "群友随手写的文章,不用等 PR review,发完即在。选题自由,从踩坑记录到技术思考都有。"
3939
}
40+
},
41+
"community": {
42+
"label": "社区网络 · 我们的生态",
43+
"monitor": {
44+
"title": "服务器状态",
45+
"desc": "实时监控全部服务健康、负载与证书,由艾露猫看守。"
46+
},
47+
"mc": {
48+
"title": "Minecraft 服务器",
49+
"desc": "内卷地狱自建 MC 生存服,加入一起联机开荒。"
50+
},
51+
"invest": {
52+
"title": "openInvest",
53+
"desc": "开源实验项目:多资产 AI 投资委员会,4 角色辩论。仅供研究,非投资建议。"
54+
}
4055
}
4156
},
4257
"footer": {

public/friends/ailumao.png

9.92 KB
Loading

0 commit comments

Comments
 (0)