Files
Axi_Omron/docs/axiomron-pcbcheck-report-draft.html
yunxiao.zhu 07841fe4fe 📝 docs(report): 添加 AI 编程汇报材料
* 添加面向非技术听众的完整汇报稿与页面文案
* 提供明亮风格 HTML 演示页及调试情景交互
* 加入本地 WPF 运行截图、代码对比与测试证据
2026-08-01 16:43:57 +08:00

1255 lines
39 KiB
HTML
Raw 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" />
<meta name="theme-color" content="#f4f7fb" />
<title>3 个月,我从写 if-else 到 Vibe Coding</title>
<style>
:root {
--ink: #10233f;
--ink-soft: #40536d;
--muted: #6d7e92;
--canvas: #f4f7fb;
--surface: #ffffff;
--surface-soft: #edf4fa;
--line: #d9e3ee;
--primary: #0877bd;
--primary-dark: #075b91;
--primary-soft: #e4f3fb;
--teal: #0e8f83;
--teal-soft: #e2f5f1;
--orange: #d86b18;
--orange-soft: #fff0e3;
--danger: #c84343;
--danger-soft: #fdeaea;
--shadow: 0 18px 55px rgba(28, 58, 90, .10);
--font-sans: "Microsoft YaHei UI", "Microsoft YaHei", "Segoe UI", Arial, sans-serif;
--font-mono: "Cascadia Mono", Consolas, monospace;
}
* { box-sizing: border-box; }
html,
body {
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
background: var(--canvas);
}
body {
color: var(--ink);
font-family: var(--font-sans);
-webkit-font-smoothing: antialiased;
}
button { font: inherit; }
button:focus-visible {
outline: 3px solid rgba(8, 119, 189, .32);
outline-offset: 3px;
}
.progress-track {
position: fixed;
z-index: 50;
top: 0;
right: 0;
left: 0;
height: 5px;
background: #dfe8f1;
}
.progress-track span {
display: block;
width: 12.5%;
height: 100%;
background: linear-gradient(90deg, var(--primary), var(--teal));
transition: width .28s ease-out;
}
.brand-mark {
position: fixed;
z-index: 30;
top: 26px;
left: clamp(24px, 4vw, 64px);
display: flex;
align-items: center;
gap: 11px;
color: var(--ink-soft);
font-size: 12px;
font-weight: 700;
letter-spacing: .08em;
}
.brand-mark::before {
width: 30px;
height: 8px;
border-radius: 999px;
background: linear-gradient(90deg, var(--primary), var(--teal));
content: "";
}
.deck {
position: relative;
width: 100%;
height: 100dvh;
}
.slide {
position: absolute;
inset: 0;
display: grid;
grid-template-rows: 1fr auto;
min-height: 100%;
padding: clamp(72px, 8vh, 96px) clamp(28px, 7vw, 128px) clamp(84px, 10vh, 112px);
overflow: hidden;
opacity: 0;
pointer-events: none;
transform: translateX(34px);
transition: opacity .24s ease-out, transform .28s ease-out;
scrollbar-width: thin;
scrollbar-color: #b8c7d8 transparent;
}
.slide::before {
position: absolute;
z-index: -2;
top: -24%;
right: -10%;
width: min(50vw, 760px);
aspect-ratio: 1;
border-radius: 50%;
background: radial-gradient(circle, rgba(8, 119, 189, .10), transparent 68%);
content: "";
}
.slide::after {
position: absolute;
z-index: -2;
bottom: -30%;
left: -14%;
width: min(42vw, 650px);
aspect-ratio: 1;
border-radius: 50%;
background: radial-gradient(circle, rgba(14, 143, 131, .08), transparent 70%);
content: "";
}
.slide.is-active {
z-index: 2;
opacity: 1;
pointer-events: auto;
transform: translateX(0);
}
.slide-body {
align-self: center;
width: min(100%, 1280px);
margin: 0 auto;
}
.slide-footer {
display: flex;
align-items: center;
justify-content: space-between;
width: min(100%, 1280px);
margin: 28px auto 0;
color: var(--muted);
font-size: 12px;
font-weight: 600;
letter-spacing: .04em;
}
.slide-index {
color: var(--primary);
font-family: var(--font-mono);
}
.eyebrow {
display: flex;
align-items: center;
gap: 10px;
margin: 0 0 18px;
color: var(--primary);
font-family: var(--font-mono);
font-size: clamp(11px, .9vw, 14px);
font-weight: 700;
letter-spacing: .1em;
text-transform: uppercase;
}
.eyebrow::before {
width: 28px;
height: 2px;
background: currentColor;
content: "";
}
h1,
h2,
h3,
p { margin-top: 0; }
h1 {
max-width: 980px;
margin-bottom: 24px;
font-size: clamp(48px, 6.2vw, 92px);
line-height: 1.08;
letter-spacing: -.05em;
}
h2 {
max-width: 1050px;
margin-bottom: 28px;
font-size: clamp(36px, 4.2vw, 64px);
line-height: 1.16;
letter-spacing: -.04em;
}
h3 {
margin-bottom: 10px;
font-size: clamp(18px, 1.4vw, 22px);
line-height: 1.35;
}
.lede {
max-width: 820px;
margin-bottom: 0;
color: var(--ink-soft);
font-size: clamp(18px, 1.55vw, 24px);
line-height: 1.72;
}
.accent { color: var(--primary); }
.teal { color: var(--teal); }
.orange { color: var(--orange); }
.cover-grid {
display: grid;
grid-template-columns: minmax(0, 1.4fr) minmax(270px, .6fr);
gap: clamp(42px, 7vw, 110px);
align-items: end;
}
.cover-card {
padding: 28px;
border: 1px solid var(--line);
border-radius: 22px;
background: rgba(255, 255, 255, .92);
box-shadow: var(--shadow);
}
.cover-card .label,
.mini-label {
color: var(--muted);
font-family: var(--font-mono);
font-size: 11px;
font-weight: 700;
letter-spacing: .08em;
text-transform: uppercase;
}
.cover-card strong {
display: block;
margin: 12px 0 24px;
font-size: 27px;
line-height: 1.28;
}
.meta-row {
display: flex;
justify-content: space-between;
gap: 16px;
padding: 13px 0;
border-top: 1px solid var(--line);
color: var(--muted);
font-size: 13px;
}
.meta-row b { color: var(--ink); }
.compare-grid {
display: grid;
grid-template-columns: 1fr auto 1fr;
gap: 22px;
align-items: stretch;
margin-top: 34px;
}
.compare-card,
.project-card,
.level-card,
.debug-card,
.step-card,
.rule-card,
.takeaway-card {
border: 1px solid var(--line);
border-radius: 20px;
background: rgba(255, 255, 255, .94);
box-shadow: 0 12px 38px rgba(28, 58, 90, .07);
}
.compare-card { padding: 28px; }
.compare-card.is-now { border-color: #abd8ed; background: var(--primary-soft); }
.compare-card p {
margin: 0;
color: var(--ink-soft);
font-size: clamp(16px, 1.25vw, 20px);
line-height: 1.65;
}
.compare-arrow {
display: grid;
width: 54px;
place-items: center;
color: var(--primary);
font-size: 30px;
font-weight: 300;
}
.analogy {
display: flex;
align-items: center;
gap: 14px;
max-width: 890px;
margin-top: 24px;
padding: 16px 20px;
border-left: 4px solid var(--teal);
color: var(--ink-soft);
background: var(--teal-soft);
font-size: clamp(16px, 1.25vw, 20px);
line-height: 1.55;
}
.project-layout {
display: grid;
grid-template-columns: .78fr 1.22fr;
gap: clamp(32px, 6vw, 86px);
align-items: center;
}
.project-evidence-layout {
display: grid;
grid-template-columns: minmax(0, 1.35fr) minmax(310px, .65fr);
gap: 22px;
align-items: stretch;
}
.app-shot-card {
position: relative;
margin: 0;
padding: 10px;
overflow: hidden;
border: 1px solid var(--line);
border-radius: 20px;
background: var(--surface);
box-shadow: var(--shadow);
}
.app-shot-frame {
aspect-ratio: 16 / 8.75;
overflow: hidden;
border: 1px solid #cbd7e4;
border-radius: 13px;
background: #e9eff5;
}
.app-shot-frame img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
object-position: left top;
}
.shot-badge {
position: absolute;
top: 23px;
right: 23px;
padding: 7px 10px;
border: 1px solid rgba(255, 255, 255, .65);
border-radius: 999px;
color: #fff;
background: rgba(16, 35, 63, .82);
font-size: 11px;
font-weight: 800;
letter-spacing: .04em;
}
.app-shot-card figcaption {
display: flex;
align-items: center;
justify-content: space-between;
gap: 18px;
padding: 11px 7px 2px;
color: var(--muted);
font-size: 12px;
line-height: 1.45;
}
.app-shot-card figcaption b { color: var(--ink); }
.flow-title {
display: block;
margin-bottom: 10px;
color: var(--ink-soft);
font-size: 14px;
font-weight: 800;
}
.flow-list.compact { gap: 8px; }
.flow-list.compact .flow-item {
min-height: 54px;
padding: 8px 13px;
grid-template-columns: 38px 1fr;
}
.flow-list.compact .flow-no {
width: 32px;
height: 32px;
}
.flow-list.compact .flow-item b { font-size: 14px; }
.flow-list.compact .flow-item span:last-child { display: none; }
.project-summary {
padding: 30px;
border-left: 5px solid var(--primary);
background: var(--surface);
box-shadow: var(--shadow);
}
.project-summary strong {
display: block;
margin-bottom: 12px;
font-size: 26px;
}
.project-summary p {
margin: 0;
color: var(--ink-soft);
font-size: 17px;
line-height: 1.7;
}
.flow-list { display: grid; gap: 12px; }
.flow-item {
display: grid;
grid-template-columns: 46px 1fr auto;
gap: 16px;
align-items: center;
min-height: 68px;
padding: 13px 18px;
border: 1px solid var(--line);
border-radius: 15px;
background: var(--surface);
}
.flow-no {
display: grid;
width: 38px;
height: 38px;
place-items: center;
border-radius: 50%;
color: #fff;
background: var(--primary);
font-family: var(--font-mono);
font-size: 12px;
font-weight: 700;
}
.flow-item b { font-size: 17px; }
.flow-item span:last-child { color: var(--muted); font-size: 12px; font-weight: 700; }
.level-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 18px;
margin-top: 30px;
}
.level-card { position: relative; padding: 28px; overflow: hidden; }
.level-card::before {
position: absolute;
top: 0;
right: 0;
left: 0;
height: 5px;
background: var(--primary);
content: "";
}
.level-card:nth-child(2)::before { background: var(--teal); }
.level-card:nth-child(3)::before { background: var(--orange); }
.level-badge {
display: inline-block;
margin-bottom: 18px;
padding: 7px 11px;
border-radius: 999px;
color: var(--primary-dark);
background: var(--primary-soft);
font-size: 12px;
font-weight: 800;
}
.level-card:nth-child(2) .level-badge { color: #086a62; background: var(--teal-soft); }
.level-card:nth-child(3) .level-badge { color: #9c4a10; background: var(--orange-soft); }
.level-card p {
margin: 0;
color: var(--ink-soft);
font-size: 16px;
line-height: 1.65;
}
.level-footer {
margin-top: 22px;
color: var(--ink-soft);
font-size: clamp(16px, 1.35vw, 20px);
text-align: center;
}
.debug-layout {
display: grid;
grid-template-columns: .92fr 1.08fr;
gap: clamp(30px, 5vw, 72px);
align-items: center;
}
.bug-box {
padding: 26px;
border: 1px solid #efc7c7;
border-radius: 18px;
background: var(--danger-soft);
}
.bug-box strong {
display: block;
margin: 10px 0 16px;
color: #8b2e2e;
font-size: 24px;
}
.log-line {
margin: 7px 0 0;
color: #653d3d;
font-family: var(--font-mono);
font-size: 13px;
line-height: 1.55;
}
.mail-analogy {
margin: 18px 0 0;
padding: 18px 20px;
border-left: 4px solid var(--primary);
color: var(--ink-soft);
background: var(--primary-soft);
font-size: 17px;
line-height: 1.6;
}
.logic-compare {
display: grid;
grid-template-columns: .84fr 1.16fr;
gap: 12px;
}
.logic-panel {
min-height: 176px;
padding: 19px;
border: 1px solid var(--line);
border-radius: 16px;
background: var(--surface);
}
.logic-panel.is-wrong {
border-color: #efc7c7;
background: var(--danger-soft);
}
.logic-panel.is-right {
border-color: #b9dfd8;
background: var(--teal-soft);
}
.logic-panel pre {
margin: 14px 0 0;
white-space: pre-wrap;
color: var(--ink);
font-family: var(--font-mono);
font-size: clamp(11px, .86vw, 13px);
line-height: 1.75;
}
.debug-clue {
margin: 12px 0 0;
padding: 11px 14px;
border-left: 4px solid var(--orange);
color: #75401a;
background: var(--orange-soft);
font-family: var(--font-mono);
font-size: 12px;
line-height: 1.5;
}
.debug-card { overflow: hidden; }
.debug-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
padding: 18px 22px;
border-bottom: 1px solid var(--line);
background: #f9fbfd;
}
.status-dot {
display: inline-flex;
align-items: center;
gap: 8px;
color: var(--muted);
font-size: 12px;
font-weight: 700;
}
.status-dot::before {
width: 8px;
height: 8px;
border-radius: 50%;
background: #9cafc2;
content: "";
}
.debug-body { padding: 24px; }
.scenario-buttons {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
margin-bottom: 20px;
}
.scenario-button,
.nav-button {
min-height: 46px;
border: 1px solid var(--line);
border-radius: 12px;
color: var(--ink);
background: var(--surface);
cursor: pointer;
font-weight: 700;
transition: color .18s ease, background .18s ease, border-color .18s ease, transform .18s ease;
}
.scenario-button:hover,
.scenario-button.is-selected {
border-color: var(--primary);
color: #fff;
background: var(--primary);
}
.scenario-result {
min-height: 170px;
padding: 20px;
border: 1px solid var(--line);
border-radius: 14px;
background: #f8fafc;
}
.scenario-result h3 { margin-bottom: 12px; }
.result-line {
display: flex;
justify-content: space-between;
gap: 20px;
padding: 10px 0;
border-top: 1px solid var(--line);
color: var(--ink-soft);
font-size: 14px;
}
.result-line b { color: var(--ink); }
.method-grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 12px;
margin-top: 28px;
}
.step-card { padding: 22px 18px; }
.step-number {
display: block;
margin-bottom: 28px;
color: var(--primary);
font-family: var(--font-mono);
font-size: 28px;
font-weight: 800;
}
.step-card p {
margin: 0;
color: var(--ink-soft);
font-size: 14px;
line-height: 1.55;
}
.prompt-box {
margin: 0;
padding: 17px 22px;
border-left: 4px solid var(--teal);
color: #16524e;
background: var(--teal-soft);
font-size: clamp(15px, 1.15vw, 18px);
line-height: 1.6;
}
.evidence-row {
display: grid;
grid-template-columns: .9fr 1.1fr;
gap: 14px;
align-items: stretch;
margin-top: 20px;
}
.test-proof {
overflow: hidden;
border: 1px solid #cbd7e4;
border-radius: 14px;
color: #dcebf7;
background: #12243a;
box-shadow: 0 10px 28px rgba(18, 36, 58, .12);
}
.test-proof-head {
display: flex;
justify-content: space-between;
gap: 16px;
padding: 10px 14px;
border-bottom: 1px solid rgba(255, 255, 255, .12);
color: #99abc0;
font-family: var(--font-mono);
font-size: 10px;
font-weight: 700;
letter-spacing: .05em;
}
.test-proof-head b { color: #82dfc7; }
.test-row {
display: grid;
grid-template-columns: 46px 1fr;
gap: 10px;
align-items: center;
padding: 8px 14px;
border-top: 1px solid rgba(255, 255, 255, .08);
font-size: 12px;
line-height: 1.4;
}
.pass-label {
color: #82dfc7;
font-family: var(--font-mono);
font-size: 10px;
font-weight: 800;
}
.rule-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16px;
margin-top: 28px;
}
.rule-card {
display: grid;
grid-template-columns: 54px 1fr;
gap: 18px;
align-items: start;
padding: 22px;
}
.rule-no {
display: grid;
width: 48px;
height: 48px;
place-items: center;
border-radius: 14px;
color: var(--primary-dark);
background: var(--primary-soft);
font-family: var(--font-mono);
font-weight: 800;
}
.rule-card:nth-child(4) .rule-no { color: #973e0c; background: var(--orange-soft); }
.rule-card p {
margin: 0;
color: var(--ink-soft);
font-size: 15px;
line-height: 1.6;
}
.finish-layout {
display: grid;
grid-template-columns: 1.08fr .92fr;
gap: clamp(40px, 7vw, 108px);
align-items: center;
}
.finish-statement {
max-width: 760px;
color: var(--ink-soft);
font-size: clamp(20px, 1.7vw, 27px);
line-height: 1.65;
}
.takeaway-list { display: grid; gap: 14px; }
.takeaway-card {
padding: 22px 24px;
border-left: 5px solid var(--primary);
}
.takeaway-card:nth-child(2) { border-left-color: var(--teal); }
.takeaway-card:nth-child(3) { border-left-color: var(--orange); }
.takeaway-card b { display: block; margin-bottom: 6px; font-size: 18px; }
.takeaway-card span { color: var(--muted); font-size: 14px; line-height: 1.5; }
.deck-controls {
position: fixed;
z-index: 40;
right: clamp(20px, 3vw, 50px);
bottom: 24px;
display: flex;
align-items: center;
gap: 10px;
}
.nav-button {
min-width: 86px;
padding: 0 18px;
box-shadow: 0 8px 24px rgba(28, 58, 90, .08);
}
.nav-button.primary {
border-color: var(--primary);
color: #fff;
background: var(--primary);
}
.nav-button:hover { transform: translateY(-1px); }
.nav-button:disabled { opacity: .42; cursor: default; transform: none; }
.dots {
position: fixed;
z-index: 40;
bottom: 38px;
left: clamp(20px, 4vw, 64px);
display: flex;
gap: 8px;
}
.dot {
width: 9px;
height: 9px;
padding: 0;
border: 0;
border-radius: 50%;
background: #b9c8d7;
cursor: pointer;
transition: width .18s ease, border-radius .18s ease, background .18s ease;
}
.dot.is-active { width: 26px; border-radius: 999px; background: var(--primary); }
@media (max-width: 920px) {
html,
body { overflow: auto; }
.deck { min-height: 100dvh; }
.slide { position: relative; display: none; min-height: 100dvh; padding: 76px 24px 104px; overflow-x: hidden; overflow-y: auto; }
.slide.is-active { display: grid; }
.cover-grid,
.project-layout,
.project-evidence-layout,
.debug-layout,
.finish-layout { grid-template-columns: 1fr; }
.compare-grid { grid-template-columns: 1fr; }
.compare-arrow { width: auto; height: 30px; transform: rotate(90deg); }
.level-grid { grid-template-columns: 1fr; }
.method-grid { grid-template-columns: repeat(2, 1fr); }
.evidence-row { grid-template-columns: 1fr; }
.rule-grid { grid-template-columns: 1fr; }
.brand-mark { top: 22px; }
.slide-footer span:first-child { display: none; }
.slide-footer { justify-content: flex-end; }
}
@media (max-width: 560px) {
h1 { font-size: clamp(42px, 13vw, 64px); }
h2 { font-size: clamp(32px, 9vw, 46px); }
.method-grid,
.logic-compare,
.scenario-buttons { grid-template-columns: 1fr; }
.flow-item { grid-template-columns: 42px 1fr; }
.flow-item span:last-child { display: none; }
.slide-footer { display: none; }
.deck-controls { right: 16px; bottom: 18px; }
.dots { left: 16px; bottom: 31px; }
.nav-button { min-width: 66px; padding: 0 12px; }
}
@media (max-height: 800px) and (min-width: 921px) {
.slide { padding-top: 68px; padding-bottom: 76px; }
h1 { font-size: clamp(44px, 5.4vw, 76px); }
h2 { margin-bottom: 20px; font-size: clamp(32px, 3.7vw, 52px); }
.project-evidence-layout { grid-template-columns: minmax(0, 1.3fr) minmax(290px, .7fr); gap: 16px; }
.app-shot-frame { aspect-ratio: 16 / 7.15; }
.app-shot-card figcaption { padding-top: 7px; font-size: 11px; }
.flow-list.compact { gap: 6px; }
.flow-list.compact .flow-item { min-height: 46px; padding-top: 6px; padding-bottom: 6px; }
.level-card { padding: 22px; }
.method-grid { margin-top: 18px; }
.step-card { padding: 16px; }
.step-number { margin-bottom: 18px; }
.evidence-row { margin-top: 12px; }
.prompt-box { padding: 13px 16px; }
.test-row { padding-top: 6px; padding-bottom: 6px; }
.rule-grid { margin-top: 20px; }
.rule-card { padding: 17px; }
.slide-footer { margin-top: 16px; }
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
scroll-behavior: auto !important;
transition-duration: .01ms !important;
animation-duration: .01ms !important;
animation-iteration-count: 1 !important;
}
}
</style>
</head>
<body>
<div class="progress-track" aria-hidden="true"><span id="progressBar"></span></div>
<div class="brand-mark">AI PROGRAMMING · FIELD CASE</div>
<main class="deck" id="deck" aria-live="polite">
<section class="slide is-active" data-slide="0" aria-label="第 1 页:封面">
<div class="slide-body cover-grid">
<div>
<p class="eyebrow">3 MONTHS · ONE REAL PROJECT</p>
<h1>从写 <span class="orange">if-else</span><br>到 <span class="accent">Vibe Coding</span></h1>
<p class="lede">我如何用 AI 搭建一套 PCB 目检放行上位机,以及普通人怎样上手、调试和避坑。</p>
</div>
<aside class="cover-card" aria-label="汇报信息">
<span class="label">CASE STUDY</span>
<strong>AxiOmron<br>PCBCheck</strong>
<div class="meta-row"><span>项目</span><b>工业上位机</b></div>
<div class="meta-row"><span>重点</span><b>上手 · 调试 · 边界</b></div>
<div class="meta-row"><span>时长</span><b>8–10 MIN</b></div>
</aside>
</div>
<footer class="slide-footer"><span>一段真实的 AI 编程实践</span><span class="slide-index">01 / 08</span></footer>
</section>
<section class="slide" data-slide="1" aria-label="第 2 页:什么是 Vibe Coding">
<div class="slide-body">
<p class="eyebrow">01 / WHAT IS VIBE CODING</p>
<h2>改变的不是“要不要思考”,<br>而是<span class="accent">把时间花在哪里</span>。</h2>
<div class="compare-grid">
<article class="compare-card">
<span class="mini-label">过去</span>
<h3>自己翻译成每一行代码</h3>
<p>需求 → 查资料 → 写代码 → 运行 → 修改</p>
</article>
<div class="compare-arrow" aria-hidden="true">→</div>
<article class="compare-card is-now">
<span class="mini-label">现在</span>
<h3>先描述目标,再检查结果</h3>
<p>讲清需求 → AI 实现 → 我来验证 → 继续迭代</p>
</article>
</div>
<div class="analogy"><strong>一个简单比喻:</strong>像和一名速度很快的程序员结对工作——AI 负责加速,我负责方向与验收。</div>
</div>
<footer class="slide-footer"><span>Vibe Coding 不是一句话生成全部,而是持续对话与验证</span><span class="slide-index">02 / 08</span></footer>
</section>
<section class="slide" data-slide="2" aria-label="第 3 页:项目案例">
<div class="slide-body">
<p class="eyebrow">02 / THE PROJECT</p>
<h2>这不是概念图,<br><span class="teal">程序真的运行起来了</span>。</h2>
<div class="project-evidence-layout">
<figure class="app-shot-card">
<div class="app-shot-frame">
<img src="assets/axiomron-dashboard-report.png" width="2575" height="1407" alt="AxiOmron PCBCheck WPF 主界面,展示 PLC、扫码枪、文件校验、安灯、流程状态与运行日志" />
</div>
<span class="shot-badge">真实 WPF 运行界面</span>
<figcaption><b>设备状态、当前条码、流程和日志集中展示</b><span>本地展示环境 · 未连接真实设备</span></figcaption>
</figure>
<div>
<span class="flow-title">一块 PCB 的 5 步旅程</span>
<div class="flow-list compact" aria-label="PCB 放行流程">
<div class="flow-item"><span class="flow-no">01</span><b>PLC 通知 PCB 到位</b><span>START</span></div>
<div class="flow-item"><span class="flow-no">02</span><b>两把扫码枪读取条码</b><span>SCAN</span></div>
<div class="flow-item"><span class="flow-no">03</span><b>根据条码检查产品文件</b><span>CHECK</span></div>
<div class="flow-item"><span class="flow-no">04</span><b>发送结果并等待确认</b><span>ACK</span></div>
<div class="flow-item"><span class="flow-no">05</span><b>保存记录并回到空闲</b><span>DONE</span></div>
</div>
</div>
</div>
</div>
<footer class="slide-footer"><span>运行界面是本地证据,不等同于真实 PLC / SFTP 现场验收</span><span class="slide-index">03 / 08</span></footer>
</section>
<section class="slide" data-slide="3" aria-label="第 4 页:上手难度">
<div class="slide-body">
<p class="eyebrow">03 / HOW HARD IS IT</p>
<h2>上手不难,<br>难的是从“能跑”走到<span class="orange">“可靠”</span>。</h2>
<div class="level-grid">
<article class="level-card">
<span class="level-badge">门槛低</span>
<h3>做出原型</h3>
<p>会描述需求、会运行项目,就能很快看到第一个结果。</p>
</article>
<article class="level-card">
<span class="level-badge">需要方法</span>
<h3>做到可用</h3>
<p>要会拆小任务、补充上下文,并检查 AI 实际改了什么。</p>
</article>
<article class="level-card">
<span class="level-badge">仍需专业判断</span>
<h3>做到可靠</h3>
<p>需要理解业务风险,并验证断网、超时和错误输入等异常场景。</p>
</article>
</div>
<p class="level-footer"><strong>它降低的是写代码的门槛,</strong>没有消除软件工程本身的难度。</p>
</div>
<footer class="slide-footer"><span>有代码基础,上手会更快;没有代码基础,也可以从小工具开始</span><span class="slide-index">04 / 08</span></footer>
</section>
<section class="slide" data-slide="4" aria-label="第 5 页:真实调试案例">
<div class="slide-body debug-layout">
<div>
<p class="eyebrow">04 / A REAL DEBUGGING CASE</p>
<h2>信号写成功了,<br>为什么<span class="orange">文件不能删</span>?</h2>
<div class="logic-compare" aria-label="修改前后的代码逻辑对比">
<article class="logic-panel is-wrong">
<span class="mini-label">最初想法 · 有风险</span>
<pre><code>await WriteReleaseAsync();
await DeleteFileAsync();</code></pre>
</article>
<article class="logic-panel is-right">
<span class="mini-label">调试后 · 等待业务确认</span>
<pre><code>await WriteReleaseAsync();
if (ackReceived)
await DeleteFileAsync();</code></pre>
</article>
</div>
<p class="debug-clue">LOG 放行信号写入成功 → 等待 PLC 确认超时</p>
<p class="mail-analogy">像邮件显示“发送成功”,不代表对方已经阅读并执行。</p>
</div>
<section class="debug-card" aria-label="调试情景演示">
<div class="debug-head"><b>调试情景演示</b><span class="status-dot" id="scenarioStatus">等待选择</span></div>
<div class="debug-body">
<div class="scenario-buttons">
<button class="scenario-button" id="ackButton" type="button">收到 PLC 确认</button>
<button class="scenario-button" id="timeoutButton" type="button">等待确认超时</button>
</div>
<div class="scenario-result" id="scenarioResult">
<span class="mini-label">点击上方按钮</span>
<h3>比较两种结果</h3>
<div class="result-line"><span>PLC 业务结果</span><b>待确认</b></div>
<div class="result-line"><span>产品文件</span><b>保持不动</b></div>
</div>
</div>
</section>
</div>
<footer class="slide-footer"><span>调试结论:协议成功 ≠ 业务完成</span><span class="slide-index">05 / 08</span></footer>
</section>
<section class="slide" data-slide="5" aria-label="第 6 页:五步调试法">
<div class="slide-body">
<p class="eyebrow">05 / DEBUG WITH AI</p>
<h2>程序出错时,<br>我用这套<span class="accent">五步调试法</span>。</h2>
<div class="method-grid">
<article class="step-card"><span class="step-number">01</span><h3>先复现</h3><p>说明做了什么、期望什么、实际发生什么。</p></article>
<article class="step-card"><span class="step-number">02</span><h3>给证据</h3><p>提供报错、日志、配置和最近的修改。</p></article>
<article class="step-card"><span class="step-number">03</span><h3>讲流程</h3><p>先让 AI 解释调用过程,不急着修改。</p></article>
<article class="step-card"><span class="step-number">04</span><h3>小步改</h3><p>一次只处理一个原因,修改后立即运行。</p></article>
<article class="step-card"><span class="step-number">05</span><h3>正反测</h3><p>既测试成功,也测试超时、断网和错误输入。</p></article>
</div>
<div class="evidence-row">
<div class="prompt-box"><strong>我的常用提示:</strong>“先不要改代码。请根据日志找到调用流程,列出最可能的三个原因,以及如何逐个验证。”</div>
<section class="test-proof" aria-label="定向测试结果">
<div class="test-proof-head"><span>dotnet test · targeted</span><b>3 PASSED · 666 ms</b></div>
<div class="test-row"><span class="pass-label">PASS</span><span>收到 PLC 确认且开关开启 → 删除文件</span></div>
<div class="test-row"><span class="pass-label">PASS</span><span>等待 PLC 确认超时 → 保留文件</span></div>
<div class="test-row"><span class="pass-label">PASS</span><span>删除功能开关关闭 → 保留文件</span></div>
</section>
</div>
</div>
<footer class="slide-footer"><span>证据越完整,AI 越不容易靠猜</span><span class="slide-index">06 / 08</span></footer>
</section>
<section class="slide" data-slide="6" aria-label="第 7 页:注意事项">
<div class="slide-body">
<p class="eyebrow">06 / FOUR THINGS TO REMEMBER</p>
<h2>Vibe Coding 很快,<br>但这四条<span class="orange">不能省</span>。</h2>
<div class="rule-grid">
<article class="rule-card"><span class="rule-no">01</span><div><h3>任务要拆小</h3><p>每一步都应该能运行、能观察、能撤回。</p></div></article>
<article class="rule-card"><span class="rule-no">02</span><div><h3>修改要看懂</h3><p>至少确认改了哪些文件、为什么改、影响到哪里。</p></div></article>
<article class="rule-card"><span class="rule-no">03</span><div><h3>本地不等于现场</h3><p>模拟测试不能替代真实设备、真实网络和实际权限。</p></div></article>
<article class="rule-card"><span class="rule-no">04</span><div><h3>高风险动作默认关闭</h3><p>删除、付款、放行等动作必须有明确条件和可控开关。</p></div></article>
</div>
</div>
<footer class="slide-footer"><span>AI 可以给建议,但业务责任和最终判断仍然属于人</span><span class="slide-index">07 / 08</span></footer>
</section>
<section class="slide" data-slide="7" aria-label="第 8 页:总结">
<div class="slide-body finish-layout">
<div>
<p class="eyebrow">07 / TAKEAWAY</p>
<h2>上手不难,<br>真正的能力是<span class="accent">会验证</span>。</h2>
<p class="finish-statement">AI 没有让我不再需要技术,而是让我把更多时间放在理解问题、判断风险和验证结果上。</p>
</div>
<div class="takeaway-list">
<article class="takeaway-card"><b>会描述</b><span>把目标、条件和期望结果讲清楚</span></article>
<article class="takeaway-card"><b>会调试</b><span>用日志和测试逐步排除原因</span></article>
<article class="takeaway-card"><b>有边界</b><span>知道什么时候不能完全相信 AI</span></article>
</div>
</div>
<footer class="slide-footer"><span>谢谢 · AxiOmron.PcbCheck</span><span class="slide-index">08 / 08</span></footer>
</section>
</main>
<nav class="dots" id="dots" aria-label="汇报页面导航"></nav>
<div class="deck-controls" aria-label="翻页控制">
<button class="nav-button" id="previousButton" type="button">上一页</button>
<button class="nav-button primary" id="nextButton" type="button">下一页</button>
</div>
<script>
const slides = Array.from(document.querySelectorAll('.slide'));
const progressBar = document.getElementById('progressBar');
const dotsContainer = document.getElementById('dots');
const previousButton = document.getElementById('previousButton');
const nextButton = document.getElementById('nextButton');
const ackButton = document.getElementById('ackButton');
const timeoutButton = document.getElementById('timeoutButton');
const scenarioStatus = document.getElementById('scenarioStatus');
const scenarioResult = document.getElementById('scenarioResult');
let activeSlideIndex = 0;
/**
* 创建汇报页面圆点导航,并为每个圆点绑定跳转行为。
* @returns {void} 只更新页面导航结构,不返回数据。
*/
function createDots() {
slides.forEach((_, index) => {
const dot = document.createElement('button');
dot.type = 'button';
dot.className = 'dot';
dot.setAttribute('aria-label', `跳转到第 ${index + 1} 页`);
dot.addEventListener('click', () => setSlide(index));
dotsContainer.appendChild(dot);
});
}
/**
* 切换到指定汇报页面,并同步进度条、圆点状态与翻页按钮状态。
* @param {number} index 目标页面的零基索引,超出范围时会自动限制到有效区间。
* @returns {void} 只更新当前页面状态,不返回数据。
*/
function setSlide(index) {
activeSlideIndex = Math.max(0, Math.min(slides.length - 1, index));
slides.forEach((slide, slideIndex) => {
const isActive = slideIndex === activeSlideIndex;
slide.classList.toggle('is-active', isActive);
slide.setAttribute('aria-hidden', String(!isActive));
});
Array.from(dotsContainer.children).forEach((dot, dotIndex) => {
const isActive = dotIndex === activeSlideIndex;
dot.classList.toggle('is-active', isActive);
dot.setAttribute('aria-current', isActive ? 'page' : 'false');
});
progressBar.style.width = `${((activeSlideIndex + 1) / slides.length) * 100}%`;
previousButton.disabled = activeSlideIndex === 0;
nextButton.disabled = activeSlideIndex === slides.length - 1;
}
/**
* 按指定方向移动汇报页面。
* @param {number} offset 页面偏移量,正数向后,负数向前。
* @returns {void} 通过调用页面切换函数更新界面。
*/
function moveSlide(offset) {
setSlide(activeSlideIndex + offset);
}
/**
* 展示“收到 PLC 确认”的调试情景,说明确认后才允许执行文件删除。
* @returns {void} 只更新情景卡片的可视内容和按钮状态。
*/
function showAcknowledgedScenario() {
ackButton.classList.add('is-selected');
timeoutButton.classList.remove('is-selected');
scenarioStatus.textContent = '业务已确认';
scenarioResult.innerHTML = `
<span class="mini-label">情景 A · 收到确认</span>
<h3 class="teal">允许执行后续动作</h3>
<div class="result-line"><span>PLC 业务结果</span><b>已确认放行</b></div>
<div class="result-line"><span>产品文件</span><b>按配置安全删除</b></div>`;
}
/**
* 展示“PLC 确认超时”的调试情景,说明协议写入成功时仍需保留产品文件。
* @returns {void} 只更新情景卡片的可视内容和按钮状态。
*/
function showTimeoutScenario() {
timeoutButton.classList.add('is-selected');
ackButton.classList.remove('is-selected');
scenarioStatus.textContent = '确认超时';
scenarioResult.innerHTML = `
<span class="mini-label">情景 B · 确认超时</span>
<h3 class="orange">停止危险的后续动作</h3>
<div class="result-line"><span>PLC 业务结果</span><b>未得到确认</b></div>
<div class="result-line"><span>产品文件</span><b>保留,不删除</b></div>`;
}
previousButton.addEventListener('click', () => moveSlide(-1));
nextButton.addEventListener('click', () => moveSlide(1));
ackButton.addEventListener('click', showAcknowledgedScenario);
timeoutButton.addEventListener('click', showTimeoutScenario);
document.addEventListener('keydown', event => {
if (event.target instanceof HTMLButtonElement) return;
if (event.key === 'ArrowRight' || event.key === 'PageDown' || event.key === ' ') moveSlide(1);
if (event.key === 'ArrowLeft' || event.key === 'PageUp') moveSlide(-1);
if (event.key === 'Home') setSlide(0);
if (event.key === 'End') setSlide(slides.length - 1);
});
createDots();
setSlide(0);
</script>
</body>
</html>