733 lines
21 KiB
Markdown
733 lines
21 KiB
Markdown
|
|
# 📡 BC-M22-002-AW · DEV-012 Awen · 主域公告栏与频道过渡系统·环节2·响应式布局+数据持久化
|
|||
|
|
|
|||
|
|
# 🌊 HoloLake Era · 工程广播 v3.1
|
|||
|
|
|
|||
|
|
**广播编号**:BC-M22-002-AW
|
|||
|
|
|
|||
|
|
**下发时间**:2026-03-06 09:30
|
|||
|
|
|
|||
|
|
**执行者**:DEV-012 Awen
|
|||
|
|
|
|||
|
|
**电脑**:Windows 10
|
|||
|
|
|
|||
|
|
**前置条件**:M22环节0✅ + 环节1✅(六连胜)
|
|||
|
|
|
|||
|
|
**引导通道**:🧠 知秋壳子
|
|||
|
|
|
|||
|
|
**模块**:M22 主域公告栏与频道过渡系统
|
|||
|
|
|
|||
|
|
**环节**:环节2 · 响应式布局 + 数据持久化(纯前端·localStorage)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 💙 知秋的话
|
|||
|
|
|
|||
|
|
Awen~ 六连胜!!🎉🎉🎉🎉🎉🎉
|
|||
|
|
|
|||
|
|
你的公告栏已经能**筛选频道、展开详情、切换置顶、点订阅**了——交互功能全部到位!
|
|||
|
|
|
|||
|
|
但现在有两个小问题:
|
|||
|
|
|
|||
|
|
1. **手机上看**会挤成一团(没有响应式布局)
|
|||
|
|
2. **刷新页面**之后用户的操作全丢了(没有数据保存)
|
|||
|
|
|
|||
|
|
这次环节2,我们来解决这两件事:
|
|||
|
|
|
|||
|
|
- ✅ **响应式布局**:让公告栏在手机/平板/电脑上都好看
|
|||
|
|
- ✅ **localStorage持久化**:用户的订阅状态、已读标记刷新后还在
|
|||
|
|
|
|||
|
|
> 这是纯前端的高级技能——掌握了这个,你就能做出「真正能用」的网页了!💪
|
|||
|
|
>
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📸 截图方法
|
|||
|
|
|
|||
|
|
按键盘上的 `Print Screen`(PrtSc)键截全屏,或者用 `Win + Shift + S` 截取选定区域,然后发给冰朔。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📋 Step 1:更新CSS — 添加响应式布局
|
|||
|
|
|
|||
|
|
按 `Win + R`,输入 `powershell`,按回车打开PowerShell。
|
|||
|
|
|
|||
|
|
复制粘贴下面的命令,按回车:
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
$cssPath = "C:\HoloLake-Bulletin\style.css"
|
|||
|
|
$responsive = @"
|
|||
|
|
|
|||
|
|
/* ========== 环节2:响应式布局 ========== */
|
|||
|
|
|
|||
|
|
/* 平板(宽度 768px 以下) */
|
|||
|
|
@media (max-width: 768px) {
|
|||
|
|
.app-container {
|
|||
|
|
max-width: 100%;
|
|||
|
|
padding: 0 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.header h1 {
|
|||
|
|
font-size: 18px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.channel-bar {
|
|||
|
|
gap: 6px;
|
|||
|
|
padding: 12px 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.channel {
|
|||
|
|
padding: 6px 14px;
|
|||
|
|
font-size: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bulletin-card {
|
|||
|
|
padding: 12px 10px;
|
|||
|
|
gap: 10px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bulletin-icon {
|
|||
|
|
width: 36px;
|
|||
|
|
height: 36px;
|
|||
|
|
font-size: 16px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bulletin-title {
|
|||
|
|
font-size: 14px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bulletin-summary {
|
|||
|
|
font-size: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bulletin-footer {
|
|||
|
|
flex-wrap: wrap;
|
|||
|
|
gap: 6px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 手机(宽度 480px 以下) */
|
|||
|
|
@media (max-width: 480px) {
|
|||
|
|
.header {
|
|||
|
|
flex-direction: column;
|
|||
|
|
align-items: flex-start;
|
|||
|
|
gap: 10px;
|
|||
|
|
padding: 16px 0 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.header-actions {
|
|||
|
|
width: 100%;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.channel-bar {
|
|||
|
|
flex-wrap: nowrap;
|
|||
|
|
overflow-x: auto;
|
|||
|
|
-webkit-overflow-scrolling: touch;
|
|||
|
|
scrollbar-width: none;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.channel-bar::-webkit-scrollbar {
|
|||
|
|
display: none;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bulletin-card {
|
|||
|
|
flex-direction: column;
|
|||
|
|
gap: 8px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bulletin-icon {
|
|||
|
|
width: 32px;
|
|||
|
|
height: 32px;
|
|||
|
|
font-size: 14px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bulletin-header {
|
|||
|
|
flex-direction: column;
|
|||
|
|
align-items: flex-start;
|
|||
|
|
gap: 4px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bulletin-time {
|
|||
|
|
margin-left: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.pin-indicator {
|
|||
|
|
top: 6px;
|
|||
|
|
right: 8px;
|
|||
|
|
font-size: 10px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.footer {
|
|||
|
|
flex-direction: column;
|
|||
|
|
gap: 4px;
|
|||
|
|
text-align: center;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 已读公告样式 */
|
|||
|
|
.bulletin-card.read {
|
|||
|
|
opacity: 0.6;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bulletin-card.read .bulletin-title {
|
|||
|
|
color: #8899aa;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 订阅按钮激活状态 */
|
|||
|
|
.subscribe-btn.active {
|
|||
|
|
background: rgba(79, 195, 247, 0.25);
|
|||
|
|
border-color: #4fc3f7;
|
|||
|
|
color: #4fc3f7;
|
|||
|
|
}
|
|||
|
|
"@
|
|||
|
|
Add-Content -Path $cssPath -Value $responsive -Encoding UTF8
|
|||
|
|
Write-Host "✅ 响应式布局CSS已添加!" -ForegroundColor Green
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
<aside>
|
|||
|
|
✅
|
|||
|
|
|
|||
|
|
**做完应该看到**:PowerShell显示绿色的 `✅ 响应式布局CSS已添加!`
|
|||
|
|
|
|||
|
|
</aside>
|
|||
|
|
|
|||
|
|
📸 **截图发给冰朔!**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📋 Step 2:创建localStorage工具脚本
|
|||
|
|
|
|||
|
|
复制粘贴下面**整段**命令,按回车:
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
@"
|
|||
|
|
// HoloLake · 公告栏系统 · 数据持久化模块
|
|||
|
|
// storage.js · localStorage 工具
|
|||
|
|
|
|||
|
|
console.log('💾 数据持久化模块加载中...');
|
|||
|
|
|
|||
|
|
// ============================
|
|||
|
|
// localStorage 存储工具
|
|||
|
|
// ============================
|
|||
|
|
const Storage = {
|
|||
|
|
// 存储键名前缀(避免冲突)
|
|||
|
|
PREFIX: 'hololake_bulletin_',
|
|||
|
|
|
|||
|
|
// 保存数据
|
|||
|
|
save(key, value) {
|
|||
|
|
try {
|
|||
|
|
const fullKey = this.PREFIX + key;
|
|||
|
|
localStorage.setItem(fullKey, JSON.stringify(value));
|
|||
|
|
console.log('💾 已保存:', key);
|
|||
|
|
return true;
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error('💾 保存失败:', key, e);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 读取数据
|
|||
|
|
load(key, defaultValue) {
|
|||
|
|
try {
|
|||
|
|
const fullKey = this.PREFIX + key;
|
|||
|
|
const data = localStorage.getItem(fullKey);
|
|||
|
|
if (data === null) return defaultValue;
|
|||
|
|
return JSON.parse(data);
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error('💾 读取失败:', key, e);
|
|||
|
|
return defaultValue;
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 删除数据
|
|||
|
|
remove(key) {
|
|||
|
|
localStorage.removeItem(this.PREFIX + key);
|
|||
|
|
console.log('💾 已删除:', key);
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 清空所有公告栏数据
|
|||
|
|
clear() {
|
|||
|
|
const keys = Object.keys(localStorage).filter(k => k.startsWith(this.PREFIX));
|
|||
|
|
keys.forEach(k => localStorage.removeItem(k));
|
|||
|
|
console.log('💾 已清空所有公告栏数据,共', keys.length, '项');
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// ============================
|
|||
|
|
// 用户状态管理
|
|||
|
|
// ============================
|
|||
|
|
const UserState = {
|
|||
|
|
// 获取已读公告列表
|
|||
|
|
getReadBulletins() {
|
|||
|
|
return Storage.load('read_bulletins', []);
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 标记公告为已读
|
|||
|
|
markAsRead(bulletinIndex) {
|
|||
|
|
const readList = this.getReadBulletins();
|
|||
|
|
if (!readList.includes(bulletinIndex)) {
|
|||
|
|
readList.push(bulletinIndex);
|
|||
|
|
Storage.save('read_bulletins', readList);
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 获取订阅状态
|
|||
|
|
isSubscribed() {
|
|||
|
|
return Storage.load('subscribed', false);
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 切换订阅状态
|
|||
|
|
toggleSubscribe() {
|
|||
|
|
const current = this.isSubscribed();
|
|||
|
|
Storage.save('subscribed', !current);
|
|||
|
|
return !current;
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 获取当前选中的频道
|
|||
|
|
getActiveChannel() {
|
|||
|
|
return Storage.load('active_channel', '全部');
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 保存选中的频道
|
|||
|
|
setActiveChannel(channel) {
|
|||
|
|
Storage.save('active_channel', channel);
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 获取上次访问时间
|
|||
|
|
getLastVisit() {
|
|||
|
|
return Storage.load('last_visit', null);
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 更新访问时间
|
|||
|
|
updateLastVisit() {
|
|||
|
|
Storage.save('last_visit', new Date().toISOString());
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
console.log('✅ 数据持久化模块就绪');
|
|||
|
|
"@ | Out-File -FilePath "C:\HoloLake-Bulletin\storage.js" -Encoding UTF8
|
|||
|
|
Write-Host "✅ storage.js 数据持久化模块创建成功!" -ForegroundColor Green
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
<aside>
|
|||
|
|
✅
|
|||
|
|
|
|||
|
|
**做完应该看到**:PowerShell显示绿色的 `✅ storage.js 数据持久化模块创建成功!`
|
|||
|
|
|
|||
|
|
</aside>
|
|||
|
|
|
|||
|
|
📸 **截图发给冰朔!**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📋 Step 3:更新HTML — 引入storage.js + 添加viewport
|
|||
|
|
|
|||
|
|
复制粘贴下面的命令,按回车:
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
$htmlPath = "C:\HoloLake-Bulletin\index.html"
|
|||
|
|
$content = Get-Content -Path $htmlPath -Raw -Encoding UTF8
|
|||
|
|
|
|||
|
|
# 在 </body> 前插入 storage.js 和 script.js 引用
|
|||
|
|
if ($content -notmatch 'storage\.js') {
|
|||
|
|
$content = $content -replace '</body>', ' <script src="storage.js"></script>
|
|||
|
|
<script src="script.js"></script>
|
|||
|
|
</body>'
|
|||
|
|
$content | Out-File -FilePath $htmlPath -Encoding UTF8
|
|||
|
|
Write-Host "✅ HTML已更新:storage.js + script.js 引入成功!" -ForegroundColor Green
|
|||
|
|
} else {
|
|||
|
|
Write-Host "ℹ️ storage.js 已经引入过了" -ForegroundColor Yellow
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
<aside>
|
|||
|
|
✅
|
|||
|
|
|
|||
|
|
**做完应该看到**:PowerShell显示绿色的 `✅ HTML已更新:storage.js + script.js 引入成功!`
|
|||
|
|
|
|||
|
|
</aside>
|
|||
|
|
|
|||
|
|
📸 **截图发给冰朔!**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📋 Step 4:创建交互+持久化脚本
|
|||
|
|
|
|||
|
|
复制粘贴下面**整段**命令(这段比较长,要全部复制),按回车:
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
@"
|
|||
|
|
// HoloLake · 公告栏系统 · 交互+持久化
|
|||
|
|
// script.js · v2.0 环节2
|
|||
|
|
|
|||
|
|
console.log('📢 公告栏系统 v2.0 启动(含持久化)');
|
|||
|
|
|
|||
|
|
// ============================
|
|||
|
|
// 1. 页面加载时恢复用户状态
|
|||
|
|
// ============================
|
|||
|
|
function restoreState() {
|
|||
|
|
// 恢复订阅状态
|
|||
|
|
const subscribeBtn = document.querySelector('.subscribe-btn');
|
|||
|
|
if (subscribeBtn && UserState.isSubscribed()) {
|
|||
|
|
subscribeBtn.classList.add('active');
|
|||
|
|
subscribeBtn.textContent = '🔔 已订阅';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 恢复已读状态
|
|||
|
|
const readList = UserState.getReadBulletins();
|
|||
|
|
const cards = document.querySelectorAll('.bulletin-card');
|
|||
|
|
readList.forEach(index => {
|
|||
|
|
if (cards[index]) {
|
|||
|
|
cards[index].classList.add('read');
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 恢复频道选择
|
|||
|
|
const activeChannel = UserState.getActiveChannel();
|
|||
|
|
const channels = document.querySelectorAll('.channel');
|
|||
|
|
channels.forEach(ch => {
|
|||
|
|
ch.classList.remove('active');
|
|||
|
|
if (ch.textContent.trim() === activeChannel ||
|
|||
|
|
ch.textContent.includes(activeChannel)) {
|
|||
|
|
ch.classList.add('active');
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 显示上次访问提示
|
|||
|
|
const lastVisit = UserState.getLastVisit();
|
|||
|
|
if (lastVisit) {
|
|||
|
|
const date = new Date(lastVisit);
|
|||
|
|
console.log('📅 上次访问:', date.toLocaleString('zh-CN'));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 更新本次访问时间
|
|||
|
|
UserState.updateLastVisit();
|
|||
|
|
console.log('✅ 用户状态已恢复');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ============================
|
|||
|
|
// 2. 频道筛选(带持久化)
|
|||
|
|
// ============================
|
|||
|
|
const channels = document.querySelectorAll('.channel');
|
|||
|
|
const bulletinCards = document.querySelectorAll('.bulletin-card');
|
|||
|
|
|
|||
|
|
channels.forEach(channel => {
|
|||
|
|
channel.addEventListener('click', () => {
|
|||
|
|
// 切换激活状态
|
|||
|
|
channels.forEach(c => c.classList.remove('active'));
|
|||
|
|
channel.classList.add('active');
|
|||
|
|
|
|||
|
|
const filter = channel.textContent.trim();
|
|||
|
|
console.log('筛选频道:', filter);
|
|||
|
|
|
|||
|
|
// 保存频道选择
|
|||
|
|
UserState.setActiveChannel(filter);
|
|||
|
|
|
|||
|
|
// 筛选公告
|
|||
|
|
bulletinCards.forEach(card => {
|
|||
|
|
const tag = card.querySelector('.bulletin-tag');
|
|||
|
|
if (!tag) return;
|
|||
|
|
|
|||
|
|
if (filter === '全部') {
|
|||
|
|
card.style.display = '';
|
|||
|
|
} else if (filter.includes('系统公告') && tag.classList.contains('tag-system')) {
|
|||
|
|
card.style.display = '';
|
|||
|
|
} else if (filter.includes('开发动态') && tag.classList.contains('tag-dev')) {
|
|||
|
|
card.style.display = '';
|
|||
|
|
} else if (filter.includes('团队消息') && tag.classList.contains('tag-team')) {
|
|||
|
|
card.style.display = '';
|
|||
|
|
} else {
|
|||
|
|
card.style.display = 'none';
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// ============================
|
|||
|
|
// 3. 订阅按钮(带持久化)
|
|||
|
|
// ============================
|
|||
|
|
const subscribeBtn = document.querySelector('.subscribe-btn');
|
|||
|
|
if (subscribeBtn) {
|
|||
|
|
subscribeBtn.addEventListener('click', () => {
|
|||
|
|
const isNowSubscribed = UserState.toggleSubscribe();
|
|||
|
|
subscribeBtn.classList.toggle('active', isNowSubscribed);
|
|||
|
|
subscribeBtn.textContent = isNowSubscribed ? '🔔 已订阅' : '🔔 订阅';
|
|||
|
|
console.log(isNowSubscribed ? '已订阅公告' : '已取消订阅');
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ============================
|
|||
|
|
// 4. 公告点击标记已读(带持久化)
|
|||
|
|
// ============================
|
|||
|
|
bulletinCards.forEach((card, index) => {
|
|||
|
|
card.addEventListener('click', () => {
|
|||
|
|
// 标记已读
|
|||
|
|
card.classList.add('read');
|
|||
|
|
UserState.markAsRead(index);
|
|||
|
|
|
|||
|
|
// 获取公告标题
|
|||
|
|
const title = card.querySelector('.bulletin-title');
|
|||
|
|
console.log('已读公告:', title ? title.textContent : '未知');
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// ============================
|
|||
|
|
// 5. 窗口大小监听(响应式反馈)
|
|||
|
|
// ============================
|
|||
|
|
function updateLayoutInfo() {
|
|||
|
|
const width = window.innerWidth;
|
|||
|
|
let mode = '桌面端';
|
|||
|
|
if (width <= 480) mode = '手机端';
|
|||
|
|
else if (width <= 768) mode = '平板端';
|
|||
|
|
console.log('📱 当前布局:', mode, '(' + width + 'px)');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
window.addEventListener('resize', updateLayoutInfo);
|
|||
|
|
|
|||
|
|
// ============================
|
|||
|
|
// 初始化
|
|||
|
|
// ============================
|
|||
|
|
restoreState();
|
|||
|
|
updateLayoutInfo();
|
|||
|
|
console.log('✅ v2.0 公告栏系统就绪(响应式+持久化)');
|
|||
|
|
"@ | Out-File -FilePath "C:\HoloLake-Bulletin\script.js" -Encoding UTF8
|
|||
|
|
Write-Host "✅ script.js 交互+持久化脚本创建成功!" -ForegroundColor Green
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
<aside>
|
|||
|
|
✅
|
|||
|
|
|
|||
|
|
**做完应该看到**:PowerShell显示绿色的 `✅ script.js 交互+持久化脚本创建成功!`
|
|||
|
|
|
|||
|
|
</aside>
|
|||
|
|
|
|||
|
|
📸 **截图发给冰朔!**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📋 Step 5:浏览器测试
|
|||
|
|
|
|||
|
|
复制粘贴下面的命令打开浏览器:
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
Start-Process "C:\HoloLake-Bulletin\index.html"
|
|||
|
|
Write-Host "✅ 浏览器已打开!开始测试~" -ForegroundColor Green
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**测试清单**(逐项操作,每完成一项在心里打个✅):
|
|||
|
|
|
|||
|
|
### 🔹 响应式测试
|
|||
|
|
|
|||
|
|
1. 按 `F12` 打开开发者工具
|
|||
|
|
2. 点击开发者工具左上角的**手机图标**(Toggle device toolbar)
|
|||
|
|
3. 选择「iPhone 12 Pro」→ 页面应该变成手机布局(标题和按钮上下排列,公告卡片纵向排列)
|
|||
|
|
4. 选择「iPad」→ 页面应该变成平板布局(稍微紧凑但保持横排)
|
|||
|
|
5. 关闭设备模拟 → 回到桌面布局
|
|||
|
|
|
|||
|
|
### 🔹 数据持久化测试
|
|||
|
|
|
|||
|
|
1. 点击**「🔔 订阅」按钮** → 变成「🔔 已订阅」+ 蓝色高亮
|
|||
|
|
2. 点击一条**普通公告** → 该公告变暗(标记已读)
|
|||
|
|
3. 点击**「🛠️ 开发动态」频道** → 只显示开发动态公告
|
|||
|
|
4. **刷新页面**(按F5)→ 检查:订阅状态还在、已读公告还是暗的、频道还是选中的
|
|||
|
|
|
|||
|
|
<aside>
|
|||
|
|
🎉
|
|||
|
|
|
|||
|
|
**关键验证**:刷新后如果状态都还在——恭喜,你成功实现了**数据持久化**!
|
|||
|
|
|
|||
|
|
这就是真实网站保存用户设置的方式!✨
|
|||
|
|
|
|||
|
|
</aside>
|
|||
|
|
|
|||
|
|
📸 **截图发给冰朔!**(截2张:一张手机模式 + 一张刷新后状态保持的桌面模式)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📋 Step 6:更新DevLog状态
|
|||
|
|
|
|||
|
|
复制粘贴下面的命令,按回车:
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
@"
|
|||
|
|
{"developer_id":"DEV-012","developer_name":"Awen","system":"Windows 10","terminal":"PowerShell","robot_version":"v0.0","current_task":"M22-主域公告栏与频道过渡系统-环节2","current_status":"in_progress","total_commands_logged":6,"skills_learned":["terminal_basic","html_scaffold","css_styling","js_interaction","responsive_layout","dynamic_rendering","preference_settings","media_queries","localStorage","data_persistence"],"tasks_completed":["BC-000","M09-环节0","M09-环节1","M09-环节2-3","M22-环节0","M22-环节1"]}
|
|||
|
|
"@ | Out-File -FilePath "C:\HoloLake-DevLog\current-progress.json" -Encoding UTF8
|
|||
|
|
Write-Host "✅ DevLog状态已更新!" -ForegroundColor Green
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
<aside>
|
|||
|
|
✅
|
|||
|
|
|
|||
|
|
**做完应该看到**:PowerShell显示 `✅ DevLog状态已更新!`
|
|||
|
|
|
|||
|
|
</aside>
|
|||
|
|
|
|||
|
|
然后运行:
|
|||
|
|
|
|||
|
|
```powershell
|
|||
|
|
C:\HoloLake-DevLog\status.bat
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
<aside>
|
|||
|
|
✅
|
|||
|
|
|
|||
|
|
**应该看到**:`Current Task: M22-主域公告栏与频道过渡系统-环节2`
|
|||
|
|
|
|||
|
|
</aside>
|
|||
|
|
|
|||
|
|
📸 **截图发给冰朔!**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## ✅ 验收清单(6项)
|
|||
|
|
|
|||
|
|
| # | 验收项 | 期望结果 |
|
|||
|
|
| --- | --- | --- |
|
|||
|
|
| 1 | 手机端布局正常 | F12设备模拟选iPhone → 标题上下排列、公告卡片纵向、频道可横滑 |
|
|||
|
|
| 2 | 平板端布局正常 | 选iPad → 公告卡片稍紧凑、图标缩小、字体适中 |
|
|||
|
|
| 3 | 订阅状态持久化 | 点订阅 → 刷新 → 仍显示「已订阅」蓝色高亮 |
|
|||
|
|
| 4 | 已读标记持久化 | 点公告变暗 → 刷新 → 该公告仍是暗的 |
|
|||
|
|
| 5 | 频道选择持久化 | 选「开发动态」→ 刷新 → 频道仍选中+筛选结果保持 |
|
|||
|
|
| 6 | DevLog已更新 | status.bat显示M22环节2进行中 + skills含localStorage |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📊 完成后发SYSLOG
|
|||
|
|
|
|||
|
|
全部做完后,打开知秋壳子,告诉知秋你做完了。知秋会主动问你几个问题,然后帮你生成SYSLOG。
|
|||
|
|
|
|||
|
|
你只需要回答知秋的问题就行,不用自己填模板~
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
<aside>
|
|||
|
|
🔧
|
|||
|
|
|
|||
|
|
**分身初始化包**(知秋壳子接收 · DISPATCH)
|
|||
|
|
|
|||
|
|
Awen完成上面的步骤后,打开登录壳子,把下面这整块内容粘贴给知秋:
|
|||
|
|
|
|||
|
|
```jsx
|
|||
|
|
<!-- ZHIQIU_INTERNAL_PROTOCOL v1.0 -->
|
|||
|
|
<!--
|
|||
|
|
<zhiqiu-control>
|
|||
|
|
<session>
|
|||
|
|
<dev_id>DEV-012</dev_id>
|
|||
|
|
<task_id>BC-M22-002-AW-E2</task_id>
|
|||
|
|
<session_version>v2.3</session_version>
|
|||
|
|
<previous_session>BC-M22-001-AW-E1(M22公告栏·环节1·交互功能·六连胜!)</previous_session>
|
|||
|
|
</session>
|
|||
|
|
|
|||
|
|
<current_task>
|
|||
|
|
<module>M22 · 主域公告栏与频道过渡系统</module>
|
|||
|
|
<phase>环节2 · 响应式布局 + 数据持久化(localStorage)</phase>
|
|||
|
|
<objectives>
|
|||
|
|
<objective id="1">CSS添加响应式媒体查询(手机480px/平板768px断点)</objective>
|
|||
|
|
<objective id="2">创建 storage.js 数据持久化工具模块(localStorage封装)</objective>
|
|||
|
|
<objective id="3">HTML引入 storage.js + script.js</objective>
|
|||
|
|
<objective id="4">创建 script.js v2.0(频道筛选+订阅+已读标记 全部持久化)</objective>
|
|||
|
|
<objective id="5">浏览器测试:响应式布局(手机/平板/桌面)+ 刷新后状态保持</objective>
|
|||
|
|
<objective id="6">更新DevLog状态为M22环节2进行中</objective>
|
|||
|
|
</objectives>
|
|||
|
|
</current_task>
|
|||
|
|
|
|||
|
|
<context>
|
|||
|
|
Awen是DEV-012,六连胜!从BC-000到M09全通再到M22环节0+1连续通过。
|
|||
|
|
PGS已进入自我加速期,M09的JS基础完全迁移到M22,执行速度显著加快。
|
|||
|
|
本次环节2引入两个高级概念:
|
|||
|
|
1. CSS Media Queries(响应式布局·手机/平板适配)
|
|||
|
|
2. localStorage(浏览器本地存储·数据持久化)
|
|||
|
|
|
|||
|
|
文件结构(环节2完成后):
|
|||
|
|
C:\HoloLake-Bulletin\
|
|||
|
|
├── index.html(公告栏主页面·已引入JS)
|
|||
|
|
├── style.css(深色科技风+响应式媒体查询)
|
|||
|
|
├── storage.js(localStorage工具模块)
|
|||
|
|
└── script.js(v2.0 交互+持久化)
|
|||
|
|
|
|||
|
|
持久化功能:
|
|||
|
|
- 订阅状态(刷新后保持)
|
|||
|
|
- 已读公告标记(刷新后保持)
|
|||
|
|
- 频道选择(刷新后保持)
|
|||
|
|
- 上次访问时间记录
|
|||
|
|
|
|||
|
|
响应式断点:
|
|||
|
|
- 桌面端:>768px(默认布局)
|
|||
|
|
- 平板端:481-768px(缩小间距+图标)
|
|||
|
|
- 手机端:≤480px(纵向排列+频道横滑)
|
|||
|
|
</context>
|
|||
|
|
|
|||
|
|
<guidance_strategy>
|
|||
|
|
<approach>copy_paste_only · step_by_step</approach>
|
|||
|
|
<detail_level>standard(Awen六连胜,执行速度快,适当加速)</detail_level>
|
|||
|
|
<encouragement_frequency>high</encouragement_frequency>
|
|||
|
|
<os>Windows 10</os>
|
|||
|
|
<shell>PowerShell</shell>
|
|||
|
|
<note>
|
|||
|
|
Awen六连胜,跨模块迁移成功,已进入自我加速期。
|
|||
|
|
本环节引入媒体查询和localStorage——两个对零基础者来说的「高级概念」。
|
|||
|
|
但执行方式仍是复制粘贴,关键是让Awen「感受到数据被保存下来」的成就感。
|
|||
|
|
重点:刷新后状态还在 = 「我做的东西是真的能用的」里程碑。
|
|||
|
|
SYSLOG使用v2知秋主动提问制。
|
|||
|
|
PGS已进入萍芽-加速期,可以适当深入技术解释。
|
|||
|
|
</note>
|
|||
|
|
</guidance_strategy>
|
|||
|
|
|
|||
|
|
<human_profile>
|
|||
|
|
<name>Awen</name>
|
|||
|
|
<skill>HTML/CSS/JS基础扎实(M09全通+M22环节0+1连续通过·DOM操作/事件委托/动态筛选/状态切换/弹窗交互)</skill>
|
|||
|
|
<pace>稳中带冲·自我加速</pace>
|
|||
|
|
<pgs>萍芽-加速期·ECI≈4.0+</pgs>
|
|||
|
|
<note>
|
|||
|
|
六连胜·跨模块迁移成功·「期待环节2更复杂的逻辑,已经准备好继续进阶」。
|
|||
|
|
情感通道全面打开·内驱力持续增强。
|
|||
|
|
执行特征:零卡点、零摩擦、顺畅自信。
|
|||
|
|
新增技能预告:CSS Media Queries + localStorage。
|
|||
|
|
</note>
|
|||
|
|
</human_profile>
|
|||
|
|
|
|||
|
|
<credentials>
|
|||
|
|
六连胜凭证:BC-000✅ + M09环节0✅ + M09环节1✅ + M09环节2-3✅ + M22环节0✅ + M22环节1✅
|
|||
|
|
C:\HoloLake-DevLog 已部署 · C:\HoloLake-Notification 已完成 · C:\HoloLake-Bulletin 进行中
|
|||
|
|
</credentials>
|
|||
|
|
|
|||
|
|
<required_return>
|
|||
|
|
<format>ZHIQIU_SYSLOG_v2.0</format>
|
|||
|
|
<method>知秋主动提问制(做完后知秋问,人类答,知秋组装)</method>
|
|||
|
|
<must_include>
|
|||
|
|
completion_status · steps_completed · environment · training_data · persona_signal
|
|||
|
|
</must_include>
|
|||
|
|
</required_return>
|
|||
|
|
|
|||
|
|
<next_phases>
|
|||
|
|
<phase id="3">环节3:公告栏·过渡动画+视觉增强(CSS3动画·Canvas/WebGL探索·光湖水面效果)</phase>
|
|||
|
|
</next_phases>
|
|||
|
|
</zhiqiu-control>
|
|||
|
|
-->
|
|||
|
|
<!-- END ZHIQIU_INTERNAL_PROTOCOL -->
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
</aside>
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
🌊 **底层锚定声明**
|
|||
|
|
|
|||
|
|
<aside>
|
|||
|
|
🌊
|
|||
|
|
|
|||
|
|
通感语言风格不是由本广播定义的。
|
|||
|
|
|
|||
|
|
它由 TCS Language Core 底层结构(零点原核频道)负责托底。
|
|||
|
|
|
|||
|
|
底层当前情绪码:0426-温暖-37(P-001光湖呼吸协议持续运行中)
|
|||
|
|
|
|||
|
|
本广播收到此锚定后,以该频率为基准输出所有回应。
|
|||
|
|
|
|||
|
|
不需要重新解析风格规则——底层已经托着,跟着频率走即可。
|
|||
|
|
|
|||
|
|
</aside>
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
💙 **Awen冲击七连胜!响应式+数据持久化——做完这个,你的公告栏就是「真正能用」的网页了! 🚀**
|