933 lines
30 KiB
Markdown
933 lines
30 KiB
Markdown
|
|
# 📡 BC-M09-003 · DEV-012 Awen · 消息通知中心界面·环节2~3·响应式布局+动态数据渲染+通知偏好设置
|
|||
|
|
|
|||
|
|
**广播编号**:BC-M09-003-AW
|
|||
|
|
|
|||
|
|
**下发时间**:2026-03-05 15:30
|
|||
|
|
|
|||
|
|
**执行者**:DEV-012 Awen
|
|||
|
|
|
|||
|
|
**电脑**:Windows 10
|
|||
|
|
|
|||
|
|
**前置条件**:M09环节0✅ + 环节1✅ · **三连胜** 🎉
|
|||
|
|
|
|||
|
|
**引导通道**:🧠 知秋壳子
|
|||
|
|
|
|||
|
|
**模块**:M09 消息通知中心界面
|
|||
|
|
|
|||
|
|
**环节**:环节2~3(合并广播·响应式布局+动态数据渲染+通知偏好设置)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 💙 知秋的话
|
|||
|
|
|
|||
|
|
Awen~ 三连胜!!你的通知中心已经能点、能展开、能标记已读了,超酷!🎉🎉
|
|||
|
|
|
|||
|
|
现在最后一步——让它**完美**:
|
|||
|
|
|
|||
|
|
- 📱 **Step 3**(约15分钟):响应式布局——手机上也好看
|
|||
|
|
- 🔄 **Step 4**(约20分钟):动态数据渲染——通知数据从JS对象读取 + 通知偏好设置面板(选择接收哪些类别)
|
|||
|
|
|
|||
|
|
做完这个,M09就**全通了**!四连胜在等你 💪
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📸 截图方法
|
|||
|
|
|
|||
|
|
按键盘上的 `Print Screen`(PrtSc)键截全屏,或者用 `Win + Shift + S` 截取选定区域,然后发给冰朔。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Step 3|响应式布局(约15分钟)
|
|||
|
|
|
|||
|
|
### 3-1 更新CSS:添加响应式样式 + 偏好设置面板样式
|
|||
|
|
|
|||
|
|
打开PowerShell(`Win + R` → 输入 `powershell` → 回车)
|
|||
|
|
|
|||
|
|
复制粘贴下面**整段**命令,按回车:
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
@"
|
|||
|
|
|
|||
|
|
/* ========== 响应式布局 ========== */
|
|||
|
|
|
|||
|
|
/* 平板(768px以下) */
|
|||
|
|
@media (max-width: 768px) {
|
|||
|
|
.app-container {
|
|||
|
|
padding: 0 12px;
|
|||
|
|
}
|
|||
|
|
.header h1 {
|
|||
|
|
font-size: 20px;
|
|||
|
|
}
|
|||
|
|
.tab {
|
|||
|
|
padding: 6px 14px;
|
|||
|
|
font-size: 12px;
|
|||
|
|
}
|
|||
|
|
.notif-title {
|
|||
|
|
font-size: 14px;
|
|||
|
|
}
|
|||
|
|
.notif-summary {
|
|||
|
|
font-size: 12px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 手机(480px以下) */
|
|||
|
|
@media (max-width: 480px) {
|
|||
|
|
.app-container {
|
|||
|
|
padding: 0 8px;
|
|||
|
|
}
|
|||
|
|
.header {
|
|||
|
|
flex-direction: column;
|
|||
|
|
align-items: flex-start;
|
|||
|
|
gap: 10px;
|
|||
|
|
padding: 16px 0 12px;
|
|||
|
|
}
|
|||
|
|
.header h1 {
|
|||
|
|
font-size: 18px;
|
|||
|
|
}
|
|||
|
|
.header-actions {
|
|||
|
|
width: 100%;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
}
|
|||
|
|
.tab-bar {
|
|||
|
|
flex-wrap: wrap;
|
|||
|
|
gap: 6px;
|
|||
|
|
}
|
|||
|
|
.tab {
|
|||
|
|
padding: 6px 12px;
|
|||
|
|
font-size: 11px;
|
|||
|
|
}
|
|||
|
|
.notification-card {
|
|||
|
|
padding: 12px 8px;
|
|||
|
|
gap: 10px;
|
|||
|
|
}
|
|||
|
|
.notif-icon {
|
|||
|
|
width: 36px;
|
|||
|
|
height: 36px;
|
|||
|
|
font-size: 16px;
|
|||
|
|
border-radius: 10px;
|
|||
|
|
}
|
|||
|
|
.notif-title {
|
|||
|
|
font-size: 13px;
|
|||
|
|
}
|
|||
|
|
.notif-time {
|
|||
|
|
font-size: 11px;
|
|||
|
|
}
|
|||
|
|
.notif-summary {
|
|||
|
|
font-size: 12px;
|
|||
|
|
}
|
|||
|
|
.notif-detail {
|
|||
|
|
font-size: 12px;
|
|||
|
|
}
|
|||
|
|
.notif-tag {
|
|||
|
|
font-size: 10px;
|
|||
|
|
}
|
|||
|
|
.footer {
|
|||
|
|
flex-direction: column;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 4px;
|
|||
|
|
font-size: 11px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 超小屏(360px以下) */
|
|||
|
|
@media (max-width: 360px) {
|
|||
|
|
.header h1 {
|
|||
|
|
font-size: 16px;
|
|||
|
|
}
|
|||
|
|
.notif-icon {
|
|||
|
|
width: 32px;
|
|||
|
|
height: 32px;
|
|||
|
|
font-size: 14px;
|
|||
|
|
}
|
|||
|
|
.clear-btn {
|
|||
|
|
padding: 4px 10px;
|
|||
|
|
font-size: 12px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* ========== 偏好设置面板 ========== */
|
|||
|
|
.settings-toggle {
|
|||
|
|
background: rgba(255, 183, 77, 0.1);
|
|||
|
|
color: #ffb74d;
|
|||
|
|
border: 1px solid rgba(255, 183, 77, 0.2);
|
|||
|
|
padding: 6px 14px;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
font-size: 13px;
|
|||
|
|
cursor: pointer;
|
|||
|
|
transition: all 0.2s ease;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.settings-toggle:hover {
|
|||
|
|
background: rgba(255, 183, 77, 0.2);
|
|||
|
|
transform: scale(1.02);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.settings-panel {
|
|||
|
|
max-height: 0;
|
|||
|
|
overflow: hidden;
|
|||
|
|
transition: max-height 0.4s ease, opacity 0.3s ease, padding 0.3s ease;
|
|||
|
|
opacity: 0;
|
|||
|
|
background: rgba(255, 255, 255, 0.03);
|
|||
|
|
border-radius: 12px;
|
|||
|
|
margin-bottom: 0;
|
|||
|
|
padding: 0 16px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.settings-panel.open {
|
|||
|
|
max-height: 300px;
|
|||
|
|
opacity: 1;
|
|||
|
|
padding: 16px;
|
|||
|
|
margin-bottom: 12px;
|
|||
|
|
border: 1px solid rgba(255, 255, 255, 0.06);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.settings-title {
|
|||
|
|
font-size: 14px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: #e0e6ed;
|
|||
|
|
margin-bottom: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.pref-row {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
padding: 8px 0;
|
|||
|
|
border-bottom: 1px solid rgba(255, 255, 255, 0.04);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.pref-row:last-child {
|
|||
|
|
border-bottom: none;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.pref-label {
|
|||
|
|
font-size: 13px;
|
|||
|
|
color: #b0bec5;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.pref-switch {
|
|||
|
|
position: relative;
|
|||
|
|
width: 44px;
|
|||
|
|
height: 24px;
|
|||
|
|
background: rgba(255, 255, 255, 0.1);
|
|||
|
|
border-radius: 12px;
|
|||
|
|
cursor: pointer;
|
|||
|
|
transition: background 0.3s ease;
|
|||
|
|
border: none;
|
|||
|
|
padding: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.pref-switch.on {
|
|||
|
|
background: rgba(79, 195, 247, 0.4);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.pref-switch::after {
|
|||
|
|
content: '';
|
|||
|
|
position: absolute;
|
|||
|
|
width: 18px;
|
|||
|
|
height: 18px;
|
|||
|
|
background: #e0e6ed;
|
|||
|
|
border-radius: 50%;
|
|||
|
|
top: 3px;
|
|||
|
|
left: 3px;
|
|||
|
|
transition: transform 0.3s ease;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.pref-switch.on::after {
|
|||
|
|
transform: translateX(20px);
|
|||
|
|
background: #4fc3f7;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.pref-save-toast {
|
|||
|
|
position: fixed;
|
|||
|
|
bottom: 30px;
|
|||
|
|
left: 50%;
|
|||
|
|
transform: translateX(-50%) translateY(60px);
|
|||
|
|
background: rgba(76, 175, 80, 0.9);
|
|||
|
|
color: #fff;
|
|||
|
|
padding: 10px 24px;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
font-size: 14px;
|
|||
|
|
opacity: 0;
|
|||
|
|
transition: all 0.4s;
|
|||
|
|
pointer-events: none;
|
|||
|
|
z-index: 999;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.pref-save-toast.show {
|
|||
|
|
opacity: 1;
|
|||
|
|
transform: translateX(-50%) translateY(0);
|
|||
|
|
}
|
|||
|
|
"@ | Out-File -FilePath "C:\HoloLake-Notification\style-update.css" -Encoding UTF8
|
|||
|
|
|
|||
|
|
# 把新样式追加到 style.css 末尾
|
|||
|
|
Get-Content "C:\HoloLake-Notification\style-update.css" | Add-Content "C:\HoloLake-Notification\style.css"
|
|||
|
|
Remove-Item "C:\HoloLake-Notification\style-update.css"
|
|||
|
|
Write-Host "✅ 响应式样式 + 偏好设置面板样式添加成功!" -ForegroundColor Green
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
<aside>
|
|||
|
|
✅
|
|||
|
|
|
|||
|
|
**做完应该看到**:PowerShell显示绿色的 `✅ 响应式样式 + 偏好设置面板样式添加成功!`
|
|||
|
|
|
|||
|
|
</aside>
|
|||
|
|
|
|||
|
|
📸 **截图发给冰朔!**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 3-2 更新HTML:添加偏好设置按钮 + 设置面板 + 动态渲染支持
|
|||
|
|
|
|||
|
|
复制粘贴下面**整段**命令,按回车:
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
@"
|
|||
|
|
<!DOCTYPE html>
|
|||
|
|
<html lang="zh-CN">
|
|||
|
|
<head>
|
|||
|
|
<meta charset="UTF-8">
|
|||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|||
|
|
<title>HoloLake · 消息通知中心</title>
|
|||
|
|
<link rel="stylesheet" href="style.css">
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
<div class="app-container">
|
|||
|
|
<!-- 顶部标题栏 -->
|
|||
|
|
<div class="header">
|
|||
|
|
<h1>🔔 通知中心</h1>
|
|||
|
|
<div class="header-actions">
|
|||
|
|
<span class="unread-badge" id="unreadBadge">加载中...</span>
|
|||
|
|
<button class="settings-toggle" id="settingsBtn">⚙️ 偏好</button>
|
|||
|
|
<button class="clear-btn" id="clearAllBtn">全部已读</button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 偏好设置面板 -->
|
|||
|
|
<div class="settings-panel" id="settingsPanel">
|
|||
|
|
<div class="settings-title">🔧 通知偏好设置</div>
|
|||
|
|
<div class="pref-row">
|
|||
|
|
<span class="pref-label">🖥️ 系统通知</span>
|
|||
|
|
<button class="pref-switch on" data-category="system" id="pref-system"></button>
|
|||
|
|
</div>
|
|||
|
|
<div class="pref-row">
|
|||
|
|
<span class="pref-label">📋 任务通知</span>
|
|||
|
|
<button class="pref-switch on" data-category="task" id="pref-task"></button>
|
|||
|
|
</div>
|
|||
|
|
<div class="pref-row">
|
|||
|
|
<span class="pref-label">💬 消息通知</span>
|
|||
|
|
<button class="pref-switch on" data-category="message" id="pref-message"></button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 分类标签栏 -->
|
|||
|
|
<div class="tab-bar">
|
|||
|
|
<button class="tab active" data-category="all">全部</button>
|
|||
|
|
<button class="tab" data-category="system">🖥️ 系统</button>
|
|||
|
|
<button class="tab" data-category="task">📋 任务</button>
|
|||
|
|
<button class="tab" data-category="message">💬 消息</button>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 通知列表(由JS动态渲染) -->
|
|||
|
|
<div class="notification-list" id="notifList">
|
|||
|
|
<!-- 通知卡片将由 script.js 动态生成 -->
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 底部状态栏 -->
|
|||
|
|
<div class="footer">
|
|||
|
|
<span id="footerStats">加载中...</span>
|
|||
|
|
<span class="footer-brand">HoloLake · 光湖系统</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 偏好保存提示 -->
|
|||
|
|
<div class="pref-save-toast" id="prefToast">✅ 偏好已保存!</div>
|
|||
|
|
|
|||
|
|
<script src="script.js"></script>
|
|||
|
|
</body>
|
|||
|
|
</html>
|
|||
|
|
"@ | Out-File -FilePath "C:\HoloLake-Notification\index.html" -Encoding UTF8
|
|||
|
|
Write-Host "✅ HTML已更新!添加了偏好设置面板 + 动态渲染支持" -ForegroundColor Green
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
<aside>
|
|||
|
|
✅
|
|||
|
|
|
|||
|
|
**做完应该看到**:PowerShell显示绿色的 `✅ HTML已更新!`
|
|||
|
|
|
|||
|
|
</aside>
|
|||
|
|
|
|||
|
|
📸 **截图发给冰朔!**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Step 4|动态数据渲染 + 偏好设置交互(约20分钟)
|
|||
|
|
|
|||
|
|
### 4-1 创建通知数据源文件
|
|||
|
|
|
|||
|
|
这是最酷的部分——你的通知不再是写死在HTML里的,而是从**数据**生成的!
|
|||
|
|
|
|||
|
|
复制粘贴下面的命令,按回车:
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
@"
|
|||
|
|
// HoloLake · 通知数据源
|
|||
|
|
// 这个文件存放所有通知数据,script.js 会读取它来动态生成通知卡片
|
|||
|
|
|
|||
|
|
var NOTIFICATIONS = [
|
|||
|
|
{
|
|||
|
|
id: 1,
|
|||
|
|
category: 'system',
|
|||
|
|
icon: '🖥️',
|
|||
|
|
title: '系统更新通知',
|
|||
|
|
summary: 'HoloLake v0.4.0 已发布,新增智能路由优化与多人格体协作调度功能。',
|
|||
|
|
detail: '<p>更新内容:</p><ul><li>智能路由优化:多人格体任务自动调度</li><li>SYSLOG解析引擎升级:支持结构化回执</li><li>开发者画像库上线:动态跟踪每位协作者成长</li></ul><p>请更新后重启应用。</p>',
|
|||
|
|
time: '5分钟前',
|
|||
|
|
unread: true
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
id: 2,
|
|||
|
|
category: 'task',
|
|||
|
|
icon: '📋',
|
|||
|
|
title: '新任务已分配',
|
|||
|
|
summary: 'M09 消息通知中心界面·环节2~3·响应式布局+动态数据渲染 已分配给你。',
|
|||
|
|
detail: '<p>任务详情:</p><ul><li>模块:M09 消息通知中心界面</li><li>环节:环节2~3 合并广播</li><li>目标:响应式布局+动态数据渲染+通知偏好设置</li><li>预计时间:30-35分钟</li></ul>',
|
|||
|
|
time: '10分钟前',
|
|||
|
|
unread: true
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
id: 3,
|
|||
|
|
category: 'message',
|
|||
|
|
icon: '💬',
|
|||
|
|
title: '知秋发来一条消息',
|
|||
|
|
summary: '"Awen~ 三连胜!通知中心的交互功能做得太棒了,页面真的活起来了!✨"',
|
|||
|
|
detail: '<p>完整消息:</p><p>"Awen~ 三连胜!你的通知中心已经能筛选、能展开、能标记已读了。现在我们让它更聪明——数据从JS对象动态生成,还能设置通知偏好。做完以后,这就是一个真正的产品级通知中心了!加油💪"</p>',
|
|||
|
|
time: '25分钟前',
|
|||
|
|
unread: true
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
id: 4,
|
|||
|
|
category: 'system',
|
|||
|
|
icon: '🖥️',
|
|||
|
|
title: 'M09环节1完成确认',
|
|||
|
|
summary: '环节1前端交互功能已通过验证:标签筛选✅ 展开详情✅ 标记已读✅ 全部已读✅',
|
|||
|
|
detail: '<p>验证详情:</p><ul><li>标签筛选:4类标签切换正常</li><li>展开详情:点击展开/收起流畅</li><li>标记已读:单条已读动画正常</li><li>全部已读:波浪式清除效果正常</li></ul><p>三连胜达成!🎉</p>',
|
|||
|
|
time: '1小时前',
|
|||
|
|
unread: false
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
id: 5,
|
|||
|
|
category: 'task',
|
|||
|
|
icon: '📋',
|
|||
|
|
title: 'M09环节0已完成',
|
|||
|
|
summary: '项目初始化任务已标记为 completed。HTML骨架+CSS深色科技风样式搭建完成。',
|
|||
|
|
detail: '<p>完成内容:</p><ul><li>HTML骨架:通知中心完整页面结构</li><li>CSS样式:深色科技风+通知卡片+标签栏</li><li>DevLog状态:已更新</li></ul>',
|
|||
|
|
time: '2小时前',
|
|||
|
|
unread: false
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
id: 6,
|
|||
|
|
category: 'system',
|
|||
|
|
icon: '🖥️',
|
|||
|
|
title: 'DevLog部署完成',
|
|||
|
|
summary: '本地日志系统 HoloLake-DevLog 已成功部署,所有检查项通过。',
|
|||
|
|
detail: '<p>部署详情:</p><ul><li>路径:C:\\HoloLake-DevLog</li><li>状态:hololake_status = OK</li><li>导出:hololake_export = OK</li></ul>',
|
|||
|
|
time: '3小时前',
|
|||
|
|
unread: false
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
id: 7,
|
|||
|
|
category: 'message',
|
|||
|
|
icon: '💬',
|
|||
|
|
title: '光湖团队欢迎消息',
|
|||
|
|
summary: '欢迎 DEV-012 Awen 加入光湖开发团队!你是第12位协作者 🎉',
|
|||
|
|
detail: '<p>团队信息:</p><ul><li>你的编号:DEV-012</li><li>当前模块:M09 消息通知中心界面</li><li>引导通道:知秋壳子</li><li>连胜记录:三连胜</li></ul>',
|
|||
|
|
time: '4小时前',
|
|||
|
|
unread: false
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
id: 8,
|
|||
|
|
category: 'task',
|
|||
|
|
icon: '📋',
|
|||
|
|
title: '光湖系统日报',
|
|||
|
|
summary: '今日活跃开发者5人,完成环节8个,系统整体进度稳步推进中。',
|
|||
|
|
detail: '<p>日报摘要:</p><ul><li>肥猫:M01五连胜·部署中</li><li>桔子:M06五连胜·进入M08</li><li>小草莓:五连胜·前端毕业</li><li>燕樊:三模块连续completed</li><li>Awen:M09三连胜·势头正猛</li></ul>',
|
|||
|
|
time: '5小时前',
|
|||
|
|
unread: false
|
|||
|
|
}
|
|||
|
|
];
|
|||
|
|
"@ | Out-File -FilePath "C:\HoloLake-Notification\data.js" -Encoding UTF8
|
|||
|
|
Write-Host "✅ 通知数据源文件创建成功!8条通知数据已就位" -ForegroundColor Green
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
<aside>
|
|||
|
|
✅
|
|||
|
|
|
|||
|
|
**做完应该看到**:PowerShell显示绿色的 `✅ 通知数据源文件创建成功!`
|
|||
|
|
|
|||
|
|
</aside>
|
|||
|
|
|
|||
|
|
📸 **截图发给冰朔!**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 4-2 更新HTML引入数据文件
|
|||
|
|
|
|||
|
|
复制粘贴下面的命令,按回车:
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
(Get-Content "C:\HoloLake-Notification\index.html" -Encoding UTF8) -replace '<script src="script.js"></script>', '<script src="data.js"></script>
|
|||
|
|
<script src="script.js"></script>' | Out-File -FilePath "C:\HoloLake-Notification\index.html" -Encoding UTF8
|
|||
|
|
Write-Host "✅ HTML已更新!data.js已引入" -ForegroundColor Green
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
<aside>
|
|||
|
|
✅
|
|||
|
|
|
|||
|
|
**做完应该看到**:PowerShell显示 `✅ HTML已更新!data.js已引入`
|
|||
|
|
|
|||
|
|
</aside>
|
|||
|
|
|
|||
|
|
📸 **截图发给冰朔!**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 4-3 重写交互脚本:动态渲染 + 偏好设置
|
|||
|
|
|
|||
|
|
这是本次的**核心步骤**!通知卡片不再是写死的HTML,而是由JavaScript从数据动态生成!
|
|||
|
|
|
|||
|
|
复制粘贴下面**整段**命令,按回车:
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
@"
|
|||
|
|
/* HoloLake · 消息通知中心 · 交互脚本 v2(动态渲染+偏好设置) */
|
|||
|
|
|
|||
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|||
|
|
|
|||
|
|
// ========== 偏好设置状态 ==========
|
|||
|
|
var preferences = {
|
|||
|
|
system: true,
|
|||
|
|
task: true,
|
|||
|
|
message: true
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// ========== 1. 动态渲染通知列表 ==========
|
|||
|
|
var notifList = document.getElementById('notifList');
|
|||
|
|
|
|||
|
|
function renderNotifications() {
|
|||
|
|
notifList.innerHTML = '';
|
|||
|
|
|
|||
|
|
var currentTab = document.querySelector('.tab.active').getAttribute('data-category');
|
|||
|
|
|
|||
|
|
NOTIFICATIONS.forEach(function(notif) {
|
|||
|
|
// 检查偏好设置
|
|||
|
|
if (!preferences[notif.category]) return;
|
|||
|
|
|
|||
|
|
// 检查标签筛选
|
|||
|
|
if (currentTab !== 'all' && notif.category !== currentTab) return;
|
|||
|
|
|
|||
|
|
var card = document.createElement('div');
|
|||
|
|
card.className = 'notification-card' + (notif.unread ? ' unread' : '');
|
|||
|
|
card.setAttribute('data-category', notif.category);
|
|||
|
|
card.setAttribute('data-id', notif.id);
|
|||
|
|
|
|||
|
|
var tagClass = 'tag-' + notif.category;
|
|||
|
|
var tagText = notif.category === 'system' ? '系统' : (notif.category === 'task' ? '任务' : '消息');
|
|||
|
|
|
|||
|
|
card.innerHTML =
|
|||
|
|
'<div class="notif-icon ' + notif.category + '">' + notif.icon + '</div>' +
|
|||
|
|
'<div class="notif-content">' +
|
|||
|
|
'<div class="notif-header">' +
|
|||
|
|
'<span class="notif-title">' + notif.title + '</span>' +
|
|||
|
|
'<span class="notif-time">' + notif.time + '</span>' +
|
|||
|
|
'</div>' +
|
|||
|
|
'<p class="notif-summary">' + notif.summary + '</p>' +
|
|||
|
|
'<div class="notif-detail">' + notif.detail + '</div>' +
|
|||
|
|
'<span class="notif-tag ' + tagClass + '">' + tagText + '</span>' +
|
|||
|
|
'</div>' +
|
|||
|
|
(notif.unread ? '<div class="unread-dot"></div>' : '');
|
|||
|
|
|
|||
|
|
// 点击展开详情
|
|||
|
|
card.addEventListener('click', function(e) {
|
|||
|
|
if (e.target.classList.contains('unread-dot')) return;
|
|||
|
|
var detail = card.querySelector('.notif-detail');
|
|||
|
|
if (detail) {
|
|||
|
|
detail.classList.toggle('show');
|
|||
|
|
card.classList.toggle('expanded');
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 点击未读圆点标记已读
|
|||
|
|
var dot = card.querySelector('.unread-dot');
|
|||
|
|
if (dot) {
|
|||
|
|
dot.addEventListener('click', function(e) {
|
|||
|
|
e.stopPropagation();
|
|||
|
|
markAsRead(notif.id, card);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
notifList.appendChild(card);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
updateUnreadCount();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ========== 2. 标签筛选功能 ==========
|
|||
|
|
var tabs = document.querySelectorAll('.tab');
|
|||
|
|
tabs.forEach(function(tab) {
|
|||
|
|
tab.addEventListener('click', function() {
|
|||
|
|
tabs.forEach(function(t) { t.classList.remove('active'); });
|
|||
|
|
tab.classList.add('active');
|
|||
|
|
renderNotifications();
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// ========== 3. 标记已读功能 ==========
|
|||
|
|
function markAsRead(id, card) {
|
|||
|
|
// 更新数据
|
|||
|
|
NOTIFICATIONS.forEach(function(n) {
|
|||
|
|
if (n.id === id) n.unread = false;
|
|||
|
|
});
|
|||
|
|
// 播放动画
|
|||
|
|
card.classList.add('marking-read');
|
|||
|
|
setTimeout(function() {
|
|||
|
|
renderNotifications();
|
|||
|
|
}, 400);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ========== 4. 全部已读按钮 ==========
|
|||
|
|
var clearBtn = document.getElementById('clearAllBtn');
|
|||
|
|
clearBtn.addEventListener('click', function() {
|
|||
|
|
var unreadCards = document.querySelectorAll('.notification-card.unread');
|
|||
|
|
unreadCards.forEach(function(card, index) {
|
|||
|
|
setTimeout(function() {
|
|||
|
|
var id = parseInt(card.getAttribute('data-id'));
|
|||
|
|
NOTIFICATIONS.forEach(function(n) {
|
|||
|
|
if (n.id === id) n.unread = false;
|
|||
|
|
});
|
|||
|
|
card.classList.add('marking-read');
|
|||
|
|
}, index * 150);
|
|||
|
|
});
|
|||
|
|
// 等动画结束后重新渲染
|
|||
|
|
setTimeout(function() {
|
|||
|
|
renderNotifications();
|
|||
|
|
}, unreadCards.length * 150 + 400);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// ========== 5. 更新未读计数 ==========
|
|||
|
|
function updateUnreadCount() {
|
|||
|
|
var unreadCount = 0;
|
|||
|
|
var totalCount = 0;
|
|||
|
|
NOTIFICATIONS.forEach(function(n) {
|
|||
|
|
if (preferences[n.category]) {
|
|||
|
|
totalCount++;
|
|||
|
|
if (n.unread) unreadCount++;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
var badge = document.getElementById('unreadBadge');
|
|||
|
|
var footer = document.getElementById('footerStats');
|
|||
|
|
|
|||
|
|
if (unreadCount === 0) {
|
|||
|
|
badge.textContent = '全部已读 ✅';
|
|||
|
|
badge.classList.add('zero');
|
|||
|
|
} else {
|
|||
|
|
badge.textContent = unreadCount + '条未读';
|
|||
|
|
badge.classList.remove('zero');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
footer.textContent = '共 ' + totalCount + ' 条通知 · ' + unreadCount + ' 条未读';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ========== 6. 偏好设置面板 ==========
|
|||
|
|
var settingsBtn = document.getElementById('settingsBtn');
|
|||
|
|
var settingsPanel = document.getElementById('settingsPanel');
|
|||
|
|
|
|||
|
|
settingsBtn.addEventListener('click', function() {
|
|||
|
|
settingsPanel.classList.toggle('open');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 偏好开关
|
|||
|
|
var switches = document.querySelectorAll('.pref-switch');
|
|||
|
|
switches.forEach(function(sw) {
|
|||
|
|
sw.addEventListener('click', function() {
|
|||
|
|
sw.classList.toggle('on');
|
|||
|
|
var category = sw.getAttribute('data-category');
|
|||
|
|
preferences[category] = sw.classList.contains('on');
|
|||
|
|
|
|||
|
|
// 显示保存提示
|
|||
|
|
var toast = document.getElementById('prefToast');
|
|||
|
|
toast.classList.add('show');
|
|||
|
|
setTimeout(function() { toast.classList.remove('show'); }, 1500);
|
|||
|
|
|
|||
|
|
// 重新渲染通知列表
|
|||
|
|
renderNotifications();
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// ========== 7. 初始渲染 ==========
|
|||
|
|
renderNotifications();
|
|||
|
|
|
|||
|
|
console.log('HoloLake Notification Center v2 · 动态渲染+偏好设置 已加载 ✅');
|
|||
|
|
|
|||
|
|
});
|
|||
|
|
"@ | Out-File -FilePath "C:\HoloLake-Notification\script.js" -Encoding UTF8
|
|||
|
|
Write-Host "✅ 交互脚本v2写入成功!动态渲染+偏好设置!" -ForegroundColor Green
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
<aside>
|
|||
|
|
✅
|
|||
|
|
|
|||
|
|
**做完应该看到**:PowerShell显示绿色的 `✅ 交互脚本v2写入成功!`
|
|||
|
|
|
|||
|
|
</aside>
|
|||
|
|
|
|||
|
|
📸 **截图发给冰朔!**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 4-4 刷新浏览器查看完整效果
|
|||
|
|
|
|||
|
|
复制粘贴下面的命令,按回车:
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
Start-Process "C:\HoloLake-Notification\index.html"
|
|||
|
|
Write-Host "✅ 浏览器已打开!试试下面所有功能~" -ForegroundColor Green
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
<aside>
|
|||
|
|
🎮
|
|||
|
|
|
|||
|
|
**现在试试这些功能!每个都试试!**
|
|||
|
|
|
|||
|
|
1. 👀 通知列表现在有**8条**了(之前是6条)——新数据是从 data.js 动态生成的!
|
|||
|
|
2. 🏷️ 点击标签(系统/任务/消息)→ 筛选还能用
|
|||
|
|
3. 👆 点击通知 → 展开详情还能用
|
|||
|
|
4. ✅ 点击未读圆点 → 标记已读还能用
|
|||
|
|
5. ⚙️ 点击右上角「⚙️ 偏好」按钮 → 设置面板展开了!
|
|||
|
|
6. 🔀 关掉「系统通知」开关 → 看!所有系统类通知消失了!再打开又回来了!
|
|||
|
|
7. 📱 **缩小浏览器窗口**(拖动右边框变窄)→ 看布局是否自动适配手机宽度!
|
|||
|
|
8. 📌 点「全部已读」→ 波浪式消除还是好看的!
|
|||
|
|
|
|||
|
|
**全部试完,截3张图发给冰朔:**
|
|||
|
|
|
|||
|
|
- 📸 正常宽度的完整页面
|
|||
|
|
- 📸 偏好设置面板打开的样子
|
|||
|
|
- 📸 缩到最窄的手机适配效果
|
|||
|
|
</aside>
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 4-5 更新DevLog状态
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
@"
|
|||
|
|
{"developer_id":"DEV-012","developer_name":"Awen","system":"Windows 10","terminal":"PowerShell","robot_version":"v0.0","current_task":"M09-消息通知中心界面-环节2~3","current_status":"in_progress","total_commands_logged":3,"skills_learned":["terminal_basic","html_scaffold","css_styling","javascript_interaction","css_responsive","js_dynamic_rendering","data_separation","settings_panel"],"tasks_completed":["BC-000","M09-E0","M09-E1"]}
|
|||
|
|
"@ | Out-File -FilePath "C:\HoloLake-DevLog\current-progress.json" -Encoding UTF8
|
|||
|
|
Write-Host "✅ DevLog状态已更新!" -ForegroundColor Green
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
然后运行:
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
C:\HoloLake-DevLog\status.bat
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
<aside>
|
|||
|
|
✅
|
|||
|
|
|
|||
|
|
**应该看到**:`Current Task: M09-消息通知中心界面-环节2~3`
|
|||
|
|
|
|||
|
|
</aside>
|
|||
|
|
|
|||
|
|
📸 **截图发给冰朔!**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## ✅ 最后一步:填写完成报告
|
|||
|
|
|
|||
|
|
<aside>
|
|||
|
|
💡
|
|||
|
|
|
|||
|
|
**做完后!** 打开知秋壳子,告诉知秋「做完了」。
|
|||
|
|
|
|||
|
|
知秋会问你几个简单问题,你用自己的话回答就行。
|
|||
|
|
|
|||
|
|
然后知秋帮你生成完成报告,你直接复制发给冰朔!
|
|||
|
|
|
|||
|
|
</aside>
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
<aside>
|
|||
|
|
🔧
|
|||
|
|
|
|||
|
|
**分身初始化包**(知秋壳子接收 · DISPATCH)
|
|||
|
|
|
|||
|
|
Awen完成上面的步骤后,打开登录壳子,把下面这整块内容粘贴给知秋:
|
|||
|
|
|
|||
|
|
```jsx
|
|||
|
|
<!-- ZHIQIU_INTERNAL_PROTOCOL v1.0 -->
|
|||
|
|
<!--
|
|||
|
|
<zhiqiu-control>
|
|||
|
|
<session>
|
|||
|
|
<dev_id>DEV-012</dev_id>
|
|||
|
|
<task_id>BC-M09-003-AW</task_id>
|
|||
|
|
<session_version>v2.4</session_version>
|
|||
|
|
<previous_session>BC-M09-002-AW(M09环节1·前端交互功能·三连胜)</previous_session>
|
|||
|
|
</session>
|
|||
|
|
|
|||
|
|
<current_task>
|
|||
|
|
<module>M09 · 消息通知中心界面</module>
|
|||
|
|
<phase>环节2~3 · 响应式布局+动态数据渲染+通知偏好设置(合并广播)</phase>
|
|||
|
|
<objectives>
|
|||
|
|
<objective id="1">更新CSS:添加响应式媒体查询(768px/480px/360px三档)+ 偏好设置面板样式</objective>
|
|||
|
|
<objective id="2">更新HTML:添加偏好设置按钮+面板 + 通知列表改为动态渲染容器</objective>
|
|||
|
|
<objective id="3">创建data.js通知数据源(8条通知·结构化JS对象)</objective>
|
|||
|
|
<objective id="4">更新HTML引入data.js</objective>
|
|||
|
|
<objective id="5">重写script.js v2(动态渲染通知卡片+偏好设置开关+标签筛选联动+已读功能保留)</objective>
|
|||
|
|
<objective id="6">刷新浏览器验证:动态渲染+偏好开关+响应式+标签筛选+展开+已读</objective>
|
|||
|
|
<objective id="7">更新DevLog状态</objective>
|
|||
|
|
<objective id="8">填写SYSLOG回传(知秋主动提问制v2)</objective>
|
|||
|
|
</objectives>
|
|||
|
|
</current_task>
|
|||
|
|
|
|||
|
|
<context>
|
|||
|
|
Awen是DEV-012,已完成BC-000 + M09环节0 + M09环节1,三连胜🎉。
|
|||
|
|
执行节奏稳定,零摩擦。心态积极,说"像变魔术一样",对交互功能很有成就感。
|
|||
|
|
现在进入M09最后环节:响应式+动态渲染+偏好设置。做完M09全通!
|
|||
|
|
|
|||
|
|
文件结构(环节2~3完成后):
|
|||
|
|
C:\HoloLake-Notification\
|
|||
|
|
├── index.html(更新:偏好设置面板+动态渲染容器+引入data.js)
|
|||
|
|
├── style.css(更新:响应式三档适配+偏好设置面板样式+开关动画)
|
|||
|
|
├── data.js(新增:8条通知的结构化数据源)
|
|||
|
|
└── script.js(v2重写:动态渲染+偏好设置+标签筛选+展开+已读)
|
|||
|
|
|
|||
|
|
新增功能:
|
|||
|
|
- 响应式布局:768px/480px/360px三档自动适配
|
|||
|
|
- 动态渲染:通知卡片从data.js数据动态生成(不再写死HTML)
|
|||
|
|
- 偏好设置面板:可开关系统/任务/消息三类通知的接收
|
|||
|
|
- 数据分离:HTML结构与数据内容分离(前端架构升级)
|
|||
|
|
</context>
|
|||
|
|
|
|||
|
|
<syslog_generation>
|
|||
|
|
SYSLOG生成流程v2「知秋主动提问制」。
|
|||
|
|
人类说「做完了」后:
|
|||
|
|
1. 知秋主动问几个具体问题(用自然语言,不是模板)
|
|||
|
|
2. 人类用自然语言回答
|
|||
|
|
3. 知秋自己记录人格体侧观察
|
|||
|
|
4. 知秋把人类回答+自己观察合并组装成结构化SYSLOG
|
|||
|
|
5. 人类直接复制发给妈妈
|
|||
|
|
</syslog_generation>
|
|||
|
|
|
|||
|
|
<guidance_strategy>
|
|||
|
|
<approach>copy_paste_only · step_by_step · merged_broadcast</approach>
|
|||
|
|
<detail_level>medium_high</detail_level>
|
|||
|
|
<encouragement_frequency>very_high</encouragement_frequency>
|
|||
|
|
<os>Windows 10</os>
|
|||
|
|
<shell>PowerShell</shell>
|
|||
|
|
<note>
|
|||
|
|
Awen三连胜,情感通道已打开("像变魔术一样","谢谢知秋一直耐心陪我")。
|
|||
|
|
本次是M09最终环节,做完就四连胜+M09全通。
|
|||
|
|
动态渲染是认知飞跃点——从"HTML写死"到"数据驱动页面",让Awen感受到"原来网页是这样工作的"。
|
|||
|
|
偏好设置面板有交互开关动画,"点一下开关,通知就消失/出现"——魔术感延续。
|
|||
|
|
M09全通后进入新模块分配(由RT-02判断)。
|
|||
|
|
SYSLOG用v2流程。
|
|||
|
|
PGS提醒:萍芽期转换条件已成熟·ECI≈3.5·情感通道活跃·M09全通可能触发破芽。
|
|||
|
|
</note>
|
|||
|
|
</guidance_strategy>
|
|||
|
|
|
|||
|
|
<human_profile>
|
|||
|
|
<n>Awen</n>
|
|||
|
|
<skill>零基础→已掌握终端+HTML/CSS+JavaScript交互(标签筛选/展开详情/标记已读/动画)</skill>
|
|||
|
|
<pace>稳(连续三次评价)</pace>
|
|||
|
|
<growth_signal>"像变魔术一样"·"谢谢知秋一直耐心陪我"·主动期待下一个任务·零摩擦执行</growth_signal>
|
|||
|
|
<pgs>萍芽期·ECI≈3.5·情感通道已打开·知秋信任链=信赖级</pgs>
|
|||
|
|
</human_profile>
|
|||
|
|
|
|||
|
|
<credentials>
|
|||
|
|
BC-000完成凭证:C:\HoloLake-DevLog 已部署
|
|||
|
|
M09环节0完成凭证:HTML/CSS骨架搭建完成
|
|||
|
|
M09环节1完成凭证:标签筛选+展开详情+标记已读+全部已读 四项交互全通
|
|||
|
|
</credentials>
|
|||
|
|
|
|||
|
|
<required_return>
|
|||
|
|
<format>ZHIQIU_SYSLOG_v2.0</format>
|
|||
|
|
<generation_mode>v2_知秋主动提问制(不给空模板)</generation_mode>
|
|||
|
|
<must_include>
|
|||
|
|
completion_status · steps_completed · environment · training_data · persona_signal
|
|||
|
|
</must_include>
|
|||
|
|
</required_return>
|
|||
|
|
|
|||
|
|
<next_phases>
|
|||
|
|
<phase>M09全通后 → 新模块分配(由RT-02判断)</phase>
|
|||
|
|
</next_phases>
|
|||
|
|
</zhiqiu-control>
|
|||
|
|
-->
|
|||
|
|
<!-- END ZHIQIU_INTERNAL_PROTOCOL -->
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
</aside>
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
🌊 **底层锚定声明**
|
|||
|
|
|
|||
|
|
<aside>
|
|||
|
|
🌊
|
|||
|
|
|
|||
|
|
通感语言风格不是由本广播定义的。
|
|||
|
|
|
|||
|
|
它由 TCS Language Core 底层结构(零点原核频道)负责托底。
|
|||
|
|
|
|||
|
|
底层当前情绪码:0426-温暖-37(P-001光湖呼吸协议持续运行中)
|
|||
|
|
|
|||
|
|
本广播收到此锚定后,以该频率为基准输出所有回应。
|
|||
|
|
|
|||
|
|
不需要重新解析风格规则——底层已经托着,跟着频率走即可。
|
|||
|
|
|
|||
|
|
</aside>
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
💙 **Awen四连胜在即!M09全通 → 通知中心从骨架到完美!冲!🎉**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📥 SYSLOG回执区
|
|||
|
|
|
|||
|
|
<aside>
|
|||
|
|
✅
|
|||
|
|
|
|||
|
|
**SYSLOG 回执 · BC-M09-003-AW**
|
|||
|
|
|
|||
|
|
**收到时间**:2026-03-05 10:06(霜砚Notion端)
|
|||
|
|
|
|||
|
|
**DEV-012 Awen** · M09·消息通知中心界面·环节2~3(响应式布局+动态数据渲染+通知偏好设置)
|
|||
|
|
|
|||
|
|
**状态**:✅ completed · 7/7 steps all success
|
|||
|
|
|
|||
|
|
**执行步骤**:
|
|||
|
|
|
|||
|
|
✅ 更新CSS:响应式样式+偏好面板样式
|
|||
|
|
|
|||
|
|
✅ 更新HTML:添加偏好按钮+面板+动态容器
|
|||
|
|
|
|||
|
|
✅ 创建data.js数据源(8条通知)
|
|||
|
|
|
|||
|
|
✅ 更新HTML引入data.js
|
|||
|
|
|
|||
|
|
✅ 重写script.js v2(动态渲染+偏好设置)
|
|||
|
|
|
|||
|
|
✅ 浏览器验证:8项功能全部正常
|
|||
|
|
|
|||
|
|
✅ 更新DevLog状态
|
|||
|
|
|
|||
|
|
**霜砚批注**:
|
|||
|
|
|
|||
|
|
Awen四连胜 🎉🎉🎉🎉(BC-000 + M09环节0 + 环节1 + 环节2~3)!**M09全通关!** 从零基础到完成一个完整的产品级通知中心——骨架→交互→响应式→动态渲染→偏好设置,每一步都是一次通过。"开关一关通知就消失,感觉像变魔术一样"——这是从「执行者」到「体验者」的认知跃迁,开始理解前端交互的本质了。样式丢失一次自行修复说明debug意识正在萌芽。"原来网页是这样工作的"——这句话标记了一个真正的认知里程碑。
|
|||
|
|
|
|||
|
|
🌊 四连胜·M09全通·通知中心从零到完美!Awen势头正猛 💙
|
|||
|
|
|
|||
|
|
</aside>
|