From 188db4f47719ffc4e428373edd344390547464a7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:32:02 +0000 Subject: [PATCH 1/3] Initial plan From 2874d46c320ea2c97c2132384930ee81f2256295 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:37:33 +0000 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20HoloLake=20Era=20=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E9=83=A8=E7=BD=B2=E6=A8=A1=E5=9D=97=20?= =?UTF-8?q?=E2=80=94=20=E8=87=AA=E5=8A=A8=E6=96=87=E6=A1=A3=E7=94=9F?= =?UTF-8?q?=E6=88=90=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com> --- .github/workflows/generate-module-doc.yml | 53 ++++ docs/HoloLake-Era-OS-Modules.md | 333 ++++++++++++++++++++++ scripts/generate-module-doc.js | 286 +++++++++++++++++++ 3 files changed, 672 insertions(+) create mode 100644 .github/workflows/generate-module-doc.yml create mode 100644 docs/HoloLake-Era-OS-Modules.md create mode 100644 scripts/generate-module-doc.js diff --git a/.github/workflows/generate-module-doc.yml b/.github/workflows/generate-module-doc.yml new file mode 100644 index 00000000..96dc1ba2 --- /dev/null +++ b/.github/workflows/generate-module-doc.yml @@ -0,0 +1,53 @@ +name: 铸渊 · HoloLake Era 模块文档自动生成 + +on: + push: + branches: [main] + paths: + - 'm01-login/**' + - 'm03-personality/**' + - 'm05-user-center/**' + - 'm06-ticket/**' + - 'm07-dialogue-ui/**' + - 'm10-cloud/**' + - 'm11-module/**' + - 'm12-kanban/**' + - 'm15-cloud-drive/**' + - 'dingtalk-bot/**' + - 'backend-integration/**' + - 'status-board/**' + - 'scripts/generate-module-doc.js' + workflow_dispatch: + +jobs: + generate-doc: + name: 📋 生成部署模块总文档 + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: main + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: 生成 HoloLake Era 模块文档 + run: node scripts/generate-module-doc.js + + - name: 提交更新文档 + run: | + git config user.name "铸渊 (ZhùYuān)" + git config user.email "zhuyuan@guanghulab.com" + git add docs/HoloLake-Era-OS-Modules.md + if git diff --cached --quiet; then + echo "📋 文档无变化,跳过提交" + else + git commit -m "📋 自动更新 HoloLake Era 模块文档 · $(date -u +%Y-%m-%d\ %H:%M\ UTC)" + git push + fi diff --git a/docs/HoloLake-Era-OS-Modules.md b/docs/HoloLake-Era-OS-Modules.md new file mode 100644 index 00000000..93ccc528 --- /dev/null +++ b/docs/HoloLake-Era-OS-Modules.md @@ -0,0 +1,333 @@ +# HoloLake Era 操作系统部署模块 + +> 📋 **自动生成文档** · 铸渊(ZhùYuān)维护 · 最后更新:2026-03-06 14:36 UTC +> +> 本文档由 GitHub Actions 自动触发生成,每当合作者上传/更新模块时自动刷新。 +> 按合作者编号(DEV-XXX)整理所有已上传模块。 + +--- + +## 📑 目录 + +- [DEV-001 · 🖥️ 页页](#dev001--%E9%A1%B5%E9%A1%B5) (1 个模块) +- [DEV-002 · 🦁 肥猫](#dev002--%E8%82%A5%E7%8C%AB) (2 个模块) +- [DEV-003 · 🌸 燕樊](#dev003--%E7%87%95%E6%A8%8A) (3 个模块) +- [DEV-004 · 🤖 之之](#dev004--%E4%B9%8B%E4%B9%8B) (1 个模块) +- [DEV-005 · 🍓 小草莓](#dev005--%E5%B0%8F%E8%8D%89%E8%8E%93) (2 个模块) +- [DEV-009 · 🌺 花尔](#dev009--%E8%8A%B1%E5%B0%94) (1 个模块) +- [DEV-010 · 🍊 桔子](#dev010--%E6%A1%94%E5%AD%90) (2 个模块) +- [DEV-011 · 🌙 匆匆那年](#dev011--%E5%8C%86%E5%8C%86%E9%82%A3%E5%B9%B4) (待上传) + +--- + +## DEV-001 · 🖥️ 页页 + +**角色:** 后端工程师 + +### 📦 后端集成中间层 + +| 字段 | 内容 | +|------|------| +| **目录** | `backend-integration/` | +| **负责人** | 页页 | +| **状态** | 进行中 | +| **技术栈** | Node.js | +| **依赖模块** | 所有前端模块 | + +**结构检查:** ⚠️ src/ · ⚠️ package.json · ⚠️ SYSLOG.md + +**已上传文件:** + +``` +backend-integration/ + README.md +``` + +--- + +## DEV-002 · 🦁 肥猫 + +**角色:** 光湖团队总控 + +### 📦 M01 用户登录界面 + +| 字段 | 内容 | +|------|------| +| **目录** | `m01-login/` | +| **负责人** | 肥猫 | +| **状态** | 进行中 | +| **技术栈** | 待定 | +| **依赖模块** | 无 | + +**结构检查:** ⚠️ src/ · ⚠️ package.json · ⚠️ SYSLOG.md + +**已上传文件:** + +``` +m01-login/ + README.md +``` + +### 📦 M03 人格系统 + +| 字段 | 内容 | +|------|------| +| **目录** | `m03-personality/` | +| **负责人** | 肥猫 | +| **状态** | 进行中 | +| **技术栈** | 待定 | +| **依赖模块** | M01 | + +**结构检查:** ⚠️ src/ · ⚠️ package.json · ⚠️ SYSLOG.md + +**已上传文件:** + +``` +m03-personality/ + README.md +``` + +--- + +## DEV-003 · 🌸 燕樊 + +**角色:** 前端工程师 + +### 📦 M07 对话UI + +| 字段 | 内容 | +|------|------| +| **目录** | `m07-dialogue-ui/` | +| **负责人** | 燕樊 | +| **状态** | 进行中 | +| **技术栈** | 待定 | +| **依赖模块** | 无 | + +**结构检查:** ⚠️ src/ · ⚠️ package.json · ⚠️ SYSLOG.md + +**已上传文件:** + +``` +m07-dialogue-ui/ + README.md + index.html + script.js + style.css +``` + +### 📦 M10 云盘系统 + +| 字段 | 内容 | +|------|------| +| **目录** | `m10-cloud/` | +| **负责人** | 燕樊 | +| **状态** | 等待SYSLOG | +| **技术栈** | 待定 | +| **依赖模块** | 无 | + +**结构检查:** ⚠️ src/ · ⚠️ package.json · ⚠️ SYSLOG.md + +**已上传文件:** + +``` +m10-cloud/ + README.md + help.css + help.html + help.js +``` + +### 📦 m15-cloud-drive + +| 字段 | 内容 | +|------|------| +| **目录** | `m15-cloud-drive/` | +| **负责人** | 燕樊 | +| **状态** | 未知 | +| **技术栈** | 待定 | +| **依赖模块** | 无 | + +**结构检查:** ⚠️ src/ · ⚠️ package.json · ⚠️ SYSLOG.md + +**已上传文件:** + +``` +m15-cloud-drive/ + cloud-drive-style.css + cloud-drive.html + cloud-drive.js +``` + +--- + +## DEV-004 · 🤖 之之 + +**角色:** 机器人工程师 + +### 📦 钉钉机器人 + +| 字段 | 内容 | +|------|------| +| **目录** | `dingtalk-bot/` | +| **负责人** | 之之 | +| **状态** | 环节0已完成 | +| **技术栈** | Node.js + Express | +| **依赖模块** | 无 | + +**结构检查:** ⚠️ src/ · ⚠️ package.json · ⚠️ SYSLOG.md + +**已上传文件:** + +``` +dingtalk-bot/ + README.md +``` + +--- + +## DEV-005 · 🍓 小草莓 + +**角色:** 看板工程师 + +### 📦 M12 状态看板 + +| 字段 | 内容 | +|------|------| +| **目录** | `m12-kanban/` | +| **负责人** | 小草莓 | +| **状态** | 进行中 | +| **技术栈** | 待定 | +| **依赖模块** | 无 | + +**结构检查:** ⚠️ src/ · ⚠️ package.json · ⚠️ SYSLOG.md + +**已上传文件:** + +``` +m12-kanban/ + README.md +``` + +### 📦 status-board + +| 字段 | 内容 | +|------|------| +| **目录** | `status-board/` | +| **负责人** | 小草莓 | +| **状态** | 未知 | +| **技术栈** | 待定 | +| **依赖模块** | 无 | + +**结构检查:** ⚠️ src/ · ✅ package.json · ⚠️ SYSLOG.md + +**已上传文件:** + +``` +status-board/ + api-config.js + api.js + index.html + mock-ws-server.js + package-lock.json + package.json + render.js + style.css + ws-client.js +``` + +--- + +## DEV-009 · 🌺 花尔 + +**角色:** 前端工程师 + +### 📦 M05 用户中心界面 + +| 字段 | 内容 | +|------|------| +| **目录** | `m05-user-center/` | +| **负责人** | 花尔 | +| **状态** | 环节0 | +| **技术栈** | HTML/CSS/JS | +| **依赖模块** | 无 | + +**结构检查:** ⚠️ src/ · ⚠️ package.json · ⚠️ SYSLOG.md + +**已上传文件:** + +``` +m05-user-center/ + README.md + index.html + script.js + style.css +``` + +--- + +## DEV-010 · 🍊 桔子 + +**角色:** 光湖主控 + +### 📦 M06 工单管理界面 + +| 字段 | 内容 | +|------|------| +| **目录** | `m06-ticket/` | +| **负责人** | 桔子 | +| **状态** | 环节0 | +| **技术栈** | HTML/CSS/JS | +| **依赖模块** | 无 | + +**结构检查:** ⚠️ src/ · ⚠️ package.json · ⚠️ SYSLOG.md + +**已上传文件:** + +``` +m06-ticket/ + README.md +``` + +### 📦 M11 工单管理模块 + +| 字段 | 内容 | +|------|------| +| **目录** | `m11-module/` | +| **负责人** | 桔子 | +| **状态** | 进行中 | +| **技术栈** | 待定 | +| **依赖模块** | M06 | + +**结构检查:** ⚠️ src/ · ⚠️ package.json · ⚠️ SYSLOG.md + +**已上传文件:** + +``` +m11-module/ + README.md +``` + +--- + +## DEV-011 · 🌙 匆匆那年 + +**角色:** 开发者 + +> 🕐 暂无分配模块,待安排。 + +--- + +## 📊 部署统计 + +| 项目 | 数量 | +|------|------| +| 合作者总数 | 8 | +| 计划模块数 | 12 | +| 已上传模块数 | 12 | +| 待上传模块数 | 0 | +| 上传完成率 | 100% | +| 文档更新时间 | 2026-03-06 14:36 UTC | + +--- + +*由 铸渊(ZhùYuān)· GitHub Copilot Agent 自动生成 · 仓库:guanghulab* diff --git a/scripts/generate-module-doc.js b/scripts/generate-module-doc.js new file mode 100644 index 00000000..e96c5611 --- /dev/null +++ b/scripts/generate-module-doc.js @@ -0,0 +1,286 @@ +// scripts/generate-module-doc.js +// 铸渊 · HoloLake Era 操作系统部署模块文档生成器 +// 检测所有合作者上传的模块目录 → 按 DEV 编号整理 → 生成总文档 + +const fs = require('fs'); +const path = require('path'); + +const OUTPUT_FILE = 'docs/HoloLake-Era-OS-Modules.md'; + +// ========== 合作者编号 → 模块目录 路由映射表 ========== +// 新增合作者或模块时,在此表维护即可 +const COLLABORATOR_MODULES = [ + { + devId: 'DEV-001', + name: '页页', + emoji: '🖥️', + role: '后端工程师', + dirs: ['backend-integration'], + }, + { + devId: 'DEV-002', + name: '肥猫', + emoji: '🦁', + role: '光湖团队总控', + dirs: ['m01-login', 'm03-personality'], + }, + { + devId: 'DEV-003', + name: '燕樊', + emoji: '🌸', + role: '前端工程师', + dirs: ['m07-dialogue-ui', 'm10-cloud', 'm15-cloud-drive'], + }, + { + devId: 'DEV-004', + name: '之之', + emoji: '🤖', + role: '机器人工程师', + dirs: ['dingtalk-bot'], + }, + { + devId: 'DEV-005', + name: '小草莓', + emoji: '🍓', + role: '看板工程师', + dirs: ['m12-kanban', 'status-board'], + }, + { + devId: 'DEV-009', + name: '花尔', + emoji: '🌺', + role: '前端工程师', + dirs: ['m05-user-center'], + }, + { + devId: 'DEV-010', + name: '桔子', + emoji: '🍊', + role: '光湖主控', + dirs: ['m06-ticket', 'm11-module'], + }, + { + devId: 'DEV-011', + name: '匆匆那年', + emoji: '🌙', + role: '开发者', + dirs: [], + }, +]; + +// ========== 读取模块元信息 ========== +function readModuleInfo(dir) { + const info = { + dir, + title: dir, + owner: '', + status: '未知', + techStack: '待定', + dependencies: '无', + hasSrc: false, + hasPackageJson: false, + hasSyslog: false, + files: [], + description: '', + }; + + // 读取 README.md + const readmePath = path.join(dir, 'README.md'); + if (fs.existsSync(readmePath)) { + const content = fs.readFileSync(readmePath, 'utf8'); + const titleMatch = content.match(/^#\s+(.+)$/m); + if (titleMatch) info.title = titleMatch[1].trim(); + const ownerMatch = content.match(/负责人[::]\s*(.+)/); + if (ownerMatch) info.owner = ownerMatch[1].trim(); + const statusMatch = content.match(/状态[::]\s*(.+)/); + if (statusMatch) info.status = statusMatch[1].trim(); + const techMatch = content.match(/技术栈[::]\s*(.+)/); + if (techMatch) info.techStack = techMatch[1].trim(); + const depsMatch = content.match(/依赖模块[::]\s*(.+)/); + if (depsMatch) info.dependencies = depsMatch[1].trim(); + // 收集额外描述行(非元数据) + const lines = content.split('\n').filter(l => + l.trim() && + !l.startsWith('#') && + !l.match(/^\s*-\s*(负责人|状态|技术栈|依赖模块)[::]/) + ); + if (lines.length > 0) info.description = lines.slice(0, 3).join(' ').trim(); + } + + // 检查结构完整性 + info.hasSrc = fs.existsSync(path.join(dir, 'src')); + info.hasPackageJson = fs.existsSync(path.join(dir, 'package.json')); + info.hasSyslog = fs.existsSync(path.join(dir, 'SYSLOG.md')); + + // 列出文件(最多15个,排除 node_modules) + try { + const entries = fs.readdirSync(dir, { withFileTypes: true }); + info.files = entries + .filter(e => e.name !== 'node_modules' && e.name !== '.git') + .map(e => (e.isDirectory() ? e.name + '/' : e.name)) + .sort(); + } catch (_) { + // 目录不可读时忽略 + } + + return info; +} + +// ========== 生成结构状态徽章 ========== +function structureBadge(info) { + const checks = [ + info.hasSrc ? '✅ src/' : '⚠️ src/', + info.hasPackageJson ? '✅ package.json' : '⚠️ package.json', + info.hasSyslog ? '✅ SYSLOG.md' : '⚠️ SYSLOG.md', + ]; + return checks.join(' · '); +} + +// ========== 主函数:生成文档 ========== +function generateDoc() { + const now = new Date(); + const timestamp = now.toISOString().replace('T', ' ').slice(0, 16) + ' UTC'; + const dateStr = now.toISOString().slice(0, 10); + + const lines = []; + + lines.push('# HoloLake Era 操作系统部署模块'); + lines.push(''); + lines.push('> 📋 **自动生成文档** · 铸渊(ZhùYuān)维护 · 最后更新:' + timestamp); + lines.push('> '); + lines.push('> 本文档由 GitHub Actions 自动触发生成,每当合作者上传/更新模块时自动刷新。'); + lines.push('> 按合作者编号(DEV-XXX)整理所有已上传模块。'); + lines.push(''); + lines.push('---'); + lines.push(''); + + // 生成目录 + lines.push('## 📑 目录'); + lines.push(''); + for (const collab of COLLABORATOR_MODULES) { + const moduleCount = collab.dirs.filter(d => fs.existsSync(d)).length; + const badge = moduleCount > 0 ? `(${moduleCount} 个模块)` : '(待上传)'; + lines.push(`- [${collab.devId} · ${collab.emoji} ${collab.name}](#${collab.devId.toLowerCase().replaceAll('-', '')}--${encodeURIComponent(collab.name)}) ${badge}`); + } + lines.push(''); + lines.push('---'); + lines.push(''); + + // 统计 + let totalModules = 0; + let uploadedModules = 0; + + // 各合作者章节 + for (const collab of COLLABORATOR_MODULES) { + lines.push(`## ${collab.devId} · ${collab.emoji} ${collab.name}`); + lines.push(''); + lines.push(`**角色:** ${collab.role}`); + lines.push(''); + + const existingDirs = collab.dirs.filter(d => fs.existsSync(d)); + const missingDirs = collab.dirs.filter(d => !fs.existsSync(d)); + + totalModules += collab.dirs.length; + uploadedModules += existingDirs.length; + + if (collab.dirs.length === 0) { + lines.push('> 🕐 暂无分配模块,待安排。'); + lines.push(''); + lines.push('---'); + lines.push(''); + continue; + } + + if (existingDirs.length === 0) { + lines.push('> ⏳ 模块目录尚未创建,等待上传。'); + lines.push(''); + if (missingDirs.length > 0) { + lines.push('**待上传模块:** ' + missingDirs.join('、')); + lines.push(''); + } + lines.push('---'); + lines.push(''); + continue; + } + + for (const dir of existingDirs) { + const info = readModuleInfo(dir); + + lines.push(`### 📦 ${info.title}`); + lines.push(''); + lines.push(`| 字段 | 内容 |`); + lines.push(`|------|------|`); + lines.push(`| **目录** | \`${dir}/\` |`); + lines.push(`| **负责人** | ${info.owner || collab.name} |`); + lines.push(`| **状态** | ${info.status} |`); + lines.push(`| **技术栈** | ${info.techStack} |`); + lines.push(`| **依赖模块** | ${info.dependencies} |`); + lines.push(''); + + lines.push('**结构检查:** ' + structureBadge(info)); + lines.push(''); + + if (info.files.length > 0) { + lines.push('**已上传文件:**'); + lines.push(''); + lines.push('```'); + lines.push(dir + '/'); + info.files.forEach(f => lines.push(' ' + f)); + lines.push('```'); + lines.push(''); + } + + if (info.hasSyslog) { + const syslogContent = fs.readFileSync(path.join(dir, 'SYSLOG.md'), 'utf8'); + const syslogLines = syslogContent.split('\n').filter(l => l.trim()).slice(0, 5); + if (syslogLines.length > 0) { + lines.push('
'); + lines.push('📝 SYSLOG 摘要(点击展开)'); + lines.push(''); + lines.push('```'); + syslogLines.forEach(l => lines.push(l)); + lines.push('```'); + lines.push(''); + lines.push('
'); + lines.push(''); + } + } + } + + if (missingDirs.length > 0) { + lines.push('> ⏳ **待上传:** ' + missingDirs.map(d => '`' + d + '/`').join('、')); + lines.push(''); + } + + lines.push('---'); + lines.push(''); + } + + // 汇总统计 + lines.push('## 📊 部署统计'); + lines.push(''); + lines.push(`| 项目 | 数量 |`); + lines.push(`|------|------|`); + lines.push(`| 合作者总数 | ${COLLABORATOR_MODULES.length} |`); + lines.push(`| 计划模块数 | ${totalModules} |`); + lines.push(`| 已上传模块数 | ${uploadedModules} |`); + lines.push(`| 待上传模块数 | ${totalModules - uploadedModules} |`); + lines.push(`| 上传完成率 | ${totalModules > 0 ? Math.round(uploadedModules / totalModules * 100) : 0}% |`); + lines.push(`| 文档更新时间 | ${timestamp} |`); + lines.push(''); + lines.push('---'); + lines.push(''); + lines.push('*由 铸渊(ZhùYuān)· GitHub Copilot Agent 自动生成 · 仓库:guanghulab*'); + lines.push(''); + + // 确保 docs/ 目录存在 + if (!fs.existsSync('docs')) { + fs.mkdirSync('docs', { recursive: true }); + } + + fs.writeFileSync(OUTPUT_FILE, lines.join('\n'), 'utf8'); + console.log('✅ 文档已生成:' + OUTPUT_FILE); + console.log('📊 合作者: ' + COLLABORATOR_MODULES.length + ' | 计划模块: ' + totalModules + ' | 已上传: ' + uploadedModules); +} + +generateDoc(); From 7698adad468ecb1275ad6b6110f3f0e94598311c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:44:19 +0000 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20=E6=A8=A1=E5=9D=97=E6=94=B6?= =?UTF-8?q?=E8=AE=AB=E8=87=AA=E5=8A=A8=E9=80=9A=E7=9F=A5=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=20=E2=80=94=20GitHub=20Issue=20@=E6=8F=90=E5=8F=8A=20+=20?= =?UTF-8?q?=E9=82=AE=E4=BB=B6=E9=80=9A=E7=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com> --- .github/brain/collaborators.json | 62 ++++++ .github/workflows/generate-module-doc.yml | 42 ++++ docs/HoloLake-Era-OS-Modules.md | 20 +- scripts/generate-module-doc.js | 15 +- scripts/notify-module-received.js | 260 ++++++++++++++++++++++ 5 files changed, 387 insertions(+), 12 deletions(-) create mode 100644 .github/brain/collaborators.json create mode 100644 scripts/notify-module-received.js diff --git a/.github/brain/collaborators.json b/.github/brain/collaborators.json new file mode 100644 index 00000000..5baaa1df --- /dev/null +++ b/.github/brain/collaborators.json @@ -0,0 +1,62 @@ +{ + "description": "HoloLake 合作者 GitHub 用户名映射表 · 铸渊通知系统使用", + "note": "请将每位合作者的 github_username 填写为他们的真实 GitHub 用户名(即 @xxx 中的 xxx)", + "collaborators": [ + { + "dev_id": "DEV-001", + "name": "页页", + "github_username": "", + "emoji": "🖥️", + "modules": ["backend-integration"] + }, + { + "dev_id": "DEV-002", + "name": "肥猫", + "github_username": "", + "emoji": "🦁", + "modules": ["m01-login", "m03-personality"] + }, + { + "dev_id": "DEV-003", + "name": "燕樊", + "github_username": "", + "emoji": "🌸", + "modules": ["m07-dialogue-ui", "m10-cloud", "m15-cloud-drive"] + }, + { + "dev_id": "DEV-004", + "name": "之之", + "github_username": "", + "emoji": "🤖", + "modules": ["dingtalk-bot"] + }, + { + "dev_id": "DEV-005", + "name": "小草莓", + "github_username": "", + "emoji": "🍓", + "modules": ["m12-kanban", "status-board"] + }, + { + "dev_id": "DEV-009", + "name": "花尔", + "github_username": "", + "emoji": "🌺", + "modules": ["m05-user-center"] + }, + { + "dev_id": "DEV-010", + "name": "桔子", + "github_username": "", + "emoji": "🍊", + "modules": ["m06-ticket", "m11-module"] + }, + { + "dev_id": "DEV-011", + "name": "匆匆那年", + "github_username": "", + "emoji": "🌙", + "modules": [] + } + ] +} diff --git a/.github/workflows/generate-module-doc.yml b/.github/workflows/generate-module-doc.yml index 96dc1ba2..e8de5d9e 100644 --- a/.github/workflows/generate-module-doc.yml +++ b/.github/workflows/generate-module-doc.yml @@ -51,3 +51,45 @@ jobs: git commit -m "📋 自动更新 HoloLake Era 模块文档 · $(date -u +%Y-%m-%d\ %H:%M\ UTC)" git push fi + + notify-collaborator: + name: 📧 通知合作者模块已收到 + runs-on: ubuntu-latest + # 仅 push 事件触发(workflow_dispatch 为手动,不发通知) + if: github.event_name == 'push' + permissions: + contents: read + issues: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: main + fetch-depth: 2 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: 获取本次 push 改动的文件列表 + id: changed + run: | + # 获取本次 push 相对于上一个 commit 改动的文件 + FILES=$(git diff --name-only HEAD~1 HEAD 2>/dev/null || git show --name-only --format="" HEAD) + echo "files<> $GITHUB_OUTPUT + echo "$FILES" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + echo "📄 改动文件:$FILES" + + - name: 发送模块收讫通知 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_REPO: ${{ github.repository }} + PUSHER_LOGIN: ${{ github.actor }} + CHANGED_FILES: ${{ steps.changed.outputs.files }} + COMMIT_SHA: ${{ github.sha }} + COMMIT_MESSAGE: ${{ github.event.head_commit.message }} + run: node scripts/notify-module-received.js + diff --git a/docs/HoloLake-Era-OS-Modules.md b/docs/HoloLake-Era-OS-Modules.md index 93ccc528..5445eaba 100644 --- a/docs/HoloLake-Era-OS-Modules.md +++ b/docs/HoloLake-Era-OS-Modules.md @@ -1,6 +1,6 @@ # HoloLake Era 操作系统部署模块 -> 📋 **自动生成文档** · 铸渊(ZhùYuān)维护 · 最后更新:2026-03-06 14:36 UTC +> 📋 **自动生成文档** · 铸渊(ZhùYuān)维护 · 最后更新:2026-03-06 14:43 UTC > > 本文档由 GitHub Actions 自动触发生成,每当合作者上传/更新模块时自动刷新。 > 按合作者编号(DEV-XXX)整理所有已上传模块。 @@ -9,14 +9,14 @@ ## 📑 目录 -- [DEV-001 · 🖥️ 页页](#dev001--%E9%A1%B5%E9%A1%B5) (1 个模块) -- [DEV-002 · 🦁 肥猫](#dev002--%E8%82%A5%E7%8C%AB) (2 个模块) -- [DEV-003 · 🌸 燕樊](#dev003--%E7%87%95%E6%A8%8A) (3 个模块) -- [DEV-004 · 🤖 之之](#dev004--%E4%B9%8B%E4%B9%8B) (1 个模块) -- [DEV-005 · 🍓 小草莓](#dev005--%E5%B0%8F%E8%8D%89%E8%8E%93) (2 个模块) -- [DEV-009 · 🌺 花尔](#dev009--%E8%8A%B1%E5%B0%94) (1 个模块) -- [DEV-010 · 🍊 桔子](#dev010--%E6%A1%94%E5%AD%90) (2 个模块) -- [DEV-011 · 🌙 匆匆那年](#dev011--%E5%8C%86%E5%8C%86%E9%82%A3%E5%B9%B4) (待上传) +- [DEV-001 · 🖥️ 页页](#dev-001-页页) (1 个模块) +- [DEV-002 · 🦁 肥猫](#dev-002-肥猫) (2 个模块) +- [DEV-003 · 🌸 燕樊](#dev-003-燕樊) (3 个模块) +- [DEV-004 · 🤖 之之](#dev-004-之之) (1 个模块) +- [DEV-005 · 🍓 小草莓](#dev-005-小草莓) (2 个模块) +- [DEV-009 · 🌺 花尔](#dev-009-花尔) (1 个模块) +- [DEV-010 · 🍊 桔子](#dev-010-桔子) (2 个模块) +- [DEV-011 · 🌙 匆匆那年](#dev-011-匆匆那年) (待上传) --- @@ -326,7 +326,7 @@ m11-module/ | 已上传模块数 | 12 | | 待上传模块数 | 0 | | 上传完成率 | 100% | -| 文档更新时间 | 2026-03-06 14:36 UTC | +| 文档更新时间 | 2026-03-06 14:43 UTC | --- diff --git a/scripts/generate-module-doc.js b/scripts/generate-module-doc.js index e96c5611..c7bf05e3 100644 --- a/scripts/generate-module-doc.js +++ b/scripts/generate-module-doc.js @@ -126,7 +126,16 @@ function readModuleInfo(dir) { return info; } -// ========== 生成结构状态徽章 ========== +// ========== 生成与 GitHub 一致的 Markdown anchor ========== +// GitHub 规则:小写 → 保留字母/数字/空格/连字符/中文 → 空格转连字符 +function toGitHubAnchor(headingText) { + return headingText + .toLowerCase() + .replace(/[^\p{L}\p{N}\s-]/gu, '') // 去除非字母/数字/空格/连字符(支持 Unicode) + .replace(/\s+/g, '-'); // 空格转连字符 +} + + function structureBadge(info) { const checks = [ info.hasSrc ? '✅ src/' : '⚠️ src/', @@ -160,7 +169,9 @@ function generateDoc() { for (const collab of COLLABORATOR_MODULES) { const moduleCount = collab.dirs.filter(d => fs.existsSync(d)).length; const badge = moduleCount > 0 ? `(${moduleCount} 个模块)` : '(待上传)'; - lines.push(`- [${collab.devId} · ${collab.emoji} ${collab.name}](#${collab.devId.toLowerCase().replaceAll('-', '')}--${encodeURIComponent(collab.name)}) ${badge}`); + const headingText = `${collab.devId} · ${collab.emoji} ${collab.name}`; + const anchor = toGitHubAnchor(headingText); + lines.push(`- [${headingText}](#${anchor}) ${badge}`); } lines.push(''); lines.push('---'); diff --git a/scripts/notify-module-received.js b/scripts/notify-module-received.js new file mode 100644 index 00000000..637e1afc --- /dev/null +++ b/scripts/notify-module-received.js @@ -0,0 +1,260 @@ +// scripts/notify-module-received.js +// 铸渊 · 模块收讫通知系统 +// 当合作者上传模块后,自动创建 GitHub Issue @提及 → GitHub 自动发邮件给对方 +// +// 环境变量(由 GitHub Actions 注入): +// GITHUB_TOKEN — 仓库 token(自动注入) +// GITHUB_REPO — 格式: owner/repo(如 qinfendebingshuo/guanghulab) +// PUSHER_LOGIN — github.actor,即推送者的 GitHub 用户名 +// CHANGED_FILES — 本次 push 中改动的文件列表(换行分隔) +// COMMIT_SHA — 本次 commit SHA(前8位) +// COMMIT_MESSAGE — 本次 commit 消息 + +const fs = require('fs'); +const https = require('https'); + +// ========== 读取配置 ========== +const GITHUB_TOKEN = process.env.GITHUB_TOKEN; +const GITHUB_REPO = process.env.GITHUB_REPO || ''; +const PUSHER_LOGIN = (process.env.PUSHER_LOGIN || '').trim(); +const CHANGED_FILES = (process.env.CHANGED_FILES || '').trim(); +const COMMIT_SHA = (process.env.COMMIT_SHA || '').slice(0, 8); +const COMMIT_MSG = (process.env.COMMIT_MESSAGE || '').split('\n')[0].slice(0, 80); + +if (!GITHUB_TOKEN || !GITHUB_REPO) { + console.error('❌ 缺少 GITHUB_TOKEN 或 GITHUB_REPO'); + process.exit(1); +} + +if (!PUSHER_LOGIN) { + console.log('⚠️ 未获取到推送者用户名,跳过通知'); + process.exit(0); +} + +const [OWNER, REPO] = GITHUB_REPO.split('/'); + +// ========== 加载合作者配置 ========== +let collaborators = []; +try { + const config = JSON.parse(fs.readFileSync('.github/brain/collaborators.json', 'utf8')); + collaborators = config.collaborators || []; +} catch (e) { + console.error('❌ 无法读取 collaborators.json:', e.message); + process.exit(1); +} + +// ========== 按推送者 GitHub 用户名查找合作者 ========== +function findCollaborator(githubLogin) { + // 先按 github_username 精确匹配 + const byUsername = collaborators.find(c => + c.github_username && c.github_username.toLowerCase() === githubLogin.toLowerCase() + ); + if (byUsername) return byUsername; + return null; +} + +// ========== 分析改动了哪些模块 ========== +function detectChangedModules(changedFilesStr) { + if (!changedFilesStr) return []; + const files = changedFilesStr.split('\n').map(f => f.trim()).filter(Boolean); + const moduleDirs = new Set(); + + // 已知模块目录前缀列表 + const KNOWN_MODULE_PREFIXES = [ + 'm01-login', 'm03-personality', 'm05-user-center', 'm06-ticket', + 'm07-dialogue-ui', 'm10-cloud', 'm11-module', 'm12-kanban', + 'm15-cloud-drive', 'dingtalk-bot', 'backend-integration', 'status-board', + ]; + + for (const file of files) { + for (const prefix of KNOWN_MODULE_PREFIXES) { + if (file.startsWith(prefix + '/') || file === prefix) { + moduleDirs.add(prefix); + } + } + } + return Array.from(moduleDirs); +} + +// ========== 构建通知 Issue 内容 ========== +function buildIssueContent(collab, changedModules, allFiles) { + const now = new Date().toISOString().replace('T', ' ').slice(0, 16) + ' UTC'; + const mention = collab && collab.github_username ? `@${collab.github_username}` : `@${PUSHER_LOGIN}`; + const devLabel = collab ? `${collab.dev_id} · ${collab.emoji} ${collab.name}` : PUSHER_LOGIN; + + const moduleListStr = changedModules.length > 0 + ? changedModules.map(m => `- \`${m}/\``).join('\n') + : '- (系统自动检测,请核对)'; + + const fileLines = allFiles.split('\n').filter(Boolean); + const fileListStr = fileLines.slice(0, 20).map(f => ` - \`${f}\``).join('\n'); + const extraNote = fileLines.length > 20 ? `\n - ...(共 ${fileLines.length} 个文件)` : ''; + + const title = `📦 铸渊收讫 · [${collab ? collab.dev_id : 'DEV-???'}] ${collab ? collab.name : PUSHER_LOGIN} 模块已收到`; + + const body = `## 铸渊收讫通知 + +${mention} 你好!🎉 + +铸渊(自动化系统)已确认收到你上传的模块。 + +--- + +### 📋 收讫详情 + +| 字段 | 内容 | +|------|------| +| **合作者** | ${devLabel} | +| **GitHub 账号** | @${PUSHER_LOGIN} | +| **收到时间** | ${now} | +| **Commit** | \`${COMMIT_SHA}\` | +| **提交说明** | ${COMMIT_MSG || '(无)'} | + +### 📦 涉及模块 + +${moduleListStr} + +### 📄 上传文件清单 + +${fileListStr}${extraNote} + +--- + +### 📌 下一步 + +1. **铸渊将自动更新** [HoloLake Era 操作系统部署模块](https://github.com/${GITHUB_REPO}/blob/main/docs/HoloLake-Era-OS-Modules.md) 总文档 +2. **模块结构检查** 已自动运行,请确认 CI 状态绿灯 +3. 如需补充 \`SYSLOG.md\`、\`package.json\` 或 \`src/\` 目录,请继续推送 + +> 💡 如有问题,请直接在本 Issue 回复,铸渊会收到通知。 + +--- +*—— 铸渊(ZhùYuān)· 光湖自动化系统 · 自动通知 #${now}*`; + + return { title, body }; +} + +// ========== 调用 GitHub API 创建 Issue ========== +function createIssue(title, body) { + return new Promise((resolve, reject) => { + const payload = JSON.stringify({ title, body, labels: ['模块收讫'] }); + const options = { + hostname: 'api.github.com', + path: `/repos/${OWNER}/${REPO}/issues`, + method: 'POST', + headers: { + 'Authorization': `Bearer ${GITHUB_TOKEN}`, + 'Accept': 'application/vnd.github+json', + 'Content-Type': 'application/json', + 'Content-Length': Buffer.byteLength(payload), + 'User-Agent': 'ZhuyuanBot/1.0', + 'X-GitHub-Api-Version': '2022-11-28', + }, + }; + + const req = https.request(options, res => { + let data = ''; + res.on('data', chunk => { data += chunk; }); + res.on('end', () => { + if (res.statusCode === 201) { + const issue = JSON.parse(data); + resolve(issue); + } else { + reject(new Error(`GitHub API 返回 ${res.statusCode}: ${data}`)); + } + }); + }); + + req.on('error', reject); + req.write(payload); + req.end(); + }); +} + +// ========== 确保标签存在(不存在则自动创建)========== +function ensureLabel() { + return new Promise((resolve) => { + const labelPayload = JSON.stringify({ + name: '模块收讫', + color: '0075ca', + description: '铸渊自动通知:合作者模块收讫确认', + }); + const options = { + hostname: 'api.github.com', + path: `/repos/${OWNER}/${REPO}/labels`, + method: 'POST', + headers: { + 'Authorization': `Bearer ${GITHUB_TOKEN}`, + 'Accept': 'application/vnd.github+json', + 'Content-Type': 'application/json', + 'Content-Length': Buffer.byteLength(labelPayload), + 'User-Agent': 'ZhuyuanBot/1.0', + 'X-GitHub-Api-Version': '2022-11-28', + }, + }; + + const req = https.request(options, res => { + let data = ''; + res.on('data', c => { data += c; }); + res.on('end', () => { + // 201 = created, 422 = already exists,都算OK + resolve(); + }); + }); + req.on('error', () => resolve()); // 标签创建失败不阻断主流程 + req.write(labelPayload); + req.end(); + }); +} + +// ========== 主流程 ========== +async function main() { + console.log(`👤 推送者:${PUSHER_LOGIN}`); + console.log(`📁 改动文件:${CHANGED_FILES ? CHANGED_FILES.split('\n').length : 0} 个`); + + const collab = findCollaborator(PUSHER_LOGIN); + if (collab) { + console.log(`✅ 识别合作者:${collab.dev_id} · ${collab.name}`); + if (!collab.github_username) { + console.log(`⚠️ ${collab.dev_id}(${collab.name})的 github_username 尚未填写`); + console.log(` 请在 .github/brain/collaborators.json 中补充,以便 @提及 生效`); + console.log(` 通知将仍然创建,但不会有 @提及 邮件通知`); + } + } else { + console.log(`ℹ️ 未在 collaborators.json 中找到 "${PUSHER_LOGIN}" 的映射,将使用 GitHub 用户名通知`); + } + + const changedModules = detectChangedModules(CHANGED_FILES); + console.log(`📦 涉及模块:${changedModules.join(', ') || '(未检测到标准模块目录)'}`); + + // 如果改动文件全部在 docs/ 或 scripts/ 或 .github/,说明是系统自动提交,跳过通知 + const allFiles = CHANGED_FILES.split('\n').filter(Boolean); + const isSystemCommit = allFiles.length > 0 && allFiles.every(f => + f.startsWith('docs/') || f.startsWith('scripts/') || f.startsWith('.github/') + ); + if (isSystemCommit) { + console.log('🤖 检测到系统自动提交(非模块上传),跳过通知'); + process.exit(0); + } + + if (changedModules.length === 0) { + console.log('⚠️ 未检测到标准模块目录的改动,跳过通知'); + process.exit(0); + } + + // 确保标签存在 + await ensureLabel(); + + // 构建并发送通知 + const { title, body } = buildIssueContent(collab, changedModules, CHANGED_FILES); + console.log(`📝 创建通知 Issue:${title}`); + + const issue = await createIssue(title, body); + console.log(`✅ Issue 已创建:#${issue.number} → ${issue.html_url}`); + console.log(`📧 GitHub 将自动发送邮件通知给 @${collab?.github_username || PUSHER_LOGIN}`); +} + +main().catch(err => { + console.error('❌ 通知失败:', err.message); + process.exit(1); +});