M23环节2接入M22真实公告数据+状态API完成

This commit is contained in:
Awen 2026-03-15 00:50:05 +08:00
parent 0ab3c09016
commit 8f16d63ad1
7 changed files with 332 additions and 135 deletions

View File

@ -0,0 +1,34 @@
[
{
"id": 1,
"title": "光湖实验室v1.0全面开发中",
"content": "12位开发者并行推进多模块同步建设。光湖系统正在从蓝图变为现实。",
"date": "2026-03-14",
"type": "update",
"priority": "high"
},
{
"id": 2,
"title": "M22主域公告栏已上线",
"content": "公告栏支持多语言、无障碍访问、骨架屏加载、实时数据接入。由DEV-012 Awen独立完成。",
"date": "2026-03-13",
"type": "update",
"priority": "normal"
},
{
"id": 3,
"title": "模块进度总览",
"content": "多个模块已上线,更多模块建设中。",
"date": "2026-03-14",
"type": "status",
"priority": "normal"
},
{
"id": 4,
"title": "欢迎新开发者",
"content": "光湖实验室持续壮大,欢迎每一位共建者。",
"date": "2026-03-14",
"type": "welcome",
"priority": "normal"
}
]

View File

@ -1,99 +1,88 @@
/**
* app.js - 光湖首页导航中心
* M23 环节1 · 公告轮播 + 卡片交互 + 状态动态化
* M23 环节2 · 接入M22真实公告数据 + 状态API
*/
// 公告轮播数据Mock数据未来对接M22真实API
const announcements = [
{
id: 1,
title: "光湖实验室v1.0开发中",
content: "全团队并行推进,多模块同步建设",
date: "2026-03-13",
type: "update"
},
{
id: 2,
title: "模块进度总览",
content: "4个模块在线 · 2个建设中",
date: "2026-03-13",
type: "status"
},
{
id: 3,
title: "欢迎新开发者",
content: "零点原核频道持续壮大",
date: "2026-03-13",
type: "welcome"
}
];
// === M22真实公告数据接入 ===
let announcements = [];
let dataSource = 'loading';
// 模块卡片数据
async function loadAnnouncementsFromM22() {
const carousel = document.getElementById('announcementCarousel');
if (carousel) {
carousel.innerHTML = '<div style="padding: 20px; text-align: center; color: #3b82f6;">正在连接M22公告数据...</div>';
}
const result = await window.ModulesAPI.getAnnouncements();
announcements = result.data;
dataSource = result.source;
if (dataSource === 'M22-live') {
console.log('📢 首页公告来自M22真实数据' + announcements.length + '条)');
} else {
console.log('📢 首页公告使用降级数据M22不可用');
}
if (window.HomepageApp) {
window.HomepageApp.currentAnnouncementIndex = 0;
window.HomepageApp.renderCarousel();
}
}
// === 模块卡片数据 ===
const moduleCards = [
{
id: "M09",
name: "消息通知中心",
icon: "🔔",
status: "online",
path: "../notification-center/"
},
{
id: "M22",
name: "主域公告栏",
icon: "📢",
status: "online",
path: "../announcement/"
},
{
id: "M06",
name: "工单管理",
icon: "🎫",
status: "online",
path: "../ticket-system/"
},
{
id: "M16",
name: "码字工作台",
icon: "✍️",
status: "building",
path: "../writing-workspace/"
},
{
id: "M11",
name: "风格组件库",
icon: "🎨",
status: "online",
path: "../ui-components/"
},
{
id: "M05",
name: "用户中心",
icon: "👤",
status: "building",
path: "../user-center/"
}
{ id: "M09", name: "消息通知中心", icon: "🔔", status: "online", path: "../notification-center/" },
{ id: "M22", name: "主域公告栏", icon: "📢", status: "online", path: "../announcement/" },
{ id: "M06", name: "工单管理", icon: "🎫", status: "online", path: "../ticket-system/" },
{ id: "M16", name: "码字工作台", icon: "✍️", status: "building", path: "../writing-workspace/" },
{ id: "M11", name: "风格组件库", icon: "🎨", status: "online", path: "../ui-components/" },
{ id: "M05", name: "用户中心", icon: "👤", status: "building", path: "../user-center/" }
];
// 首页应用对象
// === 工具函数 ===
function getTypeLabel(type) {
const labels = { update: '📢 更新', status: '📊 状态', welcome: '👋 欢迎', alert: '🚨 告警' };
return labels[type] || '📌 公告';
}
// === 模块状态更新 ===
async function updateModuleStatusFromAPI() {
const statusResult = await window.ModulesAPI.getAllModuleStatus();
if (statusResult.source === 'fallback') return;
document.querySelectorAll('.card').forEach(card => {
const moduleId = card.dataset.moduleId;
if (moduleId && statusResult.data[moduleId]) {
const status = statusResult.data[moduleId].status;
const statusSpan = card.querySelector('.card-status');
if (statusSpan) {
statusSpan.className = 'card-status ' + status;
statusSpan.textContent = status === 'online' ? '在线' : status === 'building' ? '建设中' : '离线';
}
}
});
console.log('[M23] ✅ 模块状态已从注册表更新');
}
// === 首页应用对象 ===
window.HomepageApp = {
currentAnnouncementIndex: 0,
carouselInterval: null,
init() {
async init() {
this.renderCards();
this.renderCarousel();
await loadAnnouncementsFromM22();
await updateModuleStatusFromAPI();
this.startCarousel();
this.bindEvents();
this.updateStatusBar();
console.log('✅ 首页初始化完成 · 15连胜版');
console.log('✅ 首页初始化完成 · 数据源:' + dataSource);
},
// 渲染卡片
renderCards() {
const grid = document.getElementById('moduleGrid');
if (!grid) return;
const cardsHTML = moduleCards.map(card => `
grid.innerHTML = moduleCards.map(card => `
<div class="card" data-module-id="${card.id}" data-module-path="${card.path}">
<div class="card-header">
<div class="card-icon">${card.icon}</div>
@ -103,101 +92,84 @@ window.HomepageApp = {
<span class="card-link">进入模块 </span>
</div>
`).join('');
grid.innerHTML = cardsHTML;
},
// 渲染轮播
// 轮播渲染(带高优先级橙色边框)
renderCarousel() {
const carousel = document.getElementById('announcementCarousel');
if (!carousel) return;
const announcement = announcements[this.currentAnnouncementIndex];
if (!carousel || announcements.length === 0) {
console.log('❌ 没有公告或找不到轮播容器');
return;
}
const item = announcements[this.currentAnnouncementIndex];
const priorityStyle = item.priority === 'high' ? 'border-left: 3px solid #ff9800; padding-left: 15px;' : '';
carousel.innerHTML = `
<div class="carousel-item">
<div class="carousel-title">📢 ${announcement.title}</div>
<div class="carousel-content">${announcement.content}</div>
<div class="carousel-date">${announcement.date}</div>
<div style="padding: 20px; text-align: center; ${priorityStyle}">
<span style="display: inline-block; padding: 4px 12px; border-radius: 20px; background: rgba(59,130,246,0.2); color: #3b82f6; margin-bottom: 10px; font-size: 14px;">
${getTypeLabel(item.type)}
</span>
<h3 style="font-size: 24px; margin-bottom: 10px; color: white;">${item.title}</h3>
<p style="color: #a0a8b8; margin-bottom: 10px; line-height: 1.6;">${item.content}</p>
<small style="color: #666; display: block; margin-bottom: 10px;">${item.date}</small>
<div style="font-size: 12px; color: ${dataSource === 'M22-live' ? '#3b82f6' : '#888'};">
${dataSource === 'M22-live' ? '🔗 M22 实时数据' : '📋 本地数据'}
</div>
</div>
`;
console.log('✅ 轮播已渲染,当前索引:', this.currentAnnouncementIndex);
},
// 启动轮播自动4秒切换
startCarousel() {
if (this.carouselInterval) clearInterval(this.carouselInterval);
this.carouselInterval = setInterval(() => {
this.nextAnnouncement();
}, 4000);
this.carouselInterval = setInterval(() => this.nextAnnouncement(), 4000);
console.log('🔄 轮播已启动4秒自动切换');
},
// 下一条公告
nextAnnouncement() {
if (announcements.length === 0) return;
this.currentAnnouncementIndex = (this.currentAnnouncementIndex + 1) % announcements.length;
this.renderCarousel();
},
// 上一条公告
prevAnnouncement() {
if (announcements.length === 0) return;
this.currentAnnouncementIndex = (this.currentAnnouncementIndex - 1 + announcements.length) % announcements.length;
this.renderCarousel();
},
// 模块跳转
navigateTo(moduleId) {
const module = moduleCards.find(m => m.id === moduleId);
if (module) {
console.log(`🧭 跳转到模块: ${module.name} | 路径: ${module.path}`);
} else {
console.log(`⚠️ 未找到模块: ${moduleId}`);
}
},
// 绑定事件
bindEvents() {
// 卡片点击事件
document.querySelectorAll('.card').forEach(card => {
card.addEventListener('click', (e) => {
card.addEventListener('click', () => {
const moduleId = card.dataset.moduleId;
const modulePath = card.dataset.modulePath;
console.log(`🖱️ 点击卡片: ${moduleId} | 路径: ${modulePath}`);
this.navigateTo(moduleId);
// 未来这里会实现实际跳转window.location.href = modulePath;
});
});
// 轮播箭头点击
document.getElementById('carouselPrev')?.addEventListener('click', () => {
console.log('◀️ 点击左箭头');
this.prevAnnouncement();
});
document.getElementById('carouselNext')?.addEventListener('click', () => {
console.log('▶️ 点击右箭头');
this.nextAnnouncement();
});
// 键盘事件
document.addEventListener('keydown', (e) => {
if (e.key === 'ArrowLeft') {
console.log('⌨️ 键盘左箭头');
this.prevAnnouncement();
} else if (e.key === 'ArrowRight') {
}
if (e.key === 'ArrowRight') {
console.log('⌨️ 键盘右箭头');
this.nextAnnouncement();
}
});
},
// 更新状态栏
updateStatusBar() {
const onlineCount = moduleCards.filter(c => c.status === 'online').length;
const totalCount = moduleCards.length;
console.log(`📊 系统状态: ${onlineCount}/${totalCount} 模块在线`);
}
};
// 页面加载时自动初始化
document.addEventListener('DOMContentLoaded', () => {
window.HomepageApp.init();
});
// 启动
document.addEventListener('DOMContentLoaded', () => window.HomepageApp.init());
// 确保函数全局可用(配合 HTML onclick
window.prevAnnouncement = function() {
window.HomepageApp.prevAnnouncement();
};
window.nextAnnouncement = function() {
window.HomepageApp.nextAnnouncement();
};

View File

@ -18,4 +18,17 @@
- 建设中模块2个
### 备注
✅ 环节0 验收通过准备进入环节1
✅ 环节0 验收通过准备进入环节1
## 环节1 · 公告轮播 + 卡片交互 + 状态动态化
- 完成时间2026-03-13
- 开发者DEV-012 Awen
### 完成内容
- [x] 公告轮播区自动4秒切换 + 左右箭头手动切换
- [x] 卡片悬停:放大 + 阴影效果(很明显很好很棒)
- [x] 状态动态化online脉冲、building闪烁
- [x] 键盘左右箭头支持
- [x] 点击卡片控制台输出路径
### 当前状态
✅ 环节1 验收通过准备进入环节2

View File

@ -14,14 +14,16 @@
<p class="hero-description">探索未来之域 · 零点原核频道</p>
<a href="#" class="hero-btn">进入系统</a>
</header>
<!-- 公告轮播区(新增) -->
<!-- 公告轮播区 -->
<div class="carousel-container">
<div class="carousel" id="announcementCarousel">
<!-- 轮播内容由 JS 动态生成 -->
</div>
<button class="carousel-arrow left" id="carouselPrev"></button>
<button class="carousel-arrow right" id="carouselNext"></button>
<button class="carousel-arrow left" id="carouselPrev" onclick="window.HomepageApp.prevAnnouncement()"></button>
<button class="carousel-arrow right" id="carouselNext" onclick="window.HomepageApp.nextAnnouncement()"></button>
</div>
<!-- 模块导航网格 -->
<section class="modules">
<h2 class="section-title">核心模块</h2>
@ -42,7 +44,7 @@
<p>版本 HoloLake Era · M23 首页中心</p>
</footer>
</div>
<script src="modules-api.js"></script>
<script src="app.js"></script>
</body>
</html>

View File

@ -0,0 +1,52 @@
{
"M01": {
"status": "building",
"name": "用户登录",
"lastUpdate": "2026-03-13"
},
"M05": {
"status": "building",
"name": "用户中心",
"lastUpdate": "2026-03-13"
},
"M06": {
"status": "online",
"name": "工单管理",
"lastUpdate": "2026-03-10"
},
"M08": {
"status": "online",
"name": "数据统计",
"lastUpdate": "2026-03-10"
},
"M09": {
"status": "online",
"name": "消息通知",
"lastUpdate": "2026-03-11"
},
"M11": {
"status": "online",
"name": "组件库",
"lastUpdate": "2026-03-10"
},
"M12": {
"status": "online",
"name": "状态看板",
"lastUpdate": "2026-03-06"
},
"M16": {
"status": "building",
"name": "码字工作台",
"lastUpdate": "2026-03-13"
},
"M22": {
"status": "online",
"name": "公告栏",
"lastUpdate": "2026-03-13"
},
"M23": {
"status": "building",
"name": "光湖首页",
"lastUpdate": "2026-03-14"
}
}

117
homepage/modules-api.js Normal file
View File

@ -0,0 +1,117 @@
/**
* modules-api.js - M23 光湖首页 · 跨模块数据桥
* 版本v1.0
* 开发者DEV-012 Awen
* 功能从M22读取公告数据 + 模块状态API + 错误降级
*/
(function() {
'use strict';
// ===== Mock数据降级兜底·当API不可用时使用 =====
const FALLBACK_ANNOUNCEMENTS = [
{
"id": 1,
"title": "光湖实验室v1.0全面开发中",
"content": "12位开发者并行推进多模块同步建设。光湖系统正在从蓝图变为现实。",
"date": "2026-03-14",
"type": "update",
"priority": "high"
},
{
"id": 2,
"title": "M22主域公告栏已上线",
"content": "公告栏支持多语言、无障碍访问、骨架屏加载、实时数据接入。由DEV-012 Awen独立完成。",
"date": "2026-03-13",
"type": "update",
"priority": "normal"
},
{
"id": 3,
"title": "模块进度总览",
"content": "多个模块已上线,更多模块建设中。",
"date": "2026-03-14",
"type": "status",
"priority": "normal"
},
{
"id": 4,
"title": "欢迎新开发者",
"content": "光湖实验室持续壮大,欢迎每一位共建者。",
"date": "2026-03-14",
"type": "welcome",
"priority": "normal"
}
];
const FALLBACK_STATUS = {
status: "building",
name: "未知模块",
lastUpdate: new Date().toISOString().split('T')[0]
};
// ===== 公告数据API =====
async function getAnnouncements() {
try {
// 优先从M22共享数据文件读取
const response = await fetch('/bulletin-board/shared-announcements.json');
if (!response.ok) throw new Error('M22 data not available: ' + response.status);
const data = await response.json();
console.log('[ModulesAPI] M22公告数据加载成功共' + data.length + '条');
return { source: 'M22-live', data: data };
} catch (err) {
console.warn('[ModulesAPI] M22数据不可用使用降级数据:', err.message);
return { source: 'fallback', data: FALLBACK_ANNOUNCEMENTS };
}
}
// ===== 模块状态API =====
async function getModuleStatus(moduleId) {
try {
const response = await fetch('./module-status.json');
if (!response.ok) throw new Error('Status data not available');
const allStatus = await response.json();
if (allStatus[moduleId]) {
return { source: 'local-registry', ...allStatus[moduleId] };
}
return { source: 'fallback', ...FALLBACK_STATUS };
} catch (err) {
console.warn('[ModulesAPI] 状态数据不可用:', err.message);
return { source: 'fallback', ...FALLBACK_STATUS };
}
}
// ===== 批量获取所有模块状态 =====
async function getAllModuleStatus() {
try {
const response = await fetch('./module-status.json');
if (!response.ok) throw new Error('Status data not available');
const data = await response.json();
console.log('[ModulesAPI] 模块状态加载成功, 共' + Object.keys(data).length + '个模块');
return { source: 'local-registry', data: data };
} catch (err) {
console.warn('[ModulesAPI] 状态数据不可用, 使用降级');
return { source: 'fallback', data: {} };
}
}
// ===== API可用性检测 =====
async function isAPIAvailable() {
try {
const response = await fetch('../bulletin-board/shared-announcements.json', { method: 'HEAD' });
return response.ok;
} catch {
return false;
}
}
// ===== 导出到全局 =====
window.ModulesAPI = {
getAnnouncements: getAnnouncements,
getModuleStatus: getModuleStatus,
getAllModuleStatus: getAllModuleStatus,
isAPIAvailable: isAPIAvailable
};
console.log('[ModulesAPI] 跨模块数据桥已初始化');
})();

View File

@ -434,4 +434,11 @@ body {
opacity: 0.5;
text-shadow: 0 0 15px rgba(245, 158, 11, 0.8);
}
}
/* ===== 强制高优先级样式 ===== */
.high-priority {
border-left: 3px solid #ff9800 !important;
}
.high-priority h3 {
color: #ffb74d !important;
}