965 lines
32 KiB
HTML
965 lines
32 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>古法代码之王 · 全世界 AI 崩溃后一位古法程序员的逆袭</title>
|
||
<meta name="description" content="一部近未来科幻爽文:当全世界把写代码交给 AI,只有一个被时代淘汰的人,还记得如何真正让系统运转。">
|
||
<meta property="og:title" content="古法代码之王">
|
||
<meta property="og:description" content="全世界 AI 崩溃后,一位被时代淘汰的程序员,独自把文明重新点亮。">
|
||
<meta property="og:image" content="./images/protagonist_reference.jpg">
|
||
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect fill='%230a0b10' width='100' height='100'/%3E%3Ctext x='50' y='68' font-size='60' text-anchor='middle' fill='%23c9a357' font-family='serif'%3E王%3C/text%3E%3C/svg%3E">
|
||
<style>
|
||
:root {
|
||
--bg: #0a0b10;
|
||
--bg-soft: #12141c;
|
||
--bg-card: #171923;
|
||
--border: #252836;
|
||
--fg: #e8e8ec;
|
||
--fg-soft: #a8aab4;
|
||
--fg-dim: #6e7080;
|
||
--gold: #c9a357;
|
||
--gold-soft: #8d7035;
|
||
--blue: #6a8aad;
|
||
--red: #c45a4d;
|
||
}
|
||
* { box-sizing: border-box; }
|
||
html, body {
|
||
margin: 0; padding: 0;
|
||
background: var(--bg);
|
||
color: var(--fg);
|
||
font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Microsoft YaHei', 'Source Han Sans SC', sans-serif;
|
||
font-size: 16px;
|
||
line-height: 1.75;
|
||
-webkit-font-smoothing: antialiased;
|
||
text-rendering: optimizeLegibility;
|
||
}
|
||
body { overflow-x: hidden; }
|
||
a { color: var(--gold); text-decoration: none; }
|
||
a:hover { color: var(--fg); }
|
||
img { max-width: 100%; display: block; }
|
||
|
||
/* ---------- Hero ---------- */
|
||
.hero {
|
||
position: relative;
|
||
min-height: 100vh;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
overflow: hidden;
|
||
padding: 40px 20px;
|
||
}
|
||
.hero::before {
|
||
content: '';
|
||
position: absolute;
|
||
inset: 0;
|
||
background:
|
||
radial-gradient(ellipse at center, rgba(201,163,87,0.08) 0%, transparent 60%),
|
||
linear-gradient(180deg, #05060a 0%, var(--bg) 100%);
|
||
z-index: 0;
|
||
}
|
||
.hero-portrait {
|
||
position: absolute;
|
||
right: -10%;
|
||
top: 0;
|
||
bottom: 0;
|
||
width: 70%;
|
||
background-image: url('./images/protagonist_reference.jpg');
|
||
background-size: cover;
|
||
background-position: center right;
|
||
opacity: 0.22;
|
||
filter: grayscale(30%) contrast(1.05);
|
||
mask-image: linear-gradient(90deg, transparent 0%, black 55%);
|
||
-webkit-mask-image: linear-gradient(90deg, transparent 0%, black 55%);
|
||
z-index: 1;
|
||
}
|
||
.hero-inner {
|
||
position: relative;
|
||
z-index: 2;
|
||
max-width: 820px;
|
||
width: 100%;
|
||
}
|
||
.hero-kicker {
|
||
color: var(--gold);
|
||
font-size: 13px;
|
||
letter-spacing: 0.4em;
|
||
text-transform: uppercase;
|
||
margin-bottom: 32px;
|
||
padding-left: 24px;
|
||
position: relative;
|
||
}
|
||
.hero-kicker::before {
|
||
content: '';
|
||
position: absolute;
|
||
left: 0; top: 50%;
|
||
width: 16px; height: 1px;
|
||
background: var(--gold);
|
||
}
|
||
.hero-title {
|
||
font-family: 'Songti SC', 'Noto Serif CJK SC', 'Source Han Serif SC', serif;
|
||
font-weight: 700;
|
||
font-size: clamp(56px, 11vw, 132px);
|
||
line-height: 1.05;
|
||
margin: 0 0 28px;
|
||
letter-spacing: 0.04em;
|
||
background: linear-gradient(180deg, #f2e4b8 0%, var(--gold) 50%, var(--gold-soft) 100%);
|
||
-webkit-background-clip: text;
|
||
background-clip: text;
|
||
color: transparent;
|
||
text-shadow: 0 4px 40px rgba(201,163,87,0.15);
|
||
}
|
||
.hero-subtitle {
|
||
font-size: clamp(16px, 2.4vw, 22px);
|
||
color: var(--fg-soft);
|
||
max-width: 620px;
|
||
line-height: 1.8;
|
||
margin: 0 0 12px;
|
||
}
|
||
.hero-tagline {
|
||
font-family: 'Songti SC', 'Noto Serif CJK SC', serif;
|
||
font-size: clamp(18px, 2.4vw, 24px);
|
||
color: var(--fg);
|
||
line-height: 1.8;
|
||
font-style: italic;
|
||
border-left: 2px solid var(--gold);
|
||
padding-left: 20px;
|
||
margin: 36px 0 48px;
|
||
max-width: 620px;
|
||
}
|
||
.hero-meta {
|
||
display: flex;
|
||
gap: 40px;
|
||
flex-wrap: wrap;
|
||
color: var(--fg-dim);
|
||
font-size: 13px;
|
||
letter-spacing: 0.2em;
|
||
}
|
||
.hero-meta span strong {
|
||
display: block;
|
||
color: var(--fg);
|
||
font-size: 22px;
|
||
font-weight: 600;
|
||
letter-spacing: 0;
|
||
margin-top: 4px;
|
||
font-family: 'Songti SC', serif;
|
||
}
|
||
.hero-cta {
|
||
margin-top: 48px;
|
||
display: flex;
|
||
gap: 16px;
|
||
flex-wrap: wrap;
|
||
}
|
||
.btn {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
padding: 14px 28px;
|
||
border: 1px solid var(--border);
|
||
border-radius: 0;
|
||
background: transparent;
|
||
color: var(--fg);
|
||
font-size: 14px;
|
||
letter-spacing: 0.2em;
|
||
cursor: pointer;
|
||
transition: all 0.25s ease;
|
||
font-family: inherit;
|
||
}
|
||
.btn:hover { border-color: var(--gold); color: var(--gold); }
|
||
.btn.primary { border-color: var(--gold); color: var(--gold); }
|
||
.btn.primary:hover { background: var(--gold); color: var(--bg); }
|
||
.hero-scroll {
|
||
position: absolute;
|
||
bottom: 32px;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
color: var(--fg-dim);
|
||
font-size: 11px;
|
||
letter-spacing: 0.4em;
|
||
z-index: 2;
|
||
animation: pulse 2.4s ease infinite;
|
||
}
|
||
@keyframes pulse {
|
||
0%, 100% { opacity: 0.4; transform: translate(-50%, 0); }
|
||
50% { opacity: 1; transform: translate(-50%, 6px); }
|
||
}
|
||
|
||
/* ---------- Section shared ---------- */
|
||
section {
|
||
padding: 120px 24px;
|
||
position: relative;
|
||
}
|
||
.container {
|
||
max-width: 1100px;
|
||
margin: 0 auto;
|
||
}
|
||
.container-reading {
|
||
max-width: 780px;
|
||
margin: 0 auto;
|
||
}
|
||
.eyebrow {
|
||
color: var(--gold);
|
||
font-size: 12px;
|
||
letter-spacing: 0.4em;
|
||
text-transform: uppercase;
|
||
margin-bottom: 16px;
|
||
}
|
||
.section-title {
|
||
font-family: 'Songti SC', serif;
|
||
font-size: clamp(32px, 5vw, 56px);
|
||
font-weight: 700;
|
||
margin: 0 0 48px;
|
||
line-height: 1.2;
|
||
}
|
||
|
||
/* ---------- About / Synopsis ---------- */
|
||
.about { background: var(--bg-soft); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
|
||
.about-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 80px;
|
||
align-items: start;
|
||
}
|
||
.about-text p {
|
||
color: var(--fg-soft);
|
||
margin: 0 0 20px;
|
||
line-height: 1.9;
|
||
}
|
||
.about-text p:first-of-type::first-letter {
|
||
float: left;
|
||
font-family: 'Songti SC', serif;
|
||
font-size: 64px;
|
||
line-height: 0.9;
|
||
padding: 8px 12px 0 0;
|
||
color: var(--gold);
|
||
font-weight: 700;
|
||
}
|
||
.about-stats {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 32px;
|
||
padding: 40px;
|
||
background: var(--bg-card);
|
||
border: 1px solid var(--border);
|
||
}
|
||
.stat-num {
|
||
font-family: 'Songti SC', serif;
|
||
font-size: 48px;
|
||
color: var(--gold);
|
||
line-height: 1;
|
||
font-weight: 700;
|
||
margin-bottom: 8px;
|
||
}
|
||
.stat-label {
|
||
color: var(--fg-dim);
|
||
font-size: 12px;
|
||
letter-spacing: 0.3em;
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
/* ---------- Characters ---------- */
|
||
.characters { background: var(--bg); }
|
||
.char-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
|
||
gap: 24px;
|
||
margin-top: 40px;
|
||
}
|
||
.char-card {
|
||
padding: 32px 28px;
|
||
background: var(--bg-card);
|
||
border: 1px solid var(--border);
|
||
transition: all 0.3s ease;
|
||
}
|
||
.char-card:hover {
|
||
border-color: var(--gold-soft);
|
||
transform: translateY(-2px);
|
||
}
|
||
.char-role {
|
||
color: var(--gold);
|
||
font-size: 11px;
|
||
letter-spacing: 0.3em;
|
||
text-transform: uppercase;
|
||
margin-bottom: 10px;
|
||
}
|
||
.char-name {
|
||
font-family: 'Songti SC', serif;
|
||
font-size: 26px;
|
||
font-weight: 700;
|
||
margin: 0 0 16px;
|
||
}
|
||
.char-desc {
|
||
color: var(--fg-soft);
|
||
font-size: 14px;
|
||
line-height: 1.8;
|
||
margin: 0;
|
||
}
|
||
|
||
/* ---------- Chapters list ---------- */
|
||
.chapters { background: var(--bg-soft); border-top: 1px solid var(--border); }
|
||
.volume-heading {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 20px;
|
||
margin: 72px 0 32px;
|
||
color: var(--gold);
|
||
font-family: 'Songti SC', serif;
|
||
font-size: 22px;
|
||
font-weight: 700;
|
||
}
|
||
.volume-heading::before, .volume-heading::after {
|
||
content: '';
|
||
flex: 1;
|
||
height: 1px;
|
||
background: linear-gradient(90deg, transparent, var(--gold-soft), transparent);
|
||
}
|
||
.chapter-row {
|
||
display: grid;
|
||
grid-template-columns: 80px 1fr auto;
|
||
gap: 24px;
|
||
align-items: center;
|
||
padding: 24px 0;
|
||
border-bottom: 1px solid var(--border);
|
||
cursor: pointer;
|
||
transition: all 0.2s ease;
|
||
}
|
||
.chapter-row:hover {
|
||
padding-left: 12px;
|
||
border-color: var(--gold-soft);
|
||
}
|
||
.chapter-row:hover .chapter-num {
|
||
color: var(--gold);
|
||
}
|
||
.chapter-num {
|
||
font-family: 'Songti SC', serif;
|
||
font-size: 36px;
|
||
font-weight: 700;
|
||
color: var(--fg-dim);
|
||
line-height: 1;
|
||
transition: color 0.2s;
|
||
}
|
||
.chapter-title {
|
||
font-family: 'Songti SC', serif;
|
||
font-size: 22px;
|
||
font-weight: 600;
|
||
margin: 0 0 6px;
|
||
}
|
||
.chapter-hint {
|
||
color: var(--fg-dim);
|
||
font-size: 13px;
|
||
}
|
||
.chapter-arrow {
|
||
color: var(--fg-dim);
|
||
font-size: 24px;
|
||
}
|
||
.chapter-row:hover .chapter-arrow { color: var(--gold); }
|
||
|
||
/* ---------- Reader (chapter content) ---------- */
|
||
.reader { background: var(--bg); }
|
||
.reader-chapter {
|
||
margin: 0 0 120px;
|
||
padding-top: 60px;
|
||
}
|
||
.reader-chapter:first-of-type { padding-top: 0; }
|
||
.reader-chapter-num {
|
||
color: var(--gold);
|
||
font-family: 'Songti SC', serif;
|
||
font-size: 14px;
|
||
letter-spacing: 0.4em;
|
||
margin-bottom: 12px;
|
||
}
|
||
.reader-chapter-title {
|
||
font-family: 'Songti SC', serif;
|
||
font-size: clamp(36px, 5vw, 56px);
|
||
font-weight: 700;
|
||
margin: 0 0 40px;
|
||
line-height: 1.15;
|
||
}
|
||
.reader-chapter-img {
|
||
width: 100%;
|
||
margin: 0 0 48px;
|
||
aspect-ratio: 16/10;
|
||
object-fit: cover;
|
||
background: var(--bg-card);
|
||
border: 1px solid var(--border);
|
||
}
|
||
.reader-chapter-body p {
|
||
font-family: 'Songti SC', 'Noto Serif CJK SC', serif;
|
||
font-size: 17px;
|
||
line-height: 2;
|
||
color: #d2d2d6;
|
||
margin: 0 0 24px;
|
||
text-indent: 2em;
|
||
}
|
||
.reader-chapter-body p.no-indent { text-indent: 0; }
|
||
.reader-chapter-body blockquote {
|
||
border-left: 3px solid var(--gold);
|
||
padding: 4px 0 4px 24px;
|
||
margin: 32px 0;
|
||
color: var(--fg);
|
||
font-family: 'Songti SC', serif;
|
||
font-size: 19px;
|
||
line-height: 1.9;
|
||
}
|
||
.chapter-divider {
|
||
text-align: center;
|
||
margin: 80px 0;
|
||
color: var(--gold);
|
||
font-size: 20px;
|
||
letter-spacing: 1.5em;
|
||
}
|
||
|
||
/* ---------- Gallery ---------- */
|
||
.gallery { background: var(--bg-soft); border-top: 1px solid var(--border); }
|
||
.gallery-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
||
gap: 24px;
|
||
margin-top: 40px;
|
||
}
|
||
.gallery-item {
|
||
background: var(--bg-card);
|
||
border: 1px solid var(--border);
|
||
overflow: hidden;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
}
|
||
.gallery-item:hover {
|
||
border-color: var(--gold-soft);
|
||
transform: translateY(-4px);
|
||
}
|
||
.gallery-item img {
|
||
width: 100%;
|
||
aspect-ratio: 16/10;
|
||
object-fit: cover;
|
||
transition: transform 0.5s ease;
|
||
}
|
||
.gallery-item:hover img { transform: scale(1.04); }
|
||
.gallery-meta {
|
||
padding: 20px;
|
||
}
|
||
.gallery-cap {
|
||
font-family: 'Songti SC', serif;
|
||
font-size: 18px;
|
||
margin: 0 0 6px;
|
||
font-weight: 600;
|
||
}
|
||
.gallery-sub {
|
||
color: var(--fg-dim);
|
||
font-size: 12px;
|
||
letter-spacing: 0.2em;
|
||
}
|
||
|
||
/* ---------- Reader extras (章末延伸图) ---------- */
|
||
.reader-extras {
|
||
margin: 64px 0 40px;
|
||
padding: 32px 0 0;
|
||
border-top: 1px solid var(--border);
|
||
}
|
||
.reader-extras-label {
|
||
color: var(--gold);
|
||
font-size: 11px;
|
||
letter-spacing: 0.4em;
|
||
text-transform: uppercase;
|
||
margin-bottom: 24px;
|
||
}
|
||
.reader-extras-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr;
|
||
gap: 28px;
|
||
}
|
||
.reader-extra {
|
||
margin: 0;
|
||
cursor: zoom-in;
|
||
transition: transform 0.3s ease;
|
||
}
|
||
.reader-extra:hover { transform: translateY(-2px); }
|
||
.reader-extra img {
|
||
width: 100%;
|
||
aspect-ratio: 16/10;
|
||
object-fit: cover;
|
||
background: var(--bg-card);
|
||
border: 1px solid var(--border);
|
||
}
|
||
.reader-extra figcaption {
|
||
padding: 16px 0 0;
|
||
}
|
||
.reader-extra-cap {
|
||
font-family: 'Songti SC', serif;
|
||
font-size: 19px;
|
||
font-weight: 600;
|
||
color: var(--fg);
|
||
margin-bottom: 4px;
|
||
}
|
||
.reader-extra-sub {
|
||
color: var(--gold);
|
||
font-size: 11px;
|
||
letter-spacing: 0.3em;
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
/* ---------- Gallery extras divider ---------- */
|
||
.gallery-extras-heading {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 20px;
|
||
margin: 80px 0 32px;
|
||
color: var(--gold);
|
||
font-family: 'Songti SC', serif;
|
||
font-size: 22px;
|
||
font-weight: 700;
|
||
}
|
||
.gallery-extras-heading::before, .gallery-extras-heading::after {
|
||
content: '';
|
||
flex: 1;
|
||
height: 1px;
|
||
background: linear-gradient(90deg, transparent, var(--gold-soft), transparent);
|
||
}
|
||
.gallery-extras-sub {
|
||
text-align: center;
|
||
color: var(--fg-dim);
|
||
font-size: 12px;
|
||
letter-spacing: 0.3em;
|
||
margin: -16px 0 40px;
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
/* ---------- Footer ---------- */
|
||
footer {
|
||
padding: 64px 24px 40px;
|
||
border-top: 1px solid var(--border);
|
||
color: var(--fg-dim);
|
||
font-size: 13px;
|
||
text-align: center;
|
||
background: var(--bg);
|
||
}
|
||
footer p { margin: 8px 0; }
|
||
|
||
/* ---------- Lightbox ---------- */
|
||
.lightbox {
|
||
position: fixed;
|
||
inset: 0;
|
||
background: rgba(5,6,10,0.96);
|
||
z-index: 100;
|
||
display: none;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 24px;
|
||
cursor: zoom-out;
|
||
}
|
||
.lightbox.active { display: flex; }
|
||
.lightbox img { max-width: 96%; max-height: 92vh; object-fit: contain; }
|
||
.lightbox-close {
|
||
position: absolute;
|
||
top: 24px; right: 32px;
|
||
color: var(--fg);
|
||
font-size: 28px;
|
||
cursor: pointer;
|
||
background: none;
|
||
border: none;
|
||
}
|
||
|
||
/* ---------- Nav ---------- */
|
||
.topnav {
|
||
position: fixed;
|
||
top: 0; left: 0; right: 0;
|
||
z-index: 50;
|
||
padding: 20px 32px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
background: linear-gradient(180deg, rgba(10,11,16,0.9), transparent);
|
||
backdrop-filter: blur(4px);
|
||
pointer-events: none;
|
||
}
|
||
.topnav > * { pointer-events: auto; }
|
||
.topnav-logo {
|
||
font-family: 'Songti SC', serif;
|
||
font-weight: 700;
|
||
font-size: 20px;
|
||
letter-spacing: 0.1em;
|
||
color: var(--fg);
|
||
}
|
||
.topnav-links {
|
||
display: flex;
|
||
gap: 32px;
|
||
}
|
||
.topnav-links a {
|
||
color: var(--fg-soft);
|
||
font-size: 13px;
|
||
letter-spacing: 0.2em;
|
||
text-transform: uppercase;
|
||
}
|
||
.topnav-links a:hover { color: var(--gold); }
|
||
|
||
/* ---------- Responsive ---------- */
|
||
@media (max-width: 768px) {
|
||
section { padding: 80px 20px; }
|
||
.about-grid { grid-template-columns: 1fr; gap: 48px; }
|
||
.hero-portrait { width: 100%; right: 0; opacity: 0.14; }
|
||
.topnav-links { display: none; }
|
||
.chapter-row { grid-template-columns: 56px 1fr; gap: 16px; }
|
||
.chapter-arrow { display: none; }
|
||
.chapter-num { font-size: 28px; }
|
||
.chapter-title { font-size: 18px; }
|
||
.reader-chapter-body p { font-size: 16px; line-height: 1.95; }
|
||
.hero-meta { gap: 24px; }
|
||
.hero-meta span strong { font-size: 18px; }
|
||
.reader-chapter { margin-bottom: 80px; }
|
||
}
|
||
|
||
/* ---------- Loading ---------- */
|
||
.loading {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 40px;
|
||
color: var(--fg-dim);
|
||
font-size: 14px;
|
||
letter-spacing: 0.3em;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<nav class="topnav">
|
||
<div class="topnav-logo">古法代码之王</div>
|
||
<div class="topnav-links">
|
||
<a href="#about">简介</a>
|
||
<a href="#characters">人物</a>
|
||
<a href="#chapters">章节</a>
|
||
<a href="#reader">阅读</a>
|
||
<a href="#gallery">画廊</a>
|
||
</div>
|
||
</nav>
|
||
|
||
<header class="hero">
|
||
<div class="hero-portrait"></div>
|
||
<div class="hero-inner">
|
||
<div class="hero-kicker">近未来 · 都市 · 科技爽文</div>
|
||
<h1 class="hero-title">古法代码<br>之 王</h1>
|
||
<p class="hero-subtitle">全世界 AI 崩溃后一位古法程序员的逆袭。</p>
|
||
<blockquote class="hero-tagline">
|
||
当全世界都把写代码交给 AI,<br>只有一个被时代淘汰的人,还记得如何真正让系统运转。
|
||
</blockquote>
|
||
<div class="hero-meta">
|
||
<span>章节数<strong>20 + 终章</strong></span>
|
||
<span>字数<strong>约 12 万字</strong></span>
|
||
<span>原创插图<strong>22 幅</strong></span>
|
||
<span>时间跨度<strong>20 年</strong></span>
|
||
</div>
|
||
<div class="hero-cta">
|
||
<a href="#reader" class="btn primary">开始阅读 →</a>
|
||
<a href="#chapters" class="btn">章节目录</a>
|
||
</div>
|
||
</div>
|
||
<div class="hero-scroll">↓ SCROLL</div>
|
||
</header>
|
||
|
||
<section class="about" id="about">
|
||
<div class="container">
|
||
<div class="eyebrow">SYNOPSIS · 简介</div>
|
||
<h2 class="section-title">这是一个<br>旧时代火种的故事。</h2>
|
||
<div class="about-grid">
|
||
<div class="about-text">
|
||
<p>二十一世纪三十年代后,全球进入"全栈智编时代"。绝大多数公司不再招聘传统程序员,而是招聘"意图架构师""模型协同师""AI 产线调度员"。人类几乎不再真正编写代码,只需要向超大型编程模型描述需求。</p>
|
||
<p>随着二十年的沉浸式依赖,真正理解数据结构、编译原理、操作系统、网络协议和底层工程实现的人越来越少。社会舆论将手写代码视为落后、低效、古怪甚至可笑的旧时代手艺。</p>
|
||
<p>然而这一切建立在一个全球统一的基础上:所有大型系统都深度依赖"宙核智能编程网"。一旦底层智能编程能力发生系统性失灵,整个世界将出现无人能修的灾难性后果。</p>
|
||
<p>顾沉舟,一个始终坚持手写代码、读源码、理解底层的"异类"——在漫长二十年里,他穷过、被辞退过、被恋人嫌弃过,也怀疑过自己是不是抱着一堆过时骨头不肯松手。直到那一天,世界停电。</p>
|
||
</div>
|
||
<div class="about-stats">
|
||
<div>
|
||
<div class="stat-num">20</div>
|
||
<div class="stat-label">Chapters · 章</div>
|
||
</div>
|
||
<div>
|
||
<div class="stat-num">12w</div>
|
||
<div class="stat-label">Words · 字</div>
|
||
</div>
|
||
<div>
|
||
<div class="stat-num">22</div>
|
||
<div class="stat-label">Illustrations</div>
|
||
</div>
|
||
<div>
|
||
<div class="stat-num">∞</div>
|
||
<div class="stat-label">Iteration</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="characters" id="characters">
|
||
<div class="container">
|
||
<div class="eyebrow">CAST · 人物</div>
|
||
<h2 class="section-title">那些站在他身边的人,<br>和那些笑过他的人。</h2>
|
||
<div class="char-grid">
|
||
<div class="char-card">
|
||
<div class="char-role">男主 · Protagonist</div>
|
||
<h3 class="char-name">顾沉舟</h3>
|
||
<p class="char-desc">底层技术狂人。信奉"代码必须自己写过,系统必须自己跑懂"。嘴硬、寡言、倔强,在全球智能编程崩溃之前,他是个被时代嫌弃二十年的穷光蛋。</p>
|
||
</div>
|
||
<div class="char-card">
|
||
<div class="char-role">旧爱 · First Love</div>
|
||
<h3 class="char-name">林晚乔</h3>
|
||
<p class="char-desc">大学时代最接近恋人的女孩。聪明、现实、心软却怕穷。喜欢过他写代码时专注到近乎冷峻的模样,也最终在房租与前途面前选择离开。</p>
|
||
</div>
|
||
<div class="char-card">
|
||
<div class="char-role">救赎 · Redemption</div>
|
||
<h3 class="char-name">苏青禾</h3>
|
||
<p class="char-desc">前期唯一真正看懂男主价值的人。安静、克制、细腻,在他最落魄时多次帮他扛过现实危机。陪伴型、治愈型,后期极具分量。</p>
|
||
</div>
|
||
<div class="char-card">
|
||
<div class="char-role">权势 · Power</div>
|
||
<h3 class="char-name">沈知意</h3>
|
||
<p class="char-desc">资本与媒体的宠儿。出身顶级财团,聪明、美艳、掌控欲强,对技术天才有近乎病态的占有欲。男主一朝成名后,她主动出手。</p>
|
||
</div>
|
||
<div class="char-card">
|
||
<div class="char-role">战友 · Comrade</div>
|
||
<h3 class="char-name">许幼宁</h3>
|
||
<p class="char-desc">国家级关键项目中的天才安全研究员,冷感、锋利、极致专业。与男主先是惺惺相惜的战友,后因共同经历全球危机而逐渐动情。</p>
|
||
</div>
|
||
<div class="char-card">
|
||
<div class="char-role">反派 · Foil</div>
|
||
<h3 class="char-name">韩锐</h3>
|
||
<p class="char-desc">最早全面拥抱 AI 编码红利的大学同学。擅长包装、迎合资本、表演"技术领袖"人设。危机爆发后,成为最典型的"离开 AI 就彻底无能"的昔日天才。</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="chapters" id="chapters">
|
||
<div class="container">
|
||
<div class="eyebrow">CHAPTERS · 章节目录</div>
|
||
<h2 class="section-title">二十年,<br>四卷沉浮。</h2>
|
||
<div id="chapters-list"></div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="reader" id="reader">
|
||
<div class="container-reading">
|
||
<div class="eyebrow">READ · 在线阅读</div>
|
||
<h2 class="section-title">正文</h2>
|
||
<div id="reader-content"><div class="loading">载入中 …</div></div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="gallery" id="gallery">
|
||
<div class="container">
|
||
<div class="eyebrow">GALLERY · 插图画廊</div>
|
||
<h2 class="section-title">命运的二十二帧。</h2>
|
||
<p style="color: var(--fg-soft); max-width: 620px; margin: -24px 0 40px;">从毕业即过时,到代码之王——画面随男主心境推进:冷灰蓝 → 工业寒夜 → 红色告警 → 深黑金巅峰。点击任一幅放大查看。</p>
|
||
<div class="gallery-grid" id="gallery-grid"></div>
|
||
|
||
<div class="gallery-extras-heading">扩集画面 · EXTRA</div>
|
||
<div class="gallery-extras-sub">扩写之后新生的关键时刻 · 6 幅</div>
|
||
<div class="gallery-grid" id="gallery-extras"></div>
|
||
</div>
|
||
</section>
|
||
|
||
<footer>
|
||
<p>《古法代码之王》 · 近未来都市科技爽文 · 创作归档 2026-04</p>
|
||
<p style="color: var(--fg-dim)">展示站部署于 kang-kang.com · 仓库 gitea@kangwang</p>
|
||
<p style="margin-top: 24px; color: var(--fg-dim); font-size: 11px; letter-spacing: 0.3em;">GUFA · CODE · KING · MMXXVI</p>
|
||
</footer>
|
||
|
||
<div class="lightbox" id="lightbox" onclick="closeLightbox()">
|
||
<button class="lightbox-close" onclick="closeLightbox()">×</button>
|
||
<img id="lightbox-img" src="" alt="">
|
||
</div>
|
||
|
||
<script>
|
||
const CHAPTERS = [
|
||
{ n: 1, title: '毕业即过时', img: 'ch01_graduation_outdated.jpg', volume: '第一卷 · 被时代埋掉的人', hint: 'AI 编码招聘横扫市场,他被视为古董' },
|
||
{ n: 2, title: '最便宜的程序员', img: 'ch02_the_cheapest_programmer.jpg', volume: '第一卷 · 被时代埋掉的人', hint: '边缘公司,遗留系统,人人轻视' },
|
||
{ n: 3, title: '她说你这样没有未来', img: 'ch03_you_have_no_future.jpg', volume: '第一卷 · 被时代埋掉的人', hint: '贫穷与理想,裂痕第一道' },
|
||
{ n: 4, title: '全世界都在笑他', img: 'ch04_the_world_laughed_at_him.jpg', volume: '第一卷 · 被时代埋掉的人', hint: '韩锐风光无限,他在出租屋里修服务器' },
|
||
{ n: 5, title: '被裁员的人没有资格谈梦想', img: 'ch05_laid_off_no_dreams.jpg', volume: '第一卷 · 被时代埋掉的人', hint: '第一份工作失去,跌入谷底' },
|
||
{ n: 6, title: '旧电脑与冷泡面', img: 'ch06_old_computer_cold_noodles.jpg', volume: '第二卷 · 寒冬里独自敲键盘', hint: '低端外包,熬夜,凄惨地活着',
|
||
extras: [
|
||
{ file: 'extra/ch06_panic_night.jpg', cap: '第三天夜里 · 被自己的恐惧按在地上', sub: 'PTSD 原点' }
|
||
] },
|
||
{ n: 7, title: '只有她递来一把伞', img: 'ch07_she_brought_an_umbrella.jpg', volume: '第二卷 · 寒冬里独自敲键盘', hint: '苏青禾登场,一点温柔的光' },
|
||
{ n: 8, title: '爱也会输给房租', img: 'ch08_love_lost_to_rent.jpg', volume: '第二卷 · 寒冬里独自敲键盘', hint: '林晚乔正式离开,情感谷底' },
|
||
{ n: 9, title: '没人相信的底层能力', img: 'ch09_no_one_believed_him.jpg', volume: '第二卷 · 寒冬里独自敲键盘', hint: '想推销离线开发,被当笑话' },
|
||
{ n: 10, title: '十年一梦,满身风雪', img: 'ch10_ten_years_in_snow.jpg', volume: '第二卷 · 寒冬里独自敲键盘', hint: '在行业边缘漂泊多年',
|
||
extras: [
|
||
{ file: 'extra/ch10_cafe_read_alone.jpg', cap: '他给自己读完一场没有听众的演讲', sub: '40 岁 · 平静庄严' }
|
||
] },
|
||
{ n: 11, title: '聪明人都不会手写代码了', img: 'ch11_no_one_writes_code_anymore.jpg', volume: '第三卷 · 黑箱时代的裂缝', hint: '传统工程师彻底绝迹' },
|
||
{ n: 12, title: '第一次异常', img: 'ch12_first_anomaly.jpg', volume: '第三卷 · 黑箱时代的裂缝', hint: '核心系统零星故障,被当波动' },
|
||
{ n: 13, title: '无人能读懂的补丁', img: 'ch13_unreadable_patch.jpg', volume: '第三卷 · 黑箱时代的裂缝', hint: '大平台自修复越修越乱' },
|
||
{ n: 14, title: '世界停电的那一天', img: 'ch14_the_day_the_world_went_dark.jpg',volume: '第三卷 · 黑箱时代的裂缝', hint: '金融交通医疗能源连锁崩塌',
|
||
extras: [
|
||
{ file: 'extra/ch14_linwanqiao_window.jpg', cap: '她认出了那只黑色帆布包', sub: '旧情视角 · 一面落地窗' }
|
||
] },
|
||
{ n: 15, title: '求他出山的人排到了楼下', img: 'ch15_people_queued_to_beg_him.jpg', volume: '第三卷 · 黑箱时代的裂缝', hint: '昔日嘲笑他的人开始低头' },
|
||
{ n: 16, title: '一人重启一座城', img: 'ch16_one_man_restart_a_city.jpg', volume: '第四卷 · 旧时代火种', hint: '凭古法工程修复核心调度',
|
||
extras: [
|
||
{ file: 'extra/ch16_victory_night_alone.jpg', cap: '庆功夜 · 锁门独饮', sub: '成功的空旷 · 那接下来呢' }
|
||
] },
|
||
{ n: 17, title: '财团、公权与资本都在抢他', img: 'ch17_everyone_is_fighting_for_him.jpg',volume: '第四卷 · 旧时代火种', hint: '沈知意、国家机构、巨头同时伸手' },
|
||
{ n: 18, title: '她们都在等他一句话', img: 'ch18_they_wait_for_his_answer.jpg', volume: '第四卷 · 旧时代火种', hint: '情感线全面升温' },
|
||
{ n: 19, title: '代码之王', img: 'ch19_king_of_code.jpg', volume: '第四卷 · 旧时代火种', hint: '组建离线工程联盟,重塑秩序' },
|
||
{ n: 20, title: '坐拥繁花,归来仍是少年', img: 'ch20_among_flowers_still_young.jpg', volume: '第四卷 · 旧时代火种', hint: '站上巅峰,事业情感双圆满' },
|
||
{ n: 0, title: '终章 · 写代码的人,重新定义世界', img: 'epilogue_redefine_the_world.jpg', volume: '终章', hint: 'AI 重新成为工具而非拐杖',
|
||
extras: [
|
||
{ file: 'extra/ring_classroom_10yrs_later.jpg', cap: '十年后 · 新一代走进教室', sub: '环状收尾 · 黑板三字:写 代 码' },
|
||
{ file: 'extra/s2_blank_second_page.jpg', cap: '我 怕 的——', sub: '第二部 · 序章 · 留白' }
|
||
] },
|
||
];
|
||
|
||
function renderChapterList() {
|
||
const wrap = document.getElementById('chapters-list');
|
||
let html = '', lastVolume = '';
|
||
CHAPTERS.forEach((ch, idx) => {
|
||
if (ch.volume !== lastVolume) {
|
||
html += `<div class="volume-heading">${ch.volume}</div>`;
|
||
lastVolume = ch.volume;
|
||
}
|
||
const num = ch.n === 0 ? '终' : ch.n.toString().padStart(2, '0');
|
||
const title = ch.n === 0 ? ch.title.replace('终章 · ', '') : ch.title;
|
||
html += `
|
||
<div class="chapter-row" onclick="jumpToChapter(${idx})">
|
||
<div class="chapter-num">${num}</div>
|
||
<div>
|
||
<h3 class="chapter-title">${title}</h3>
|
||
<div class="chapter-hint">${ch.hint}</div>
|
||
</div>
|
||
<div class="chapter-arrow">→</div>
|
||
</div>`;
|
||
});
|
||
wrap.innerHTML = html;
|
||
}
|
||
|
||
function renderGallery() {
|
||
const wrap = document.getElementById('gallery-grid');
|
||
wrap.innerHTML = CHAPTERS.map((ch, idx) => {
|
||
const num = ch.n === 0 ? '终章' : `第 ${ch.n} 章`;
|
||
const title = ch.n === 0 ? '写代码的人,重新定义世界' : ch.title;
|
||
return `
|
||
<div class="gallery-item" onclick="openLightbox('./images/${ch.img}')">
|
||
<img src="./images/${ch.img}" alt="${title}" loading="lazy">
|
||
<div class="gallery-meta">
|
||
<div class="gallery-cap">${title}</div>
|
||
<div class="gallery-sub">${num}</div>
|
||
</div>
|
||
</div>`;
|
||
}).join('');
|
||
|
||
// Extras gallery — new scenes born from expansion
|
||
const extrasWrap = document.getElementById('gallery-extras');
|
||
if (extrasWrap) {
|
||
const extraItems = [];
|
||
CHAPTERS.forEach(ch => {
|
||
if (!ch.extras) return;
|
||
const num = ch.n === 0 ? '终章' : `第 ${ch.n} 章`;
|
||
ch.extras.forEach(ex => {
|
||
extraItems.push({ ...ex, num, chTitle: ch.title });
|
||
});
|
||
});
|
||
extrasWrap.innerHTML = extraItems.map(ex => `
|
||
<div class="gallery-item" onclick="openLightbox('./images/${ex.file}')">
|
||
<img src="./images/${ex.file}" alt="${ex.cap}" loading="lazy">
|
||
<div class="gallery-meta">
|
||
<div class="gallery-cap">${ex.cap}</div>
|
||
<div class="gallery-sub">${ex.num} · ${ex.sub}</div>
|
||
</div>
|
||
</div>`).join('');
|
||
}
|
||
}
|
||
|
||
function jumpToChapter(idx) {
|
||
const el = document.getElementById('chapter-' + idx);
|
||
if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||
}
|
||
|
||
function openLightbox(src) {
|
||
const box = document.getElementById('lightbox');
|
||
document.getElementById('lightbox-img').src = src;
|
||
box.classList.add('active');
|
||
document.body.style.overflow = 'hidden';
|
||
}
|
||
function closeLightbox() {
|
||
document.getElementById('lightbox').classList.remove('active');
|
||
document.body.style.overflow = '';
|
||
}
|
||
|
||
async function loadNovel() {
|
||
try {
|
||
const resp = await fetch('./novel.md');
|
||
const text = await resp.text();
|
||
renderNovel(text);
|
||
} catch (e) {
|
||
document.getElementById('reader-content').innerHTML =
|
||
'<div class="loading" style="color: var(--red)">小说载入失败:' + e.message + '</div>';
|
||
}
|
||
}
|
||
|
||
function renderNovel(md) {
|
||
// Strip title & quote block before first ## section
|
||
const sections = md.split(/^## /m).slice(1); // each section starts with chapter heading
|
||
const out = [];
|
||
sections.forEach((sec, idx) => {
|
||
const lines = sec.split('\n');
|
||
const heading = lines[0].trim();
|
||
const body = lines.slice(1).join('\n').trim();
|
||
// match "第1章 标题" or "终章 标题"
|
||
const m = heading.match(/^(第(\d+)章|终章)\s+(.+)$/);
|
||
if (!m) return;
|
||
const isEpilogue = !m[2];
|
||
const num = isEpilogue ? '终' : m[2].padStart(2, '0');
|
||
const title = m[3];
|
||
const ch = CHAPTERS[idx];
|
||
const imgPath = ch ? `./images/${ch.img}` : '';
|
||
const paragraphs = body.split(/\n\s*\n/).map(p => {
|
||
const line = p.trim();
|
||
if (!line) return '';
|
||
if (line.startsWith('>')) {
|
||
return '<blockquote>' + line.replace(/^>\s*/, '') + '</blockquote>';
|
||
}
|
||
return '<p>' + escapeHtml(line) + '</p>';
|
||
}).join('\n');
|
||
const extrasHtml = (ch && ch.extras) ? `
|
||
<div class="reader-extras">
|
||
<div class="reader-extras-label">章末延伸画面 · Extra</div>
|
||
<div class="reader-extras-grid">
|
||
${ch.extras.map(ex => `
|
||
<figure class="reader-extra" onclick="openLightbox('./images/${ex.file}')">
|
||
<img src="./images/${ex.file}" alt="${ex.cap}" loading="lazy">
|
||
<figcaption>
|
||
<div class="reader-extra-cap">${ex.cap}</div>
|
||
<div class="reader-extra-sub">${ex.sub}</div>
|
||
</figcaption>
|
||
</figure>`).join('')}
|
||
</div>
|
||
</div>` : '';
|
||
out.push(`
|
||
<article class="reader-chapter" id="chapter-${idx}">
|
||
<div class="reader-chapter-num">${isEpilogue ? 'EPILOGUE' : 'CHAPTER ' + num}</div>
|
||
<h2 class="reader-chapter-title">${title}</h2>
|
||
${imgPath ? `<img class="reader-chapter-img" src="${imgPath}" alt="${title}" loading="lazy" onclick="openLightbox('${imgPath}')" style="cursor: zoom-in;">` : ''}
|
||
<div class="reader-chapter-body">${paragraphs}</div>
|
||
${extrasHtml}
|
||
${idx < sections.length - 1 ? '<div class="chapter-divider">· · ·</div>' : ''}
|
||
</article>
|
||
`);
|
||
});
|
||
document.getElementById('reader-content').innerHTML = out.join('');
|
||
}
|
||
|
||
function escapeHtml(s) {
|
||
return s.replace(/[&<>]/g, c => ({ '&': '&', '<': '<', '>': '>' }[c]));
|
||
}
|
||
|
||
document.addEventListener('keydown', e => {
|
||
if (e.key === 'Escape') closeLightbox();
|
||
});
|
||
|
||
renderChapterList();
|
||
renderGallery();
|
||
loadNovel();
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|