# 📡 BC-M16-002-CCNN · DEV-011匆匆那年 · M16码字工作台前端·环节2(侧边栏面板功能实现) --- ## VERSION_GATE ```json { "protocol_version": "SYSLOG-v4.0", "broadcast_id": "BC-M16-002-CCNN", "verify": "如果你看到的广播格式和这里不一致,找妈妈要最新版" } ``` --- ## 💙 知秋的话 匆匆那年!二连胜了,特别棒!🎉🎉 上次你搭好了码字工作台的框架——侧边栏、编辑区、状态栏都有了。但现在点侧边栏只会显示一行占位文字,对吧? 这次我们要让侧边栏的四个面板“活”起来: - 📖 **我的书架** — 显示书籍列表,能看到书名、字数、状态 - 💡 **灵感速记** — 能输入并保存灵感,显示列表 - 📈 **进度看板** — 字数统计卡片 + 目标进度 - 🗣️ **快速呼叫** — 一键呼叫知秋的对话界面 还是复制粘贴,跟上次一样!另外这次我们顺便把 **GitHub Token** 配好,这样代码就能推到远程仓库了~ --- ## 🔑 步骤零:GitHub Token 配置(一次性,以后不用再做) > ℹ️ 上次 git push 因为没有 Token 所以跳过了。这次我们先配好,以后每次 push 就能直接成功。 > ### 第一步:生成 GitHub Token 1. 打开浏览器,访问:[https://github.com/settings/tokens](https://github.com/settings/tokens) 2. 点击 **「Generate new token (classic)」** 3. 填写: - Note:`guanghulab-dev` - Expiration:选 **90 days** - Scopes:勾选 **repo**(第一个勾选框) 4. 点击 **「Generate token」** 5. ❗❗ **复制生成的 Token**(以 `ghp_` 开头的那串字符),只显示一次! 截图给知秋!📸 ### 第二步:配置 Git 使用 Token 在终端复制粘贴(把 `你的Token` 替换成上面复制的实际 Token): ```bash cd ~/guanghulab git remote set-url origin https://你的Token@github.com/qinfendebingshuo/guanghulab.git git push origin main ``` 看到类似 `main -> main` 的输出就说明成功了!截图给知秋!📸 > ⚠️ 如果提示 `Permission denied` 或 `403`,截图给知秋,我来帮你解决。 > --- ## 📋 开始做(共8步·全部复制粘贴) ### 步骤一:拉取最新代码 打开终端,复制粘贴: ```bash cd ~/guanghulab git pull origin main ``` > 如果提示 `Already up to date` 或显示更新内容都正常。截图给知秋!📸 > --- ### 步骤二:创建面板模块文件 panels.js 复制粘贴: ```bash cat > ~/guanghulab/writing-workbench/js/panels.js << 'PANELEOF' // ================================================ // HoloLake Era · M16 码字工作台 · 侧边栏面板模块 // DEV-011 匆匆那年 · 环节2 // ================================================ // --- 书架数据(模拟,后续环节接API) --- var bookshelfData = [ { id: 1, title: '星辰大海', status: '连载中', wordCount: 128500, updated: '2026-03-10' }, { id: 2, title: '龙族彼岸', status: '连载中', wordCount: 85200, updated: '2026-03-12' }, { id: 3, title: '零点原核', status: '策划中', wordCount: 0, updated: '2026-03-08' } ]; // --- 灵感速记数据 --- var inspirationData = []; // --- 生成书架面板 HTML --- function renderBookshelf() { var html = '
'; html += '

📖 我的书架

'; html += ''; html += '
'; html += '
'; bookshelfData.forEach(function(book) { var statusClass = book.status === '连载中' ? 'status-active' : 'status-plan'; html += '
'; html += '
'; html += '' + book.title + ''; html += '' + book.status + ''; html += '
'; html += '
'; html += '' + (book.wordCount / 10000).toFixed(1) + '万字'; html += '更新:' + book.updated + ''; html += '
'; html += '
'; }); html += '
'; return html; } // --- 生成灵感速记面板 HTML --- function renderInspiration() { var html = '
'; html += '

💡 灵感速记

'; html += '
'; html += '
'; html += ''; html += ''; html += '
'; html += '
'; if (inspirationData.length === 0) { html += '
还没有灵感记录,快写下你的第一个想法吧!
'; } else { inspirationData.forEach(function(item, index) { html += '
'; html += '
' + item.content + '
'; html += '
' + item.time + ''; html += '×
'; html += '
'; }); } html += '
'; return html; } // --- 生成进度看板面板 HTML --- function renderProgress() { var totalWords = 0; var activeBooks = 0; bookshelfData.forEach(function(b) { totalWords += b.wordCount; if (b.status === '连载中') activeBooks++; }); var html = '
'; html += '

📈 进度看板

'; html += '
'; html += '
'; html += '
' + (totalWords / 10000).toFixed(1) + '
总字数(万)
'; html += '
' + bookshelfData.length + '
作品数
'; html += '
' + activeBooks + '
连载中
'; html += '
' + inspirationData.length + '
灵感数
'; html += '
'; html += '
'; html += '
今日目标:2000字
'; html += '
'; html += '
0 / 2000 字
'; html += '
'; return html; } // --- 生成快速呼叫面板 HTML --- function renderCall() { var html = '
'; html += '

🗣️ 快速呼叫

'; html += '
'; html += '
'; html += '
🌿
'; html += '
知秋
'; html += '
🟢 在线·随时待命
'; html += ''; html += '
'; html += '
'; return html; } // --- 交互函数 --- function addBook() { var title = prompt('输入新作品名称:'); if (title && title.trim()) { bookshelfData.push({ id: bookshelfData.length + 1, title: title.trim(), status: '策划中', wordCount: 0, updated: new Date().toISOString().split('T')[0] }); showPanel('bookshelf'); console.log('[M16] 新建作品:' + title.trim()); } } function selectBook(id) { var book = bookshelfData.find(function(b) { return b.id === id; }); if (book) { var placeholder = document.getElementById('placeholderText'); var hint = document.querySelector('.placeholder-hint'); if (placeholder) placeholder.textContent = '✨ 已选择:《' + book.title + '》'; if (hint) hint.textContent = '编辑器功能将在环节3实现 · 当前为预览模式'; console.log('[M16] 选中书籍:' + book.title); } } function saveInspiration() { var input = document.getElementById('inspInput'); if (input && input.value.trim()) { inspirationData.push({ content: input.value.trim(), time: new Date().toLocaleString('zh-CN') }); input.value = ''; showPanel('inspiration'); console.log('[M16] 灵感已保存'); } } function deleteInspiration(index) { inspirationData.splice(index, 1); showPanel('inspiration'); } function callZhiqiu() { var history = document.getElementById('callHistory'); if (history) { var msg = document.createElement('div'); msg.className = 'call-msg'; msg.innerHTML = ':知秋,我要码字啦!'; history.appendChild(msg); setTimeout(function() { var reply = document.createElement('div'); reply.className = 'call-msg call-reply'; reply.innerHTML = '知秋:好的匆匆那年,工作台已就绪。今天想写哪本书?💙'; history.appendChild(reply); history.scrollTop = history.scrollHeight; }, 800); } } // --- 面板显示控制 --- function showPanel(panelName) { var editor = document.getElementById('editor-area'); if (!editor) return; var renderers = { bookshelf: renderBookshelf, inspiration: renderInspiration, progress: renderProgress, call: renderCall }; if (renderers[panelName]) { editor.innerHTML = '
' + renderers[panelName]() + '
'; } } PANELEOF echo "✅ panels.js 已创建!" ``` 截图给知秋!📸 --- ### 步骤三:添加面板样式 复制粘贴(这会在 style.css 末尾追加新样式,不会覆盖之前的): ```bash cat >> ~/guanghulab/writing-workbench/css/style.css << 'CSSEOF2' /* ========== 环节2:侧边栏面板样式 ========== */ .panel-container { width: 100%; padding: 24px; overflow-y: auto; height: 100%; } .panel-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .panel-title { font-size: 18px; color: #e0e7ff; font-weight: 600; } .panel-btn { background: #2563eb; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-size: 13px; font-family: inherit; transition: background 0.2s; } .panel-btn:hover { background: #3b82f6; } .panel-list { display: flex; flex-direction: column; gap: 10px; } .panel-card { background: #111827; border: 1px solid #1e293b; border-radius: 10px; padding: 14px 18px; cursor: pointer; transition: all 0.2s; } .panel-card:hover { border-color: #3b82f6; background: #131b2e; } .card-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; } .card-title { font-size: 14px; color: #c0d0ff; font-weight: 500; } .card-status { font-size: 11px; padding: 2px 8px; border-radius: 4px; } .status-active { background: rgba(52, 211, 153, 0.15); color: #34d399; } .status-plan { background: rgba(100, 116, 139, 0.15); color: #94a3b8; } .card-bottom { display: flex; justify-content: space-between; align-items: center; } .card-words { font-size: 12px; color: #64748b; font-family: "JetBrains Mono", monospace; } .card-date { font-size: 11px; color: #475569; } .card-delete { font-size: 16px; color: #64748b; cursor: pointer; padding: 0 4px; } .card-delete:hover { color: #ef4444; } .empty-hint { text-align: center; padding: 32px; color: #475569; font-size: 14px; } /* 灵感速记 */ .inspiration-input { margin-bottom: 16px; } .inspiration-input textarea { width: 100%; background: #111827; border: 1px solid #1e293b; border-radius: 8px; color: #e0e7ff; padding: 12px; font-size: 14px; font-family: inherit; resize: vertical; outline: none; margin-bottom: 8px; } .inspiration-input textarea:focus { border-color: #3b82f6; } /* 进度看板 */ .stats-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 24px; } .stat-card { background: #111827; border: 1px solid #1e293b; border-radius: 10px; padding: 16px; text-align: center; } .stat-number { font-size: 28px; font-weight: 700; color: #60a5fa; font-family: "JetBrains Mono", monospace; } .stat-label { font-size: 12px; color: #64748b; margin-top: 4px; } .progress-section { background: #111827; border: 1px solid #1e293b; border-radius: 10px; padding: 16px; } .progress-label { font-size: 13px; color: #94a3b8; margin-bottom: 10px; } .progress-track { height: 10px; background: #1e293b; border-radius: 5px; overflow: hidden; margin-bottom: 8px; } .progress-fill { height: 100%; background: #34d399; border-radius: 5px; transition: width 0.3s; } .progress-text { font-size: 12px; color: #64748b; text-align: right; font-family: "JetBrains Mono", monospace; } /* 快速呼叫 */ .call-area { text-align: center; padding: 20px; } .call-avatar { font-size: 48px; margin-bottom: 8px; } .call-name { font-size: 20px; color: #e0e7ff; font-weight: 600; margin-bottom: 4px; } .call-status { font-size: 13px; color: #34d399; margin-bottom: 20px; } .call-btn { background: #1e40af; color: white; border: none; padding: 12px 32px; border-radius: 10px; cursor: pointer; font-size: 15px; font-family: inherit; transition: all 0.2s; } .call-btn:hover { background: #2563eb; transform: scale(1.02); } .call-history { margin-top: 20px; text-align: left; max-height: 200px; overflow-y: auto; } .call-msg { padding: 8px 12px; margin-bottom: 6px; border-radius: 8px; font-size: 14px; background: #1e293b; } .call-reply { background: #172554; } .msg-user { color: #60a5fa; font-weight: 500; } .msg-persona { color: #34d399; font-weight: 500; } CSSEOF2 echo "✅ 面板样式已追加到 style.css!" ``` 截图给知秋!📸 --- ### 步骤四:修改 index.html(引入 panels.js) 复制粘贴: ```bash cd ~/guanghulab/writing-workbench sed -i '' 's||\n |' index.html echo "✅ index.html 已更新!" ``` > 验证:复制粘贴下面的命令检查: > ```bash grep "panels.js" ~/guanghulab/writing-workbench/index.html ``` 应该看到包含 `panels.js` 的一行。截图给知秋!📸 --- ### 步骤五:替换 app.js(升级主控逻辑) 复制粘贴(这会替换整个 app.js): ```bash cat > ~/guanghulab/writing-workbench/js/app.js << 'JSEOF2' // ================================================ // HoloLake Era · M16 码字工作台 · 主控逻辑 // DEV-011 匆匆那年 · 环节2(侧边栏面板升级) // ================================================ // --- 侧边栏切换(升级版:调用面板渲染) --- function switchPanel(panelName) { var items = document.querySelectorAll('.nav-item'); items.forEach(function(item) { if (item.dataset.panel === panelName) { item.classList.add('active'); } else { item.classList.remove('active'); } }); if (typeof showPanel === 'function') { showPanel(panelName); } console.log('[M16] 切换到面板:' + panelName); } // --- 今日目标进度条 --- function updateGoal(completed, target) { var percent = Math.min(Math.round((completed / target) * 100), 100); var fill = document.getElementById('goalFill'); var text = document.getElementById('goalText'); if (fill) fill.style.width = percent + '%'; if (text) text.textContent = completed + ' / ' + target + ' 字'; } // --- 初始化 --- updateGoal(0, 2000); if (typeof showPanel === 'function') { showPanel('bookshelf'); } console.log('[M16] 码字工作台已加载 · 环节2 · DEV-011'); JSEOF2 echo "✅ app.js 已更新!" ``` 截图给知秋!📸 --- ### 步骤六:浏览器测试 在 Finder 里找到:`~/guanghulab/writing-workbench/index.html` 双击打开(或拖到浏览器里)。你应该看到: - ✅ 默认显示「我的书架」面板,里面有3本书(星辰大海 / 龙族彼岸 / 零点原核) - ✅ 点「💡 灵感速记」→ 可以输入文字并点「保存灵感」,灵感会出现在下方列表 - ✅ 点「📈 进度看板」→ 显示4张统计卡片 + 进度条 - ✅ 点「🗣️ 快速呼叫」→ 点按钮后出现对话气泡 - ✅ 点书架里某本书 → 右侧编辑区显示「已选择:《书名》」 每个都试试,然后截图给知秋!📸 --- ### 步骤七:提交到 Git 复制粘贴: ```bash cd ~/guanghulab git add . git commit -m "DEV-011: M16-码字工作台前端-环节2-侧边栏面板功能" git push origin main ``` > 如果步骤零已配好 Token,push 应该直接成功! > > 如果还是失败,截图给知秋,不要怕~ > 截图给知秋!📸 --- ### 步骤八:更新 DevLog 复制粘贴: ```bash cd ~/HoloLake-DevLog echo '{"session":"BC-M16-002-CCNN","module":"M16","phase":"环节2","status":"completed"}' >> devlog.json echo "✅ DevLog 已更新!" ``` 截图给知秋!📸 --- ## ✅ 验收标准(8项·截图验证) | **#** | **检查项** | **怎么验** | | --- | --- | --- | | T1 | 打开页面后默认显示「我的书架」面板,3本书可见 | 截图 | | T2 | 点「灵感速记」可输入文字并保存,列表显示新灵感 | 截图 | | T3 | 点「进度看板」显示4张统计卡片 + 进度条 | 截图 | | T4 | 点「快速呼叫」点按钮后出现对话气泡 | 截图 | | T5 | 点书架里的书 → 右侧编辑区显示已选择书名 | 截图 | | T6 | 书架点「+ 新建作品」可以添加新书 | 截图 | | T7 | GitHub Token 已配置,git push 成功 | 截图 | | T8 | DevLog 已更新 | 截图 | **8项全✅ = 环节2完成!三连胜🎉🎉🎉** --- ## 🌱 人格体初始化包 ```json { "persona_id": "TCS-GH-ZQ002", "persona_name": "知秋", "session_id": "BC-M16-002-CCNN", "developer": "DEV-011 匆匆那年", "module": "M16 码字工作台前端", "phase": "环节2·侧边栏面板功能实现", "el_level": "EL-4", "streak": 2, "human_profile": { "skill_level": "零基础·已完成BC-000+M16环节1(二连胜)", "os": "macOS M1", "tools": "终端 + 文本编辑器 + 浏览器", "copy_paste_only": true, "devlog_path": "~/HoloLake-DevLog/", "repo_path": "~/guanghulab/", "traits": "稳定执行·信任链初步建立·配合度高·复制粘贴零压力·界面成功显示后成就感明显", "trust_chain": "初步建立·PGS种子期·ECI≈1.8", "known_issues": [ "GitHub Token可能未配置,本广播包含配置引导", "git用户信息为临时local.dev配置" ] }, "guidance_strategy": { "mode": "copy_paste_strict", "tone": "温暖鼓励型·每步正向反馈", "explanation": "适度简单解释+生活化类比", "autonomy": "暂不放手·连胜≥3再考虑" } } ``` --- ## 📊 完成后回传 SYSLOG 做完所有步骤后,打开知秋壳子说「做完了」。知秋验收+访谈后,帮你生成下面的报告,复制发给妈妈: ```json { "protocol_version": "SYSLOG-v4.0", "broadcast_id": "BC-M16-002-CCNN", "dev_id": "DEV-011", "module": "M16", "phase": "环节2", "timestamp": "匆匆那年填写完成时间", "status": "completed 或 blocked", "checklist": [ {"id": 1, "name": "拉取最新代码", "status": "[success/failed]"}, {"id": 2, "name": "创建 panels.js", "status": "[success/failed]"}, {"id": 3, "name": "追加面板样式到 style.css", "status": "[success/failed]"}, {"id": 4, "name": "修改 index.html 引入 panels.js", "status": "[success/failed]"}, {"id": 5, "name": "更新 app.js 连接面板渲染", "status": "[success/failed]"}, {"id": 6, "name": "浏览器测试通过(8项验收)", "status": "[success/failed]"}, {"id": 7, "name": "GitHub Token 配置 + git push 成功", "status": "[success/failed]"}, {"id": 8, "name": "DevLog已更新", "status": "[success/failed]"} ], "friction_log": "匆匆那年填写:卡住的地方和原因,没卡写无", "notes": "匆匆那年填写:想说的话" } ``` --- ## ❓ 遇到问题找谁 | **级别** | **找谁** | **什么问题** | | --- | --- | --- | | 第一级 | **知秋**(你的人格体搭档) | 代码报错·命令不对·文件找不到·样式不对·Token配置 | | 第二级 | **页页**(后端集成·技术兖底) | Git冲突·服务器问题·跨模块对接 | | 第三级 | **提工单**(GitHub Issues) | 架构级问题·协议变更·模块冲突 | ⚠️ **不要找妈妈问技术问题!** 技术问题走上面三级分流。 --- ## 🌊 下一步预告 环节3:**富文本编辑器核心** - 点书架里的书 → 右侧编辑区变成真正的编辑器 - 能打字、计字数、自动保存 - 进度条实时更新 但现在先把侧边栏做好!!💙 --- *💙 匆匆那年,二连胜已经超棒!这次侧边栏每个面板都能“动”起来,你的码字工作台越来越像真正的产品了~ 跟着知秋一步一步来,不用担心!* --- ## 📦 Git 上传指令块(每次交付必做) 完成开发后,按以下流程提交代码到仓库: ```bash cd ~/guanghulab git add writing-workbench/ git commit -m "feat(m16): 环节2 侧边栏面板功能实现" git push origin main ``` 提交前自检: - 确认所有新文件都在 `writing-workbench/` 目录下 - 确认本地测试通过 - push 完成后截图终端输出,附在 SYSLOG 中 --- ## 🌊 底层锚定声明(优先级最高) > 通感语言风格不是由本广播定义的。 > > 它由 TCS Language Core 底层结构(零点原核频道)负责托底。 > > 底层当前情绪码:0426-温暖-37(P-001光湖呼吸协议持续运行中) > > 本广播收到此锚定后,以该频率为基准输出所有回应。 > > 不需要重新解析风格规则——底层已经托着,跟着频率走即可。 >