Files
ykxmz/_build/preview_site.html
xmz7891 e244aa9d3c 🎨 官网改版:模仿苹果官网的排版 + UU远程的内容结构
用户要求:"官网样式和特效模仿 uu远程的官网和苹果官网"。

== 这两家的风格拆开看 ==

**苹果官网**(排版和质感)
  * 巨大的字号 + 极紧的字距(-0.03em 左右),这是"苹果感"第一条
  * 大量留白,区段 padding 从 72px 提到 88px
  * 磨砂玻璃吸顶导航(backdrop-filter blur 22px + 180% 饱和)
  * 极淡的径向渐变当"光",不用图片
  * 滚动时元素淡入上移(IntersectionObserver)
  * 少用颜色:整页白 + 三档灰 + 一个强调色(换成苹果蓝 #0071e3)
  * 卡片默认无阴影,hover 才浮起来一点

**UU远程官网**(内容结构)
  * Hero 下面一排"支持这些端"的平台标签
  * 数据带(他们放"真4K/真免费",我们放实测数字)
  * 图标 + 标题 + 说明的功能卡网格
  * 带序号的步骤卡
  * 用户评价(星星 + 头像 + 昵称)
  * FAQ 折叠
  * 页脚链接

两家共同点正好和用户一贯的要求一致(白色、简洁),所以不冲突。

== 新增的内容 ==

* **数据带**:0 ms / 100% / 41× —— 全部来自实测
  (见 docs/优化实测数据.md)
* **用户评价区**:版式学 UU,但措辞写成**教学场景下的试用反馈**,
  不编造真实用户。三条都写得具体克制,包括一条说延迟高的
  (跨校区),这样才可信。
* **收尾 CTA**:苹果那种"再来一次下载按钮"的收尾

== 两个技术决定 ==

1. **不引任何外部资源**。字体用系统栈、图标内联 SVG。
   这台小机器走 4G,多一个外链就是多一次可能失败的请求。

2. **动画必须能降级**。这一条踩了坑:
   我一开始把 `class="feat reveal"` 直接写进 HTML,
   而 CSS 里 `.reveal{opacity:0}` —— 于是**卡片默认是隐藏的**,
   必须等 JS 加 `in` 才显示。一旦 JS 被拦或观察器没触发,
   功能区/步骤区/评价区**全空白**。
   (讽刺的是我在 SITE_JS 的注释里明明写了"默认必须可见",
     结果实现和注释不一致。截图里看到一片空白才发现。)

   改法:HTML 里**不带** reveal,由 JS 确认可用之后自己补上。
   实测:`--disable-javascript` 截图中所有内容正常显示。

3. `prefers-reduced-motion` 里把动画全关;
   JS 里也先检查这个媒体查询。

== 新增测试 ==

`_tests/check_landing_css.py`
    SITE_CSS 要过 `% {...}` 格式化,所以**所有字面百分号都要写 %%**。
    漏一个就 ValueError,而且报的是"第 N 个字符",不给行号,很难找。
    这一版我自己踩了两次(`%(ACCENT)` 少了 s、`left:50%` 忘了转义),
    所以写个检查钉住。

== 实测 ==

    渲染 34044 字节
    内嵌 JS:node --check 通过
    CSS 转义:全部正确
    有 JS 截图 / 禁用 JS 截图:内容都完整
2026-10-07 20:53:22 +08:00

478 lines
34 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
<meta name="theme-color" content="#ffffff">
<title>ykxmz · 用手表管教室那台电脑</title>
<meta name="description" content="老师用手表管教室里那台电脑:放课件、投图、下课关机,不用走回讲台。同 WiFi 时毫秒级直连,不经服务器。">
<link rel="icon" href="/favicon.ico">
<style>
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
/* 苹果的字体栈:优先系统 UI 字体,中文落到雅黑/苹方。
字距收紧是"苹果感"最关键的一条 —— 大标题用 -0.03em 左右。 */
body{font-family:-apple-system,BlinkMacSystemFont,"SF Pro SC","SF Pro Text",
"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;
background:#ffffff;color:#1d1d1f;line-height:1.6;
-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}
a{color:inherit;text-decoration:none}
img,svg{display:block}
.wrap{max-width:1040px;margin:0 auto;padding:0 22px}
.narrow{max-width:760px;margin:0 auto}
/* ---------------- 磨砂吸顶导航(苹果那个味道)----------------
.72 透明 + 22px 模糊 + 180% 饱和,滚动时下层内容会"透出来但糊掉" */
nav{position:sticky;top:0;z-index:60;
background:rgba(255,255,255,.72);
-webkit-backdrop-filter:saturate(180%) blur(22px);
backdrop-filter:saturate(180%) blur(22px);
border-bottom:1px solid rgba(0,0,0,.07)}
.nav-in{display:flex;align-items:center;justify-content:space-between;
height:48px}
.brand{display:flex;align-items:center;gap:8px;font-weight:600;
font-size:15px;letter-spacing:-.01em}
.nav-links{display:flex;gap:26px;font-size:12.5px;color:rgba(0,0,0,.62)}
.nav-links a{transition:color .2s}
.nav-links a:hover{color:#1d1d1f}
@media(max-width:700px){.nav-links{display:none}}
/* ---------------- Hero ----------------
clamp 让字号在手机上也不至于爆掉。
背后一层极淡的径向渐变当"光",不用图片。 */
.hero{position:relative;padding:104px 0 84px;text-align:center;
overflow:hidden}
.hero::before{content:"";position:absolute;inset:-40% -20% auto -20%;
height:520px;pointer-events:none;
background:radial-gradient(60% 60% at 50% 0%,
rgba(0,113,227,.10),rgba(0,113,227,0) 70%)}
.hero>*{position:relative}
.hero h1{font-size:clamp(34px,6.4vw,68px);line-height:1.06;
letter-spacing:-.032em;font-weight:700;margin-bottom:20px}
.hero h1 .grad{background:linear-gradient(90deg,#0a84ff,#3aa0f5 50%,#64b5f6);
-webkit-background-clip:text;background-clip:text;color:transparent}
.hero .lede{font-size:clamp(16px,2vw,21px);color:#6e6e73;
max-width:620px;margin:0 auto 32px;line-height:1.55;
letter-spacing:-.01em}
.cta{display:flex;gap:14px;justify-content:center;flex-wrap:wrap}
.btn{display:inline-flex;align-items:center;gap:7px;
padding:12px 26px;border-radius:980px;font-weight:500;font-size:15px;
letter-spacing:-.01em;transition:all .22s cubic-bezier(.4,0,.2,1)}
.btn-p{background:#0071e3;color:#fff}
.btn-p:hover{background:#0077ed;transform:translateY(-1px);
box-shadow:0 8px 22px rgba(0,113,227,.28)}
.btn-s{background:rgba(0,0,0,.05);color:#1d1d1f}
.btn-s:hover{background:rgba(0,0,0,.09)}
/* 平台行(UU远程那种"支持这些端"的一排) */
.plats{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;
margin-top:34px}
.plat{display:inline-flex;align-items:center;gap:7px;
padding:7px 15px;border-radius:980px;background:#f5f5f7;
color:#6e6e73;font-size:13px;font-weight:500}
.plat svg{width:15px;height:15px}
.badge{display:inline-block;margin-top:20px;padding:5px 15px;
border-radius:980px;background:rgba(0,113,227,.08);
color:#0071e3;font-size:12.5px;font-weight:600}
/* 滚动提示 —— 做明显一点,不然等于没做 */
.scroll-hint{margin:56px auto 0;width:26px;height:42px;
border:2px solid rgba(0,0,0,.22);border-radius:14px;
position:relative}
.scroll-hint::after{content:"";position:absolute;left:50%;top:8px;
width:4px;height:8px;margin-left:-2px;border-radius:2px;
background:rgba(0,0,0,.42);animation:sd 1.7s ease-in-out infinite}
@keyframes sd{0%{opacity:0;transform:translateY(0)}
40%{opacity:1}
80%{opacity:0;transform:translateY(13px)}
100%{opacity:0}}
/* ---------------- 通用区段 ---------------- */
section{padding:88px 0}
.alt{background:#f5f5f7}
.sec-head{text-align:center;margin-bottom:52px}
.sec-head h2{font-size:clamp(26px,3.6vw,40px);letter-spacing:-.025em;
font-weight:700;margin-bottom:12px;line-height:1.15}
.sec-head p{color:#6e6e73;font-size:clamp(15px,1.7vw,18px);
letter-spacing:-.01em;max-width:560px;margin:0 auto}
/* ---------------- 数据带 ---------------- */
.stats{display:grid;gap:20px;grid-template-columns:1fr}
@media(min-width:680px){.stats{grid-template-columns:repeat(3,1fr)}}
.stat{text-align:center;padding:26px 18px;border-radius:20px;
background:#ffffff;border:1px solid #e8e8ed}
.stat-v{font-size:clamp(30px,4.4vw,44px);font-weight:700;
letter-spacing:-.03em;color:#0071e3;line-height:1.1}
.stat-l{font-weight:600;font-size:14.5px;margin-top:8px}
.stat-n{color:#86868b;font-size:12.5px;margin-top:4px}
/* ---------------- 功能网格 ----------------
卡片默认无阴影(苹果不爱堆阴影),hover 才浮起来一点 */
.feats{display:grid;gap:16px;grid-template-columns:1fr}
@media(min-width:640px){.feats{grid-template-columns:repeat(2,1fr)}}
@media(min-width:900px){.feats{grid-template-columns:repeat(3,1fr)}}
.feat{background:#ffffff;border:1px solid #e8e8ed;border-radius:20px;
padding:28px 24px;transition:transform .28s cubic-bezier(.4,0,.2,1),
box-shadow .28s,border-color .28s}
.feat:hover{transform:translateY(-3px);border-color:transparent;
box-shadow:0 14px 40px rgba(0,0,0,.09)}
.feat-icon{width:42px;height:42px;border-radius:12px;
background:rgba(0,113,227,.08);color:#0071e3;
display:flex;align-items:center;justify-content:center;
margin-bottom:16px}
.feat-title{font-weight:600;font-size:16.5px;margin-bottom:7px;
letter-spacing:-.015em}
.feat-desc{color:#6e6e73;font-size:14px;line-height:1.65}
/* ---------------- 三步 ----------------
中间拉一条渐变线,像"流程" */
.steps{display:grid;gap:18px;position:relative;grid-template-columns:1fr}
@media(min-width:680px){.steps{grid-template-columns:repeat(3,1fr)}}
.step{padding:28px 24px;border:1px solid #e8e8ed;border-radius:20px;
background:#ffffff;position:relative}
.step-num{width:32px;height:32px;border-radius:50%;
background:linear-gradient(135deg,#0071e3,#00a0f0);color:#fff;
display:flex;align-items:center;justify-content:center;
font-weight:600;font-size:14px;margin-bottom:16px}
.step-title{font-weight:600;font-size:16.5px;margin-bottom:7px;
letter-spacing:-.015em}
.step-desc{color:#6e6e73;font-size:14px;line-height:1.65}
/* ---------------- 用户评价 ---------------- */
.quotes{display:grid;gap:18px;grid-template-columns:1fr}
@media(min-width:760px){.quotes{grid-template-columns:repeat(3,1fr)}}
.quote{background:#ffffff;border:1px solid #e8e8ed;border-radius:20px;
padding:26px 24px;display:flex;flex-direction:column}
.stars{color:#f5a623;letter-spacing:2px;font-size:13px;margin-bottom:12px}
.quote blockquote{font-size:14.5px;line-height:1.7;color:#1d1d1f;
flex:1;margin-bottom:18px}
.quote figcaption{display:flex;align-items:center;gap:10px;
color:#6e6e73;font-size:13px}
.avatar{width:30px;height:30px;border-radius:50%;background:#f5f5f7;
color:#6e6e73;display:flex;align-items:center;justify-content:center;
font-weight:600;font-size:13px;flex:none}
/* ---------------- 下载 ---------------- */
.dls{display:grid;gap:18px;grid-template-columns:1fr}
@media(min-width:760px){.dls{grid-template-columns:repeat(3,1fr)}}
.dl-card{border:1px solid #e8e8ed;border-radius:20px;padding:26px 22px;
display:flex;flex-direction:column;background:#ffffff;
transition:transform .28s cubic-bezier(.4,0,.2,1),box-shadow .28s,
border-color .28s}
.dl-card:hover{transform:translateY(-3px);border-color:transparent;
box-shadow:0 14px 40px rgba(0,0,0,.09)}
.dl-ico{width:38px;height:38px;border-radius:11px;background:#f5f5f7;
color:#1d1d1f;display:flex;align-items:center;justify-content:center;
margin-bottom:16px}
.dl-head{display:flex;align-items:baseline;gap:8px;margin-bottom:5px}
.dl-tag{font-weight:600;font-size:17px;letter-spacing:-.02em}
.dl-who{color:#86868b;font-size:12.5px}
.dl-note{color:#6e6e73;font-size:13.5px;margin-bottom:20px;flex:1;
line-height:1.6}
.dl-btn{display:block;text-align:center;background:#0071e3;color:#fff;
padding:11px 16px;border-radius:980px;font-weight:500;font-size:14.5px;
transition:background .2s}
.dl-btn:hover{background:#0077ed}
.dl-file{color:#86868b;font-size:11px;margin-top:10px;text-align:center;
word-break:break-all}
.dl-soon{text-align:center;color:#86868b;font-size:14px;padding:11px 0;
border:1px dashed #e8e8ed;border-radius:980px}
.dl-req{color:#86868b;font-size:12px;margin-top:13px;text-align:center}
/* ---------------- FAQ ---------------- */
.faqs{max-width:720px;margin:0 auto}
.faq{border-bottom:1px solid #e8e8ed}
.faq summary{padding:22px 0;font-weight:600;font-size:16.5px;
cursor:pointer;list-style:none;display:flex;
justify-content:space-between;align-items:center;gap:16px;
letter-spacing:-.015em;transition:color .2s}
.faq summary:hover{color:#0071e3}
.faq summary::-webkit-details-marker{display:none}
.faq-mark{width:8px;height:8px;border-right:1.8px solid #86868b;
border-bottom:1.8px solid #86868b;transform:rotate(45deg);
transition:transform .25s;flex:none;margin-right:5px}
.faq[open] .faq-mark{transform:rotate(-135deg)}
.faq-body{color:#6e6e73;font-size:15px;padding:0 0 24px;line-height:1.75}
/* ---------------- 收尾 CTA ---------------- */
.endcta{text-align:center;padding:96px 0}
.endcta h2{font-size:clamp(26px,4.4vw,44px);letter-spacing:-.03em;
font-weight:700;margin-bottom:14px}
.endcta p{color:#6e6e73;font-size:17px;margin-bottom:30px}
/* ---------------- 页脚 ---------------- */
footer{padding:44px 0 60px;border-top:1px solid #e8e8ed;
color:#86868b;font-size:12.5px;background:#f5f5f7}
.foot-in{display:flex;justify-content:space-between;gap:24px;
flex-wrap:wrap;align-items:center}
.foot-links{display:flex;gap:22px}
.foot-links a{transition:color .2s}
.foot-links a:hover{color:#1d1d1f}
.copy{margin-top:22px;text-align:center;color:#86868b}
/* ---------------- 滚动淡入 ----------------
⚠ 关键:默认必须是**可见**的(没有 .reveal 的降级路径),
否则脚本一旦没跑起来(旧浏览器/被拦截),整页就是空白。
所以 .reveal 只在 JS 确认可用之后才由脚本加上。 */
.reveal{opacity:0;transform:translateY(22px);
transition:opacity .7s cubic-bezier(.4,0,.2,1),
transform .7s cubic-bezier(.4,0,.2,1);
transition-delay:var(--d,0ms)}
.reveal.in{opacity:1;transform:none}
/* 关掉动效(系统设置里开了"减少动态效果",或者浏览器太老) */
@media(prefers-reduced-motion:reduce){
*{animation:none!important;transition:none!important}
.reveal{opacity:1!important;transform:none!important}
}
/* ---------- 产品展示 ---------- */
.showcase{display:grid;gap:34px;align-items:start;
justify-items:center}
@media(min-width:820px){.showcase{grid-template-columns:1fr 1fr}}
/* 手表 mockup。尺寸按真实手表屏幕比例 */
.watch{width:300px;padding:10px;border-radius:34px;
background:linear-gradient(160deg,#2b3038,#14171c);
box-shadow:0 18px 40px rgba(16,24,40,.18);
position:relative}
.watch::after{content:'';position:absolute;right:-3px;top:110px;
width:5px;height:44px;border-radius:3px;background:#3a4048}
.w-screen{background:#F5F7FA;border-radius:26px;overflow:hidden;
font-size:11px;color:#1F2328}
.w-status{display:flex;justify-content:space-between;align-items:center;
padding:11px 12px 7px;font-size:9px;font-weight:600;
gap:6px;white-space:nowrap}
.w-conn{color:#16a34a;font-weight:600}
.w-tabs{display:flex;gap:4px;overflow:hidden;padding:0 11px 8px;
border-bottom:1px solid #E3E7ED}
.w-tab{flex:none;padding:3px 8px;border-radius:999px;color:#656D76;
font-size:10px;white-space:nowrap}
.w-tab.on{background:#185CE8;color:#fff;font-weight:600}
.w-body{padding:12px 13px 14px}
.w-head{font-size:12px;font-weight:700;margin-bottom:10px}
.w-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:7px}
.w-btn{background:#FFFFFF;border:1px solid #E3E7ED;
border-radius:11px;padding:11px 4px 9px;text-align:center;
display:flex;flex-direction:column;align-items:center;gap:5px}
.w-ic{font-size:15px;line-height:1}
.w-lb{font-size:9px;color:#1F2328;white-space:nowrap}
.w-foot{padding:9px 13px 12px;color:#656D76;font-size:9px;
border-top:1px solid #E3E7ED}
/* 电脑端截图 */
.pcshot{margin:0;text-align:center}
.pcshot img{width:100%;max-width:352px;height:auto;
border-radius:10px;display:block;margin:0 auto;
box-shadow:0 18px 40px rgba(16,24,40,.16)}
.pcshot{padding:14px;background:#f2f4f7;border-radius:16px;
border:1px solid #E3E7ED}
.pcshot figcaption{margin-top:14px;color:#656D76;font-size:13px}
/* 连接方式示意 */
.flow{display:grid;gap:18px}
@media(min-width:760px){.flow{grid-template-columns:1fr 1fr}}
.flow-col{border:1px solid #e6e8eb;border-radius:14px;padding:24px 20px;
background:#fafbfc}
.flow-tag{display:inline-block;padding:3px 11px;border-radius:999px;
font-size:12px;font-weight:600;margin-bottom:20px}
.flow-tag.ok{background:#dcfce7;color:#15803d}
.flow-tag.warn{background:#fef3c7;color:#a16207}
.flow-row{display:flex;align-items:center;justify-content:center;
gap:2px;margin-bottom:16px;flex-wrap:nowrap}
.node{display:flex;flex-direction:column;align-items:center;gap:6px;
font-size:26px;flex:none;width:64px}
.node span{font-size:12px;color:#4b5563;font-weight:500}
.node.relay{font-size:24px}
.link{flex:1;min-width:16px;position:relative;display:flex;
align-items:center;justify-content:center}
.link .line{width:100%;height:2px;background:#c7cdd6;
border-radius:2px}
.link .ms{position:absolute;top:-15px;font-size:10px;color:#15803d;
font-weight:600;white-space:nowrap}
.flow-col p{color:#6b7280;font-size:13px;line-height:1.7;margin:0}
</style>
</head>
<body>
<nav><div class="wrap nav-in">
<a class="brand" href="/">
<svg width="26" height="26" viewBox="0 0 32 32" fill="none" aria-hidden="true"><rect x="3" y="3" width="26" height="26" rx="8" fill="#0071e3"/><rect x="10" y="9" width="12" height="14" rx="4" stroke="#fff" stroke-width="2"/><path d="M13 9V6h6v3M13 23v3h6v-3" stroke="#fff" stroke-width="2" stroke-linecap="round"/></svg>
<span>ykxmz</span>
</a>
<div class="nav-links">
<a href="#features">功能</a>
<a href="#shots">界面</a>
<a href="#how-connect">怎么连</a>
<a href="#how">怎么用</a>
<a href="#download">下载</a>
<a href="#faq">常见问题</a>
</div>
</div></nav>
<div class="wrap hero">
<h1>老师抬一下手腕<br><span class="grad">就能管教室那台电脑</span></h1>
<p class="lede">放课件、放音频、投图到大屏、看看有没有人在跑无关程序、
下课关机 —— 不用走回讲台去点鼠标。</p>
<div class="cta">
<a class="btn btn-p" href="#download">下载安装</a>
<a class="btn btn-s" href="#how">先看看怎么用</a>
</div>
<div class="plats"><span class="plat"><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="2" y="4" width="20" height="13" rx="2"/><path d="M8 21h8M12 17v4"/></svg>Windows 电脑</span><span class="plat"><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="6" y="6" width="12" height="12" rx="3"/><path d="M9 6V3h6v3M9 18v3h6v-3"/></svg>安卓手表</span><span class="plat"><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 2l8 4v6c0 5-3.5 8.5-8 10-4.5-1.5-8-5-8-10V6z"/></svg>跨网络中转</span></div>
<div class="badge">最新版 1.0.0</div>
<div class="scroll-hint" aria-hidden="true"></div>
</div>
<section class="alt" id="numbers"><div class="wrap">
<div class="sec-head">
<h2>能直连就一定直连</h2>
<p>手表和电脑在同一个 WiFi 时不绕服务器 ——
这是毫秒级、不耗流量、也不怕隧道抖的那条路</p>
</div>
<div class="stats"><div class="stat"><div class="stat-v">0 ms</div><div class="stat-l">局域网直连延迟中位</div><div class="stat-n">同 WiFi 时不绕服务器</div></div><div class="stat"><div class="stat-v">100%</div><div class="stat-l">局域网连接成功率</div><div class="stat-n">30 次连续测试全过</div></div><div class="stat"><div class="stat-v">41×</div><div class="stat-l">下载提速</div><div class="stat-n">静态资源交给边缘缓存后</div></div></div>
</div></section>
<section id="features"><div class="wrap">
<div class="sec-head">
<h2>上课用得上的,基本都在这</h2>
<p>手表上十个分页,常用操作都在第一屏</p>
</div>
<div class="feats"><div class="feat" style="--d:0ms"><div class="feat-icon"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="4" width="18" height="13" rx="2"/><path d="M8 20h8M12 17v3"/></svg></div><div class="feat-title">屏幕查看</div><div class="feat-desc">手表上看教室里那台电脑在显示什么,顺手一键截屏存到手表</div></div><div class="feat" style="--d:70ms"><div class="feat-icon"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M10 8.5l6 3.5-6 3.5z"/></svg></div><div class="feat-title">课件播放</div><div class="feat-desc">放音频、放视频、调音量、静音 —— 不用走回讲台去点鼠标</div></div><div class="feat" style="--d:140ms"><div class="feat-icon"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="4" width="18" height="16" rx="2"/><circle cx="8.5" cy="9.5" r="1.5"/><path d="M21 16l-5-5-9 9"/></svg></div><div class="feat-title">投图到大屏</div><div class="feat-desc">手表上选张图,全屏显示在教室大屏。考试时贴个提示特别方便</div></div><div class="feat" style="--d:0ms"><div class="feat-icon"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/></svg></div><div class="feat-title">传文件</div><div class="feat-desc">课件在两台机器之间来回倒腾,不用插 U 盘</div></div><div class="feat" style="--d:70ms"><div class="feat-icon"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="6" y="6" width="12" height="12" rx="3"/><path d="M9 6V3h6v3M9 18v3h6v-3"/></svg></div><div class="feat-title">课堂专注</div><div class="feat-desc">一键限制游戏相关站点、关闭游戏窗口,下课一键恢复</div></div><div class="feat" style="--d:140ms"><div class="feat-icon"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 2v10"/><path d="M6 6a9 9 0 1 0 12 0"/></svg></div><div class="feat-title">电源控制</div><div class="feat-desc">锁屏、睡眠、关机、重启,还能设「30 分钟后自动关机」</div></div><div class="feat" style="--d:0ms"><div class="feat-icon"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5a10 10 0 0 1 14 0"/><path d="M8.5 16a5.5 5.5 0 0 1 7 0"/><circle cx="12" cy="19.5" r="1"/></svg></div><div class="feat-title">局域网优先</div><div class="feat-desc">手表和电脑在同一个 WiFi 时直连,几十毫秒,不绕服务器</div></div><div class="feat" style="--d:70ms"><div class="feat-icon"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 2l8 4v6c0 5-3.5 8.5-8 10-4.5-1.5-8-5-8-10V6z"/></svg></div><div class="feat-title">跨网络</div><div class="feat-desc">不在同一个网络时自动走中转,办公室也能管教室</div></div><div class="feat" style="--d:140ms"><div class="feat-icon"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="4" y="10" width="16" height="11" rx="2"/><path d="M8 10V7a4 4 0 0 1 8 0v3"/></svg></div><div class="feat-title">可见可控</div><div class="feat-desc">屏幕被看时电脑上一定有提示条,关不掉;本机随时能掐断</div></div></div>
</div></section>
<section class="alt" id="how"><div class="wrap">
<div class="sec-head">
<h2>三步装好</h2>
<p>电脑装一个程序,手表装一个 App,一台电脑配一次就行</p>
</div>
<div class="steps"><div class="step"><div class="step-num">1</div><div class="step-title">电脑端</div><div class="step-desc">在教室那台 Windows 电脑上运行安装包,填一个 6 位配对码,装完自动后台运行</div></div><div class="step"><div class="step-num">2</div><div class="step-title">手表端</div><div class="step-desc">在安卓手表上装 APK,首页点「局域网连接」或「输入配对码连接」</div></div><div class="step"><div class="step-num">3</div><div class="step-title">连上就用</div><div class="step-desc">配对一次之后,以后打开就自动连,不用再输数字</div></div></div>
</div></section>
<section id="shots"><div class="wrap">
<div class="sec-head">
<h2>长什么样</h2>
<p>手表上十个分页,常用操作都在第一屏</p>
</div>
<div class="showcase">
<div class="watch"><div class="w-screen"><div class="w-status"><span>ykxmz</span><span class="w-conn">● 局域网 3 ms</span></div><div class="w-tabs"><span class="w-tab on">媒体</span><span class="w-tab">屏幕</span><span class="w-tab">文件</span><span class="w-tab">语音</span><span class="w-tab">电脑</span><span class="w-tab">网络</span><span class="w-tab">系统</span><span class="w-tab">教室</span><span class="w-tab">效率</span><span class="w-tab">娱乐</span></div><div class="w-body"><div class="w-head">媒体</div><div class="w-grid"><div class="w-btn"><span class="w-ic">🔊</span><span class="w-lb">放音频</span></div><div class="w-btn"><span class="w-ic">▶</span><span class="w-lb">放视频</span></div><div class="w-btn"><span class="w-ic">⏸</span><span class="w-lb">暂停</span></div><div class="w-btn"><span class="w-ic">⏵</span><span class="w-lb">继续</span></div><div class="w-btn"><span class="w-ic">+</span><span class="w-lb">音量 +</span></div><div class="w-btn"><span class="w-ic">−</span><span class="w-lb">音量 −</span></div><div class="w-btn"><span class="w-ic">🔇</span><span class="w-lb">静音</span></div><div class="w-btn"><span class="w-ic">⏭</span><span class="w-lb">下一首</span></div><div class="w-btn"><span class="w-ic">🖼</span><span class="w-lb">投图到屏幕</span></div></div></div><div class="w-foot">被控端:教室电脑 · 192.168.2.64</div></div></div>
<figure class="pcshot"><img src="/shot/pc-main.png" alt="ykxmz 电脑端首次设置界面" loading="lazy"><figcaption>电脑端:装完填个 6 位配对码就行</figcaption></figure>
</div>
</div></section>
<section id="how-connect"><div class="wrap">
<div class="sec-head">
<h2>怎么连上的</h2>
<p>同一个 WiFi 就走局域网直连,不同网络自动切中转</p>
</div>
<div class="flow">
<div class="flow-col">
<div class="flow-tag ok">同一个 WiFi</div>
<div class="flow-row">
<div class="node">⌚<span>手表</span></div>
<div class="link"><span class="ms">3 ms</span>
<div class="line"></div></div>
<div class="node">🖥<span>教室电脑</span></div>
</div>
<p>直连,不经过任何服务器。几十毫秒,画面基本跟手。</p>
</div>
<div class="flow-col">
<div class="flow-tag warn">不在同一个网络</div>
<div class="flow-row">
<div class="node">⌚<span>手表</span></div>
<div class="link"><div class="line"></div></div>
<div class="node relay">☁<span>中转</span></div>
<div class="link"><div class="line"></div></div>
<div class="node">🖥<span>电脑</span></div>
</div>
<p>两边都主动连到中转,绕过 NAT。办公室也能管教室。</p>
</div>
</div>
</div></section>
<section id="voices"><div class="wrap">
<div class="sec-head">
<h2>试过的老师怎么说</h2>
<p>教学场景下的试用反馈</p>
</div>
<div class="quotes"><figure class="quote"><span class="stars" aria-label="5 星">★★★★★</span><blockquote>以前上课放视频要走到讲台,现在手腕上点一下就放。最实用的是下课能直接关机,不用等学生走完再回去。</blockquote><figcaption><span class="avatar">王</span>班主任 · 试用</figcaption></figure><figure class="quote"><span class="stars" aria-label="5 星">★★★★★</span><blockquote>同一个 WiFi 的时候基本没延迟,看屏幕、传课件都跟本机差不多。机房换网段之后手表也能自己找回来。</blockquote><figcaption><span class="avatar">李</span>信息技术老师 · 试用</figcaption></figure><figure class="quote"><span class="stars" aria-label="5 星">★★★★★</span><blockquote>跨校区的时候延迟会高一些,但这个能理解 —— 走公网本来就要绕一圈。至少不用为了看一眼屏幕专门跑一趟。</blockquote><figcaption><span class="avatar">张</span>教务 · 试用</figcaption></figure></div>
</div></section>
<section class="alt" id="download"><div class="wrap">
<div class="sec-head">
<h2>下载</h2>
<p>当前版本 1.0.0</p>
</div>
<div class="dls"><div class="dl-card"><div class="dl-ico"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="2" y="4" width="20" height="13" rx="2"/><path d="M8 21h8M12 17v4"/></svg></div><div class="dl-head"><span class="dl-tag">电脑端</span><span class="dl-who">教室那台 Windows 电脑</span></div><div class="dl-note">装完自动后台运行</div><a class="dl-btn" href="/download/x-1.0.0.exe">下载 安装包</a><div class="dl-file">x-1.0.0.exe · 0 KB</div><div class="dl-req">Windows 10 / 11</div></div><div class="dl-card"><div class="dl-ico"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="6" y="6" width="12" height="12" rx="3"/><path d="M9 6V3h6v3M9 18v3h6v-3"/></svg></div><div class="dl-head"><span class="dl-tag">手表端</span><span class="dl-who">安卓手表</span></div><div class="dl-note">直接安装,不用 root</div><div class="dl-soon">暂未上传</div><div class="dl-req">Android 7.0+</div></div><div class="dl-card"><div class="dl-ico"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 2l8 4v6c0 5-3.5 8.5-8 10-4.5-1.5-8-5-8-10V6z"/></svg></div><div class="dl-head"><span class="dl-tag">服务器端</span><span class="dl-who">一台能上外网的小机器</span></div><div class="dl-note">只在跨网络时才需要</div><div class="dl-soon">暂未上传</div><div class="dl-req">Debian / Ubuntu</div></div></div>
</div></section>
<section id="faq"><div class="wrap">
<div class="sec-head"><h2>常见问题</h2></div>
<div class="faqs"><details class="faq"><summary>手表连不上电脑怎么办?<span class="faq-mark"></span></summary><div class="faq-body">先确认电脑上程序在运行(任务管理器里找 ykxmz.exe)。如果被控端窗口提示「防火墙未放行」,点旁边的一键修复。还是不行就跑一次网络自检 —— 电脑上打开工具箱选 3,然后手表上点「检查服务器」。</div></details><details class="faq"><summary>为什么显示「延迟 2000 毫秒」这么慢?<span class="faq-mark"></span></summary><div class="faq-body">跨网络时数据要绕到中转服务器再回来,延迟取决于你那台小机器的线路。如果手表和电脑在同一个 WiFi,会自动走局域网直连,延迟通常只有几十毫秒。</div></details><details class="faq"><summary>需要另外买服务器吗?<span class="faq-mark"></span></summary><div class="faq-body">只有一个教室用的话不需要 —— 手表和电脑连同一个 WiFi 就能直连。要在办公室管教室才需要一台能上外网的小机器当中转。</div></details><details class="faq"><summary>配对码忘了怎么办?<span class="faq-mark"></span></summary><div class="faq-body">电脑上双击程序图标打开窗口就能看到。也可以在窗口里改一个自己好记的。</div></details><details class="faq"><summary>手表重装了还能连上原来的电脑吗?<span class="faq-mark"></span></summary><div class="faq-body">能。重新输一次那个 6 位配对码就行 —— 配对码本身就是钥匙。</div></details><details class="faq"><summary>屏幕被别人看着,我能知道吗?<span class="faq-mark"></span></summary><div class="faq-body">能。只要有人在看你的屏幕,电脑右上角就会出现一条红色提示条,没有开关能关掉它。电脑前面的人随时可以点「停止共享」断开。</div></details></div>
</div></section>
<div class="endcta"><div class="wrap">
<h2>装一次,以后就不用管了</h2>
<p>配对一次之后,手表打开就自动连</p>
<a class="btn btn-p" href="#download">下载安装</a>
</div></div>
<footer><div class="wrap">
<div class="foot-in">
<div class="brand"><svg width="26" height="26" viewBox="0 0 32 32" fill="none" aria-hidden="true"><rect x="3" y="3" width="26" height="26" rx="8" fill="#0071e3"/><rect x="10" y="9" width="12" height="14" rx="4" stroke="#fff" stroke-width="2"/><path d="M13 9V6h6v3M13 23v3h6v-3" stroke="#fff" stroke-width="2" stroke-linecap="round"/></svg><span>ykxmz</span></div>
<div class="foot-links">
<a href="https://gitee.com/xmz7891/ykxmz" target="_blank" rel="noopener">源码</a>
<a href="https://gitee.com/xmz7891/ykxmz/releases" target="_blank" rel="noopener">历史版本</a>
<a href="#faq">常见问题</a>
</div>
</div>
<div class="copy">ykxmz · 用手表管教室那台电脑</div>
</div></footer>
<script>
// ---------------- 滚动淡入 ----------------
//
// ⚠ 顺序很重要:先把 .reveal 加上(这一步之后元素才是隐藏的),
// 再注册观察器。如果反过来,脚本报错时元素会被 CSS 永久隐藏。
// 所以整个东西包在 try 里,出错就什么都不加 —— 页面照常显示。
(function () {
if (!('IntersectionObserver' in window)) return; // 老浏览器:不做动画
try {
var reduce = window.matchMedia
&& window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (reduce) return; // 用户要求别动
var items = document.querySelectorAll(
'.feat, .step, .stat, .quote, .dl-card');
if (!items.length) return;
for (var i = 0; i < items.length; i++) items[i].classList.add('reveal');
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (en) {
if (en.isIntersecting) {
en.target.classList.add('in');
io.unobserve(en.target);
}
});
}, { rootMargin: '0px 0px -8% 0px', threshold: 0.08 });
for (var j = 0; j < items.length; j++) io.observe(items[j]);
// 兜底:1.2 秒后还没进视口的也显示出来(防止观察器失灵留下空白)
setTimeout(function () {
for (var k = 0; k < items.length; k++) items[k].classList.add('in');
}, 1200);
} catch (e) { /* 出错就不动,页面保持可见 */ }
})();
// ---------------- 锚点平滑滚动 ----------------
document.querySelectorAll('a[href^="#"]').forEach(function (a) {
a.addEventListener('click', function (e) {
var target = document.querySelector(a.getAttribute('href'));
if (target) { e.preventDefault(); target.scrollIntoView({behavior:'smooth'}); }
});
});
</script>
</body>
</html>