Skip to content

Commit 6a3ec46

Browse files
committed
ux(web): web端展示重做为完整产品页(UI/产品/增长) v0.7.16
- 裸表单→产品页:顶栏(logo+Star)+价值hero+体检卡+「查什么」四宫格+信任栏+页脚 - 3秒看懂是什么/查什么/安不安全;增长钩子Star/示例/公众号;移动端响应式 - 保留统一路径栏+扫描遮罩
1 parent af6a971 commit 6a3ec46

3 files changed

Lines changed: 89 additions & 51 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/),
66
and this project adheres to [Semantic Versioning](https://semver.org/).
77

8+
## [0.7.16] - 2026-06-21
9+
10+
### Changed — web 端展示重做(UI/产品/增长)
11+
- 本地客户端从"裸表单"升级为**完整产品页**:顶栏(logo+Star) + 价值主张 hero(标签+大标题+副述) + 体检卡片 + **「查什么」四宫格**(数据出境/密钥/个人信息/.env) + **信任栏**(不出本机/零依赖/开源/中文优先) + 页脚(公众号/GitHub)
12+
- 3 秒看懂"是什么、查什么、安不安全";增长钩子:Star 按钮、示例演示、公众号
13+
- 移动端响应式(四宫格→两列);保留统一路径栏 + 扫描遮罩
14+
815
## [0.7.15] - 2026-06-21
916

1017
### Changed — 本地客户端体验重做(用户反馈"体验不好")

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "shellward",
3-
"version": "0.7.15",
3+
"version": "0.7.16",
44
"mcpName": "io.github.jnMetaCode/shellward",
55
"description": "AI agent security & MCP security middleware — prompt injection detection, AI firewall, runtime guardrails & data-loss prevention for LLM tool calls. 8-layer defense against data exfiltration & dangerous commands. Zero dependencies. SDK + OpenClaw plugin. Supports LangChain, AutoGPT, Claude Code, Cursor, OpenAI Agents, Hermes Agent.",
66
"keywords": [

src/web/scan-server.ts

Lines changed: 81 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -283,15 +283,42 @@ function formPage(local: boolean): string {
283283
<details class="alt"><summary>或:体检公开仓库 URL</summary>${urlForm}</details>` : ''
284284

285285
return page('ShellWard 合规体检', `
286-
<div class="hero">
287-
<div class="logo">🛡️ Shell<span>Ward</span> 合规网关</div>
288-
<h1>AI 应用合规体检</h1>
289-
<p class="sub">${local ? '选你的项目,' : '贴公开仓库链接,'}30 秒查出数据出境 / 硬编码密钥 / 个人信息暴露等中国合规红线。</p>
290-
${local ? localForms : urlForm}
286+
<nav class="nav">
287+
<div class="logo">🛡️ Shell<span>Ward</span> <em>合规网关</em></div>
288+
<a class="ghbtn" href="https://github.com/jnMetaCode/shellward" target="_blank">★ GitHub Star</a>
289+
</nav>
290+
<main class="wrap">
291+
<header class="hd">
292+
<div class="tag">网安法 2026 · PIPL · 等保2.0 · 数据出境 · AI标识</div>
293+
<h1>30 秒,查出你的 AI 项目<br>踩了哪些 <span class="hl">中国合规红线</span></h1>
294+
<p class="sub">数据出境 · 硬编码密钥 · 个人信息暴露 —— 精确到 <code>文件:行</code>,并给出境内替代建议。${local ? '<b>私有代码不出本机。</b>' : ''}</p>
295+
</header>
296+
297+
<section class="card">
298+
${local ? localForms : urlForm}
299+
</section>
300+
301+
<section class="checks">
302+
<div class="chk"><span>🌐</span><b>数据出境</b><i>境外大模型端点/SDK</i></div>
303+
<div class="chk"><span>🔑</span><b>硬编码密钥</b><i>OpenAI/GitHub/AWS…</i></div>
304+
<div class="chk"><span>🪪</span><b>个人信息</b><i>身份证/手机/银行卡</i></div>
305+
<div class="chk"><span>📂</span><b>.env 暴露</b><i>权限/明文密钥</i></div>
306+
</section>
307+
291308
<p class="demo">🤔 想先看效果? <a href="/demo">▶ 看一个含风险的示例报告</a></p>
292-
<p class="foot">网安法 2026 · PIPL · 等保2.0 · 数据出境 · AI标识 | 零依赖 · 开源 ·
293-
<a href="https://github.com/jnMetaCode/shellward">GitHub ⭐</a></p>
294-
</div>
309+
310+
<section class="trust">
311+
<div><b>🔒 ${local ? '不出本机' : '不存储代码'}</b>${local ? '服务端直读本机,零上传' : '公开仓库浅克隆,用完即删'}</div>
312+
<div><b>📦 零依赖</b>可在信创/离线环境跑</div>
313+
<div><b>⚖️ 开源</b>Apache-2.0,代码全公开</div>
314+
<div><b>🇨🇳 中文优先</b>为中国监管而生</div>
315+
</section>
316+
317+
<footer class="ft">
318+
公众号「AI不止语」· 技术问答 · 实战文章&nbsp;&nbsp;|&nbsp;&nbsp;
319+
<a href="https://github.com/jnMetaCode/shellward" target="_blank">github.com/jnMetaCode/shellward</a> · Apache-2.0
320+
</footer>
321+
</main>
295322
<div id="overlay" class="overlay"><div class="spin"></div><div id="ovtext">扫描中…</div></div>
296323
${local ? BROWSE_SCRIPT : ''}`)
297324
}
@@ -366,55 +393,59 @@ function page(title: string, body: string): string {
366393
return `<!DOCTYPE html><html lang="zh-CN"><head><meta charset="utf-8">
367394
<meta name="viewport" content="width=device-width,initial-scale=1"><title>${esc(title)}</title>
368395
<style>
369-
*{box-sizing:border-box}body{margin:0;min-height:100vh;display:grid;place-items:center;
370-
background:linear-gradient(135deg,#eef1f6,#e2e8f0);color:#0f172a;
396+
*{box-sizing:border-box}
397+
body{margin:0;min-height:100vh;background:linear-gradient(180deg,#f4f7fb,#e8edf4);color:#0f172a;
371398
font:16px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif}
372-
.hero{background:#fff;max-width:580px;width:92%;margin:40px;padding:38px 40px 34px;border-radius:18px;
373-
box-shadow:0 12px 40px rgba(15,23,42,.12);text-align:center;border-top:4px solid #cb0000}
374-
.logo{font-weight:800;font-size:15px;letter-spacing:.2px}.logo span{color:#cb0000}
375-
h1{font-size:29px;margin:12px 0 8px;letter-spacing:-.5px}
376-
.sub{color:#64748b;margin:0 0 24px;font-size:15px}
399+
a{color:#cb0000;text-decoration:none}
400+
.nav{display:flex;justify-content:space-between;align-items:center;max-width:760px;margin:0 auto;padding:18px 24px}
401+
.logo{font-weight:800;font-size:17px}.logo span{color:#cb0000}
402+
.logo em{font-style:normal;color:#94a3b8;font-weight:600;font-size:13px;margin-left:5px}
403+
.ghbtn{border:1px solid #cbd5e1;border-radius:8px;padding:7px 14px;font-size:13px;font-weight:700;color:#0f172a;background:#fff;transition:.15s}
404+
.ghbtn:hover{border-color:#cb0000;color:#cb0000}
405+
.wrap{max-width:760px;margin:0 auto;padding:0 24px 48px}
406+
.hd{text-align:center;padding:22px 0 26px}
407+
.tag{display:inline-block;background:#fef2f2;color:#cb0000;font-size:12px;font-weight:700;padding:5px 14px;border-radius:999px;margin-bottom:16px}
408+
h1{font-size:34px;line-height:1.25;margin:0 0 12px;letter-spacing:-.6px}
409+
h1 .hl{color:#cb0000}
410+
.sub{color:#475569;font-size:16px;max-width:580px;margin:0 auto}
411+
.sub code{background:#eef2f7;padding:1px 6px;border-radius:5px;font-size:14px}
412+
.card{background:#fff;border-radius:16px;padding:24px 26px;box-shadow:0 10px 30px rgba(15,23,42,.10);border-top:3px solid #cb0000}
377413
form{display:flex;flex-direction:column;gap:10px;text-align:left}
378414
label{font-size:13px;font-weight:700;color:#334155}
379-
input{padding:14px 16px;border:1px solid #cbd5e1;border-radius:10px;font-size:16px;width:100%}
415+
input{padding:14px 16px;border:1px solid #cbd5e1;border-radius:10px;font-size:15px;width:100%}
380416
input:focus{outline:none;border-color:#cb0000;box-shadow:0 0 0 3px rgba(203,0,0,.12)}
381-
.hint{font-size:12.5px;color:#64748b;margin:2px 0 6px;line-height:1.55}
382-
.hint code{background:#f1f5f9;padding:1px 6px;border-radius:5px}
383-
/* 文件选择器:美化成虚线投放区 + 红色按钮 */
384-
input[type=file]{width:100%;padding:20px 16px;border:2px dashed #cbd5e1;border-radius:12px;
385-
background:#f8fafc;cursor:pointer;font-size:14px;color:#64748b;transition:.15s}
386-
input[type=file]:hover{border-color:#cb0000;background:#fff}
387-
input[type=file]::file-selector-button{background:#cb0000;color:#fff;border:0;border-radius:8px;
388-
padding:9px 18px;margin-right:14px;font-weight:700;font-size:14px;cursor:pointer}
389-
input[type=file]::file-selector-button:hover{background:#a80000}
390-
button{background:#cb0000;color:#fff;border:0;border-radius:10px;padding:14px;font-size:16px;
391-
font-weight:700;cursor:pointer;margin-top:4px;transition:.15s}button:hover{background:#a80000}
392-
button:disabled{background:#94a3b8;cursor:default}
393-
form{margin:0 0 14px}.or{text-align:center;color:#94a3b8;font-size:13px;margin:6px 0 14px}
394-
.status{display:none;margin:10px 0 0;padding:10px 14px;border-radius:8px;background:#f1f5f9;
395-
color:#334155;font-size:13.5px;border-left:3px solid #cb0000;text-align:left}
396-
.pathrow{display:flex;gap:8px}
417+
button{background:#cb0000;color:#fff;border:0;border-radius:10px;padding:14px;font-size:16px;font-weight:700;cursor:pointer;transition:.15s}
418+
button:hover{background:#a80000}button:disabled{background:#94a3b8;cursor:default}
419+
.hint{font-size:12.5px;color:#64748b;margin:8px 0 0;line-height:1.55}
420+
code,.hint code{background:#eef2f7;padding:1px 6px;border-radius:5px;font-size:12.5px}
421+
.pathrow{display:flex;gap:8px;margin-top:6px}
397422
.pathrow input{flex:1;font-family:ui-monospace,Menlo,monospace;font-size:13px}
398-
.pathrow button{margin-top:0;white-space:nowrap;padding:14px 22px}
399-
.demo{margin:18px 0 0;font-size:13px;color:#475569}.demo a{font-weight:600}
400-
.overlay{display:none;position:fixed;inset:0;background:rgba(15,23,42,.55);z-index:99;
423+
.pathrow button{padding:14px 22px;white-space:nowrap}
424+
.browser{border:1px solid #e2e8f0;border-radius:10px;overflow:hidden;margin:10px 0 0;text-align:left}
425+
.dirs{list-style:none;margin:0;padding:0;max-height:200px;overflow-y:auto}
426+
.dirs li{padding:9px 14px;border-top:1px solid #eef2f7;cursor:pointer;font-size:14px}
427+
.dirs li:first-child{border-top:0}.dirs li:hover{background:#f8fafc}
428+
.dirs li.up{color:#cb0000;font-weight:600}.dirs li.empty{color:#94a3b8;cursor:default;font-size:13px}
429+
details.alt{margin:14px 0 0;border-top:1px dashed #e2e8f0;padding-top:12px}
430+
details.alt summary{cursor:pointer;color:#cb0000;font-size:13px;font-weight:600}
431+
details.alt[open] summary{margin-bottom:10px}
432+
.checks{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin:22px 0}
433+
.chk{background:#fff;border:1px solid #eef2f7;border-radius:12px;padding:16px 10px;text-align:center}
434+
.chk span{font-size:24px;display:block;margin-bottom:6px}
435+
.chk b{display:block;font-size:14px}.chk i{font-style:normal;color:#94a3b8;font-size:11px;display:block;margin-top:3px}
436+
.demo{text-align:center;font-size:13.5px;color:#475569;margin:6px 0 22px}.demo a{font-weight:700}
437+
.trust{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin:0 0 26px}
438+
.trust div{background:#f8fafc;border-radius:10px;padding:14px 12px;font-size:11.5px;color:#64748b;line-height:1.5}
439+
.trust b{display:block;color:#0f172a;font-size:13px;margin-bottom:3px}
440+
.ft{text-align:center;color:#94a3b8;font-size:12.5px;padding-top:14px;border-top:1px solid #e3e9f1}
441+
.overlay{display:none;position:fixed;inset:0;background:rgba(15,23,42,.6);z-index:99;
401442
flex-direction:column;align-items:center;justify-content:center;color:#fff;gap:16px;font-size:15px;font-weight:600}
402-
.spin{width:46px;height:46px;border:4px solid rgba(255,255,255,.25);border-top-color:#fff;
403-
border-radius:50%;animation:sp .8s linear infinite}
443+
.spin{width:46px;height:46px;border:4px solid rgba(255,255,255,.25);border-top-color:#fff;border-radius:50%;animation:sp .8s linear infinite}
404444
@keyframes sp{to{transform:rotate(360deg)}}
405-
details.alt{margin:6px 0 10px;text-align:left}
406-
details.alt summary{cursor:pointer;color:#cb0000;font-size:13px;font-weight:600;padding:6px 0}
407-
details.alt[open] summary{margin-bottom:8px}
408-
.browser{border:1px solid #cbd5e1;border-radius:10px;overflow:hidden;margin:4px 0 10px;text-align:left}
409-
.bpath{background:#0f172a;color:#93c5fd;font-family:ui-monospace,Menlo,monospace;font-size:12px;
410-
padding:9px 12px;word-break:break-all}
411-
.dirs{list-style:none;margin:0;padding:0;max-height:240px;overflow-y:auto}
412-
.dirs li{padding:9px 14px;border-top:1px solid #eef2f7;cursor:pointer;font-size:14px}
413-
.dirs li:hover{background:#f1f5f9}
414-
.dirs li.up{color:#cb0000;font-weight:600}
415-
.dirs li.empty{color:#94a3b8;cursor:default;font-size:13px}
416-
.foot{margin:24px 0 0;font-size:12.5px;color:#94a3b8}.foot a,.back{color:#cb0000;text-decoration:none}
417-
.back{font-weight:600}
445+
/* 错误页复用 */
446+
.hero{background:#fff;max-width:520px;margin:60px auto;padding:36px;border-radius:16px;box-shadow:0 10px 30px rgba(15,23,42,.1);text-align:center}
447+
.hero .logo{font-size:15px}.back{font-weight:600}
448+
@media(max-width:560px){h1{font-size:26px}.checks,.trust{grid-template-columns:repeat(2,1fr)}}
418449
</style></head><body>${body}</body></html>`
419450
}
420451

0 commit comments

Comments
 (0)