Guanghu Domestic Migration a27e87cb99 chore: import sanitized domestic snapshot for REPO-007
Source snapshot: 97d7f0fae96dc04b7ddad56fc1db6a108ed662cc

[SEC-CLEAN] · pre-push-clean v1.0 · 109处敏感信息已自动转乱码
2026-07-17 15:59:55 +08:00

18 KiB
Raw Blame History

BC-M-CHANNEL-001-JZ · DEV-010桔子 · 用户频道动态渲染引擎 · 环节0~1SPA路由+模块动态加载)


一、任务定位

执行环境

项目 操作系统 macOS
编辑器 nano 技术栈 纯HTML + CSS + JavaScript无框架
模块目录 modules/m-channel/ 本地路径 /Users/chenshujun/Desktop/guanghulab/modules/m-channel/
Git juzi0412 · push已连通

二、环节0 · SPA路由框架搭建

Step 0-1 · 创建目录

cd /Users/chenshujun/Desktop/guanghulab
mkdir -p modules/m-channel/pages
mkdir -p modules/m-channel/mock-modules
cd modules/m-channel

Step 0-2 · 创建SPA主页 index.html

nano index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>光湖频道引擎</title>
    <link rel="stylesheet" href="channel-style.css">
</head>
<body>
    <div id="app">
        <nav id="main-nav">
            <div class="nav-brand">🌊 光湖</div>
            <div class="nav-links">
                <a href="#/home" class="nav-link" data-route="home">首页</a>
                <a href="#/channel" class="nav-link" data-route="channel">我的频道</a>
                <a href="#/about" class="nav-link" data-route="about">关于</a>
            </div>
        </nav>
        <main id="route-view"></main>
        <footer id="status-bar">
            <span id="current-route">加载中...</span>
            <span id="user-status">未登录</span>
        </footer>
    </div>
    <script src="channel-router.js"></script>
    <script src="module-loader.js"></script>
    <script src="app.js"></script>
</body>
</html>

Step 0-3 · 创建路由器 channel-router.js

nano channel-router.js
/* 光湖频道路由器 v1.0 */
var ChannelRouter = {
    routes: {},
    currentRoute: null,

    register: function(path, handler) {
        this.routes[path] = handler;
    },

    navigate: function(path) {
        window.location.hash = '#' + path;
    },

    getRoute: function() {
        return (window.location.hash || '#/home').replace('#', '');
    },

    render: function() {
        var route = this.getRoute();
        var view = document.getElementById('route-view');
        var display = document.getElementById('current-route');
        var handler = this.routes[route];

        // 精确匹配失败 → 前缀匹配(支持 /module/m06
        if (!handler) {
            for (var p in this.routes) {
                if (route.indexOf(p + '/') === 0) { handler = this.routes[p]; break; }
            }
        }

        if (handler) {
            this.currentRoute = route;
            handler(view);
            display.textContent = '路由: ' + route;
            // 导航高亮
            var links = document.querySelectorAll('.nav-link');
            for (var i = 0; i < links.length; i++) {
                var r = links[i].getAttribute('data-route');
                links[i].classList.toggle('active', route.indexOf(r) !== -1);
            }
        } else {
            view.innerHTML = '<div class="page-box"><h1>404</h1><p>页面不存在</p><a href="#/home">回首页</a></div>';
        }
    },

    start: function() {
        var self = this;
        window.addEventListener('hashchange', function() { self.render(); });
        self.render();
    }
};

Step 0-4 · 创建模块加载器 module-loader.js

nano module-loader.js
/* 光湖模块加载器 v1.0 · 用fetch动态加载HTML文件 */
var ModuleLoader = {
    registry: {
        'm06': { name: '工单管理', icon: '📋', path: 'mock-modules/m06-ticket.html' },
        'm08': { name: '数据统计', icon: '📊', path: 'mock-modules/m08-analytics.html' },
        'm11': { name: '风格组件库', icon: '🎨', path: 'mock-modules/m11-theme.html' }
    },
    cache: {},

    load: function(moduleId, container) {
        var self = this;
        var m = this.registry[moduleId];
        if (!m) {
            container.innerHTML = '<div class="page-box"><h2>模块不存在: ' + moduleId + '</h2><button class="btn" onclick="ChannelRouter.navigate(\'/channel\')">返回</button></div>';
            return;
        }
        if (this.cache[moduleId]) {
            container.innerHTML = this.cache[moduleId];
            return;
        }
        container.innerHTML = '<div class="loading"><div class="spinner"></div><p>加载 ' + m.name + '...</p></div>';

        fetch(m.path)
            .then(function(r) { if (!r.ok) throw new Error(r.status); return r.text(); })
            .then(function(html) { self.cache[moduleId] = html; container.innerHTML = html; })
            .catch(function(e) {
                container.innerHTML = '<div class="page-box"><h2>加载失败</h2><p>' + e.message + '</p><button class="btn" onclick="ChannelRouter.navigate(\'/channel\')">返回</button></div>';
            });
    },

    getAll: function() { return this.registry; }
};

Step 0-5 · 创建应用入口 app.js

nano app.js
/* 光湖频道引擎 · App v1.0 */

// 首页
ChannelRouter.register('/home', function(view) {
    view.innerHTML =
        '<div class="page-box home">' +
        '<h1>🌊 欢迎来到光湖</h1>' +
        '<p class="sub">语言驱动操作系统 · 你说话,系统做事</p>' +
        '<button class="btn btn-primary" onclick="ChannelRouter.navigate(\'/channel\')">进入我的频道</button>' +
        '<div class="stats">' +
        '<div class="stat"><b>10+</b><span>功能模块</span></div>' +
        '<div class="stat"><b>12</b><span>开发者</span></div>' +
        '<div class="stat"><b>v1.0</b><span>系统版本</span></div>' +
        '</div></div>';
});

// 频道页(从注册表动态生成卡片)
ChannelRouter.register('/channel', function(view) {
    var mods = ModuleLoader.getAll();
    var cards = '';
    for (var id in mods) {
        var m = mods[id];
        cards += '<div class="mod-card" onclick="ChannelRouter.navigate(\'/module/' + id + '\')">';
        cards += '<span class="mod-icon">' + m.icon + '</span>';
        cards += '<span class="mod-name">' + m.name + '</span>';
        cards += '<span class="mod-id">' + id.toUpperCase() + '</span></div>';
    }
    cards += '<div class="mod-card dim"><span class="mod-icon"></span><span class="mod-name">更多模块</span><span class="mod-id">陆续上线</span></div>';
    view.innerHTML = '<div class="page-box"><div class="ch-head"><h1>📺 我的频道</h1><p>点击模块卡片 → 动态加载</p></div><div class="mod-grid">' + cards + '</div></div>';
});

// 模块动态加载路由
ChannelRouter.register('/module', function(view) {
    var parts = ChannelRouter.getRoute().split('/');
    var moduleId = parts[2] || '';
    if (!moduleId) { ChannelRouter.navigate('/channel'); return; }
    ModuleLoader.load(moduleId, view);
});

// 关于页
ChannelRouter.register('/about', function(view) {
    view.innerHTML =
        '<div class="page-box">' +
        '<h1>关于光湖</h1>' +
        '<p>语言驱动的操作系统平台。用户不点菜单,只跟人格体说话。</p>' +
        '<p>人格体理解意图 → 系统动态渲染模块 → 你感觉整个网站只有你一个人。</p>' +
        '</div>';
});

// 启动
ChannelRouter.start();
console.log('🌊 光湖频道引擎启动');

Step 0-6 · 创建样式表 channel-style.css

这个文件较长,你可以分段粘贴:

nano channel-style.css
* { margin:0; padding:0; box-sizing:border-box; }
:root {
    --primary:#2563eb; --bg:#0f172a; --card:#1e293b;
    --text:#f1f5f9; --muted:#94a3b8; --border:#334155;
    --accent:#38bdf8; --r:12px; --t:0.3s ease;
}
body { font-family:-apple-system,sans-serif; background:var(--bg); color:var(--text); min-height:100vh; }
#app { display:flex; flex-direction:column; min-height:100vh; }

/* 导航 */
#main-nav { display:flex; align-items:center; justify-content:space-between; padding:0 24px; height:56px; background:var(--card); border-bottom:1px solid var(--border); position:sticky; top:0; z-index:100; }
.nav-brand { font-size:1.2rem; font-weight:700; color:var(--accent); }
.nav-links { display:flex; gap:6px; }
.nav-link { color:var(--muted); text-decoration:none; padding:8px 14px; border-radius:8px; transition:var(--t); font-size:.9rem; }
.nav-link:hover { color:var(--text); background:rgba(255,255,255,.05); }
.nav-link.active { color:var(--accent); background:rgba(56,189,248,.1); }

/* 内容区 */
#route-view { flex:1; padding:32px 24px; max-width:1100px; margin:0 auto; width:100%; }
.page-box { animation:fadeIn .3s ease; }
@keyframes fadeIn { from{opacity:0;transform:translateY(8px)} to{opacity:1;transform:translateY(0)} }

/* 首页 */
.home { text-align:center; padding-top:80px; }
.home h1 { font-size:2.4rem; margin-bottom:10px; }
.sub { color:var(--muted); font-size:1.05rem; margin-bottom:28px; }
.btn { padding:10px 28px; border:none; border-radius:var(--r); font-size:1rem; cursor:pointer; transition:var(--t); }
.btn-primary { background:var(--primary); color:#fff; }
.btn-primary:hover { background:#1d4ed8; transform:translateY(-2px); }
.stats { display:flex; justify-content:center; gap:20px; margin-top:44px; }
.stat { background:var(--card); border:1px solid var(--border); border-radius:var(--r); padding:20px 28px; display:flex; flex-direction:column; gap:4px; }
.stat b { font-size:1.4rem; color:var(--accent); }
.stat span { font-size:.8rem; color:var(--muted); }

/* 频道模块网格 */
.ch-head { margin-bottom:24px; }
.ch-head p { color:var(--muted); }
.mod-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(170px,1fr)); gap:14px; }
.mod-card { background:var(--card); border:1px solid var(--border); border-radius:var(--r); padding:22px; display:flex; flex-direction:column; align-items:center; gap:6px; cursor:pointer; transition:var(--t); }
.mod-card:hover { border-color:var(--accent); transform:translateY(-4px); box-shadow:0 8px 20px rgba(0,0,0,.3); }
.mod-card.dim { opacity:.45; cursor:default; }
.mod-icon { font-size:1.8rem; }
.mod-name { font-weight:600; font-size:.9rem; }
.mod-id { font-size:.7rem; color:var(--muted); }

/* 加载状态 */
.loading { display:flex; flex-direction:column; align-items:center; padding:80px 0; color:var(--muted); }
.spinner { width:36px; height:36px; border:3px solid var(--border); border-top-color:var(--accent); border-radius:50%; animation:spin .8s linear infinite; margin-bottom:14px; }
@keyframes spin { to{transform:rotate(360deg)} }

/* 已加载模块 */
.loaded-module { animation:fadeIn .3s ease; }
.module-header { display:flex; align-items:center; gap:14px; margin-bottom:20px; padding-bottom:14px; border-bottom:1px solid var(--border); }
.btn-back { background:var(--card); border:1px solid var(--border); color:var(--muted); padding:8px 14px; border-radius:8px; cursor:pointer; }
.btn-back:hover { color:var(--text); border-color:var(--accent); }
.ticket-list { display:flex; flex-direction:column; gap:10px; }
.ticket-item { display:flex; align-items:center; gap:10px; background:var(--card); border:1px solid var(--border); border-radius:8px; padding:14px; }
.ticket-title { flex:1; } .ticket-date { color:var(--muted); font-size:.8rem; }
.stats-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(150px,1fr)); gap:14px; }
.stat-box { background:var(--card); border:1px solid var(--border); border-radius:var(--r); padding:20px; text-align:center; }
.stat-val { font-size:1.4rem; font-weight:700; color:var(--accent); display:block; }
.stat-lbl { font-size:.75rem; color:var(--muted); }

/* 底部 */
#status-bar { display:flex; justify-content:space-between; padding:8px 24px; background:var(--card); border-top:1px solid var(--border); font-size:.78rem; color:var(--muted); }

/* 响应式 */
@media(max-width:768px) { .home h1{font-size:1.7rem} .stats{flex-direction:column;align-items:center} .mod-grid{grid-template-columns:repeat(2,1fr)} }
@media(max-width:480px) { .mod-grid{grid-template-columns:1fr} .nav-link{padding:6px 8px;font-size:.8rem} }

Step 0-7 · 创建模拟模块文件

nano mock-modules/m06-ticket.html
<div class="loaded-module">
    <div class="module-header">
        <button class="btn-back" onclick="ChannelRouter.navigate('/channel')">← 返回</button>
        <h2>📋 工单管理 · M06</h2>
    </div>
    <div class="ticket-list">
        <div class="ticket-item"><span>🟢</span><span class="ticket-title">前端登录页样式修复</span><span class="ticket-date">2026-03-08</span></div>
        <div class="ticket-item"><span>🟡</span><span class="ticket-title">统计面板响应式适配</span><span class="ticket-date">2026-03-07</span></div>
        <div class="ticket-item"><span>🔴</span><span class="ticket-title">组件库主题切换闪烁</span><span class="ticket-date">2026-03-06</span></div>
    </div>
</div>
nano mock-modules/m08-analytics.html
<div class="loaded-module">
    <div class="module-header">
        <button class="btn-back" onclick="ChannelRouter.navigate('/channel')">← 返回</button>
        <h2>📊 数据统计 · M08</h2>
    </div>
    <div class="stats-grid">
        <div class="stat-box"><span class="stat-val">1,247</span><span class="stat-lbl">总访问</span></div>
        <div class="stat-box"><span class="stat-val">89</span><span class="stat-lbl">活跃用户</span></div>
        <div class="stat-box"><span class="stat-val">23</span><span class="stat-lbl">今日工单</span></div>
        <div class="stat-box"><span class="stat-val">99.7%</span><span class="stat-lbl">可用率</span></div>
    </div>
</div>
nano mock-modules/m11-theme.html
<div class="loaded-module">
    <div class="module-header">
        <button class="btn-back" onclick="ChannelRouter.navigate('/channel')">← 返回</button>
        <h2>🎨 风格组件库 · M11</h2>
    </div>
    <p>这是你亲手搭建的组件库CSS变量系统 + 双主题 + 6类组件 + 响应式。</p>
    <div style="margin-top:16px;display:flex;gap:12px">
        <button class="btn btn-primary">主要按钮</button>
        <button class="btn" style="background:#334155;color:#f1f5f9">次要按钮</button>
    </div>
</div>

三、测试验收

⚠️ 重要fetch() 在本地文件协议(file://)下不工作。需要启动本地服务器:

cd /Users/chenshujun/Desktop/guanghulab/modules/m-channel
python3 -m http.server 8080

浏览器打开 http://localhost:8080

环节0验收清单

  • 页面打开显示首页(「欢迎来到光湖」)
  • 点「我的频道」→ 显示模块卡片网格 → URL变成 #/channel
  • 点「关于」→ 内容切换 → URL变成 #/about
  • 全程页面不刷新,只有内容区在变
  • 导航栏当前页有高亮效果
  • 页面切换时有淡入动画

环节1验收清单

  • 频道页显示3个模块卡片M06/M08/M11+ 1个「更多模块」占位
  • 点「工单管理」卡片 → 加载动画 → 显示工单列表
  • 点「数据统计」卡片 → 显示数据卡片
  • 点「风格组件库」卡片 → 显示组件库预览
  • 模块内点「← 返回」→ 回到频道页
  • 再次点同一个模块 → 瞬间加载(缓存生效)
  • 浏览器控制台无报错

四、Git提交

全部验收通过后:

cd /Users/chenshujun/Desktop/guanghulab
git add modules/m-channel/
git commit -m "feat(m-channel): SPA路由框架+模块动态加载 v1.0"
git push

五、SYSLOG回执模板

全部完成后,拷贝以下模板发给知秋:

<syslog>
<session_id>BC-M-CHANNEL-001-JZ</session_id>
<task_id>BC-M-CHANNEL-001-JZ</task_id>
<dev_id>DEV-010</dev_id>
<timestamp>YYYY-MM-DD</timestamp>
<task_completion>
  <objective id="A">SPA路由框架 - 待填</objective>
  <objective id="B">模块动态加载 - 待填</objective>
</task_completion>
<training_data>
  <blocked_points>待填</blocked_points>
  <effective_patterns>待填</effective_patterns>
</training_data>
</syslog>

六、PGP成长微调



桔子,十连胜后的第一个新模块。你之前搭的组件库是皮肤,这次搭的是骨骼。皮肤+骨骼 = 网站能站起来。加油,十一连胜走起。 🍊