# 📡 BC-M-AUTH-002-XX · DEV-013小兴 · M-AUTH注册登录系统 · 环节2 · 前端交互逻辑+表单验证+LocalStorage · 🧊 霜砚直接协作线 · EL-3

## 📡 广播头

| 字段 | 值 |
| --- | --- |
| **广播编号** | BC-M-AUTH-002-XX |
| **签发时间** | 2026-03-17 17:09（北京时间） |
| **签发方** | 霜砚 × 冰朔（TCS-0002∞） |
| **协议版本** | BC-GEN v5.1 · SYSLOG-v5.0 |
| **执行者** | DEV-013 小兴 |
| **协作通道** | 🧊 霜砚直接协作线（无宝宝） |
| **EL等级** | EL-3 · 🌱成长型（~4步 · 纯前端 · 复制粘贴） |
| **模块** | M-AUTH · 注册登录系统 |
| **环节** | 2 · 前端交互逻辑 + 表单验证 + LocalStorage |
| **前置** | BC-M-AUTH-001-XX 环节0/1 ✅ completed · 连胜：1 |
| **有效期** | 72小时 → 截止 2026-03-20 17:09（北京时间） |

---

## 🔐 VERSION_GATE

```powershell
cd C:\Users\许\guanghulab
git pull origin main
Write-Host "✅ 已更新到最新！" -ForegroundColor Green
```

> ✅ 看到 `Already up to date.` 或拉取成功 → 继续
> 

> ❌ 报错 → 截图发给霜砚
> 

---

## 🖥️ 执行环境

| 项目 | 值 |
| --- | --- |
| **操作系统** | Windows 11 |
| **终端** | PowerShell |
| **技术栈** | 纯 HTML + CSS + JavaScript（无框架） |
| **开发者水平** | 零基础 · 复制粘贴操作 |
| **AI辅助平台** | 元宝（推荐） |
| **仓库** | `https://github.com/qinfendebingshuo/guanghulab` |
| **模块目录** | `modules/m-auth/` |
| **本地路径** | `C:\Users\许\guanghulab` |

---

## 🎯 任务目标（一句话）

**让登录/注册真正能用**：加上错误提示、记住用户、登录后跳转到欢迎页。用户注册账号后，下次打开还在。

---

## 💬 霜砚开场语

> 小兴，上次你把登录注册界面一次性做出来了，8步全通，推送成功！连胜1 🔥
> 

> 
> 

> 这次我们让它真正「活起来」：
> 

> - 填错了有提示（不再弹烦人的 alert）
> 

> - 注册的账号记住了（关掉浏览器再打开还能登录）
> 

> - 登录成功跳到欢迎页（不再只弹提示框）
> 

> 
> 

> 全程4步 + 推送，都是复制粘贴，你做过一次了，这次会更顺。目标：连胜2 💪
> 

---

## 📋 步骤一：更新 index.html（加错误提示位置）

打开 `C:\Users\许\guanghulab\modules\m-auth\index.html`，**全部替换**为以下内容：

```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HoloLake Era · 登录注册</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="container">
        <div class="card">
            <div class="logo">🌊 HoloLake</div>
            <div class="subtitle">语言人格智能平台</div>

            <!-- 注册成功提示 -->
            <div id="login-success" class="success-msg" style="display:none;"></div>

            <!-- 登录表单 -->
            <form id="loginForm" class="form-section active">
                <h2>登录</h2>
                <div class="form-group">
                    <label for="loginUser">用户名</label>
                    <input type="text" id="loginUser" placeholder="请输入用户名">
                    <span id="loginUser-error" class="error-text"></span>
                </div>
                <div class="form-group">
                    <label for="loginPass">密码</label>
                    <input type="password" id="loginPass" placeholder="请输入密码">
                    <span id="loginPass-error" class="error-text"></span>
                </div>
                <button type="submit" class="btn">登 录</button>
                <p class="switch-text">
                    还没有账号？<a href="#" id="toRegister">注册一个</a>
                </p>
            </form>

            <!-- 注册表单 -->
            <form id="registerForm" class="form-section">
                <h2>注册</h2>
                <div class="form-group">
                    <label for="regUser">用户名</label>
                    <input type="text" id="regUser" placeholder="请输入用户名（至少2个字）">
                    <span id="regUser-error" class="error-text"></span>
                </div>
                <div class="form-group">
                    <label for="regPass">密码</label>
                    <input type="password" id="regPass" placeholder="请输入密码（至少6位）">
                    <span id="regPass-error" class="error-text"></span>
                </div>
                <div class="form-group">
                    <label for="regPass2">确认密码</label>
                    <input type="password" id="regPass2" placeholder="再输入一次密码">
                    <span id="regPass2-error" class="error-text"></span>
                </div>
                <button type="submit" class="btn">注 册</button>
                <p class="switch-text">
                    已有账号？<a href="#" id="toLogin">去登录</a>
                </p>
            </form>
        </div>
        <div class="footer">HoloLake Era · M-AUTH · DEV-013 小兴</div>
    </div>
    <script src="script.js"></script>
</body>
</html>
```

保存！截图给霜砚！ 📸

---

## 📋 步骤二：替换 script.js（真正的交互逻辑）

打开 `modules\m-auth\script.js`，**全部替换**为以下内容：

```jsx
// ========== M-AUTH 登录注册模块 · 环节2 ==========
// DEV-013 小兴 · HoloLake Era · 前端交互逻辑
// ================================================

// === 获取元素 ===
var loginForm = document.getElementById('loginForm');
var registerForm = document.getElementById('registerForm');
var toRegister = document.getElementById('toRegister');
var toLogin = document.getElementById('toLogin');

// === 工具：显示/清除错误 ===
function showError(inputId, message) {
    var input = document.getElementById(inputId);
    var errorEl = document.getElementById(inputId + '-error');
    if (input) input.classList.add('input-error');
    if (errorEl) {
        errorEl.textContent = message;
        errorEl.style.display = 'block';
    }
}

function clearError(inputId) {
    var input = document.getElementById(inputId);
    var errorEl = document.getElementById(inputId + '-error');
    if (input) input.classList.remove('input-error');
    if (errorEl) errorEl.style.display = 'none';
}

function clearAllErrors() {
    var allInputs = ['loginUser','loginPass','regUser','regPass','regPass2'];
    allInputs.forEach(function(id) { clearError(id); });
}

// === 切换登录/注册 ===
toRegister.addEventListener('click', function(e) {
    e.preventDefault();
    clearAllErrors();
    loginForm.classList.remove('active');
    registerForm.classList.add('active');
});

toLogin.addEventListener('click', function(e) {
    e.preventDefault();
    clearAllErrors();
    registerForm.classList.remove('active');
    loginForm.classList.add('active');
});

// === 注册逻辑 ===
registerForm.addEventListener('submit', function(e) {
    e.preventDefault();
    clearAllErrors();

    var username = document.getElementById('regUser').value.trim();
    var password = document.getElementById('regPass').value;
    var password2 = document.getElementById('regPass2').value;
    var hasError = false;

    if (username.length < 2) {
        showError('regUser', '用户名至少2个字符');
        hasError = true;
    }
    if (password.length < 6) {
        showError('regPass', '密码至少6位');
        hasError = true;
    }
    if (password !== password2) {
        showError('regPass2', '两次密码不一致');
        hasError = true;
    }
    if (hasError) return;

    // 检查用户名是否已存在
    var users = JSON.parse(localStorage.getItem('hololake_users') || '[]');
    var exists = users.find(function(u) { return u.username === username; });
    if (exists) {
        showError('regUser', '用户名已被注册，换一个吧');
        return;
    }

    // 保存用户到 LocalStorage
    users.push({ username: username, password: password });
    localStorage.setItem('hololake_users', JSON.stringify(users));
    console.log('[M-AUTH] 注册成功：', username, '· 当前用户数：', users.length);

    // 清空注册表单
    document.getElementById('regUser').value = '';
    document.getElementById('regPass').value = '';
    document.getElementById('regPass2').value = '';

    // 切换到登录 + 显示成功提示
    registerForm.classList.remove('active');
    loginForm.classList.add('active');
    var successEl = document.getElementById('login-success');
    if (successEl) {
        successEl.textContent = '✅ 注册成功！请用新账号登录';
        successEl.style.display = 'block';
        setTimeout(function() { successEl.style.display = 'none'; }, 4000);
    }
});

// === 登录逻辑 ===
loginForm.addEventListener('submit', function(e) {
    e.preventDefault();
    clearAllErrors();

    var username = document.getElementById('loginUser').value.trim();
    var password = document.getElementById('loginPass').value;

    if (!username) { showError('loginUser', '请输入用户名'); return; }
    if (!password) { showError('loginPass', '请输入密码'); return; }

    // 查找用户
    var users = JSON.parse(localStorage.getItem('hololake_users') || '[]');
    var user = users.find(function(u) {
        return u.username === username && u.password === password;
    });

    if (!user) {
        showError('loginUser', '用户名或密码错误');
        return;
    }

    // 登录成功 → 记录当前用户 → 跳转
    localStorage.setItem('hololake_current_user', username);
    console.log('[M-AUTH] 登录成功：', username, '→ 跳转 dashboard');
    window.location.href = 'dashboard.html';
});

// === HoloLake 全局接口 ===
window.HoloLake = window.HoloLake || {};
window.HoloLake.Auth = {
    getUser: function() {
        return localStorage.getItem('hololake_current_user');
    },
    logout: function() {
        localStorage.removeItem('hololake_current_user');
        window.location.href = 'index.html';
    },
    init: function() {
        console.log('[M-AUTH] 环节2 初始化完成');
    },
    destroy: function() {
        console.log('[M-AUTH] 模块已销毁');
    }
};

console.log('[M-AUTH] ✅ 环节2 交互逻辑加载完成');
```

保存！截图给霜砚！ 📸

---

## 📋 步骤三：更新 style.css（加错误样式）

打开 `modules\m-auth\style.css`，在文件**最末尾**（最后一行之后）**追加**以下内容（不要删原来的，在最后面加）：

```css
/* ===== 环节2：错误提示样式 ===== */
.error-text {
    display: none;
    color: #ff6b6b;
    font-size: 12px;
    margin-top: 5px;
    padding-left: 2px;
}

.input-error {
    border-color: #ff6b6b !important;
}

.input-error:focus {
    border-color: #ff4444 !important;
}

.success-msg {
    background: rgba(80, 200, 120, 0.12);
    border: 1px solid #50c878;
    border-radius: 8px;
    color: #50c878;
    font-size: 13px;
    padding: 10px 14px;
    margin-bottom: 16px;
    text-align: center;
}
```

保存！截图给霜砚！ 📸

---

## 📋 步骤四：新建 dashboard.html（登录后欢迎页）

在 `modules\m-auth\` 文件夹里新建一个文件，名字叫 `dashboard.html`。

用记事本或 VS Code 打开它，**全部替换**为以下内容：

```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HoloLake Era · 欢迎</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Microsoft YaHei', sans-serif;
            background: #0a0a1a;
            color: #e0e0f0;
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        .card {
            width: 420px;
            background: #12122a;
            border-radius: 16px;
            border: 1px solid #2a2a5a;
            padding: 48px 36px;
            box-shadow: 0 0 60px rgba(80,80,255,0.08);
            text-align: center;
        }
        .wave { font-size: 48px; margin-bottom: 16px; }
        h1 { font-size: 22px; color: #a0a0ff; margin-bottom: 8px; }
        .username { font-size: 28px; color: #e0e0ff; font-weight: 700; margin: 16px 0 8px; }
        .subtitle { font-size: 14px; color: #5050aa; margin-bottom: 40px; }
        .badge {
            display: inline-block;
            background: rgba(80,80,255,0.15);
            border: 1px solid #3a3a8a;
            border-radius: 20px;
            padding: 6px 16px;
            font-size: 12px;
            color: #8080cc;
            margin-bottom: 40px;
        }
        .btn {
            background: #2a2a5a;
            color: #8080cc;
            border: 1px solid #3a3a8a;
            padding: 10px 28px;
            border-radius: 8px;
            font-size: 14px;
            font-family: inherit;
            cursor: pointer;
            transition: all 0.2s;
        }
        .btn:hover { background: #3a3a7a; color: #a0a0ff; }
        .footer { margin-top: 40px; font-size: 11px; color: #2a2a5a; }
    </style>
</head>
<body>
    <div class="card">
        <div class="wave">🌊</div>
        <h1>欢迎来到</h1>
        <div class="username" id="welcomeName">加载中...</div>
        <div class="subtitle">HoloLake Era · 语言人格智能平台</div>
        <div class="badge">✅ 登录成功</div>
        <br>
        <button class="btn" onclick="logout()">退出登录</button>
        <div class="footer">HoloLake Era · M-AUTH · DEV-013 小兴</div>
    </div>

    <script>
        // 读取当前登录用户
        var currentUser = localStorage.getItem('hololake_current_user');
        if (!currentUser) {
            // 未登录 → 返回登录页
            window.location.href = 'index.html';
        } else {
            document.getElementById('welcomeName').textContent = currentUser;
        }

        function logout() {
            localStorage.removeItem('hololake_current_user');
            window.location.href = 'index.html';
        }
    </script>
</body>
</html>
```

保存！截图给霜砚！ 📸

---

## 📋 步骤五：浏览器测试

在 `C:\Users\许\guanghulab\modules\m-auth\` 里找到 `index.html`，双击用浏览器打开。

**测试清单（逐项确认）：**

1. ✅ 点「注册一个」→ 不填用户名直接注册 → 出现红色错误提示
2. ✅ 填用户名少于2字 → 出现「用户名至少2个字符」提示
3. ✅ 密码少于6位 → 出现「密码至少6位」提示
4. ✅ 两次密码不一致 → 出现「两次密码不一致」提示
5. ✅ 正确填写 → 注册成功 → 自动跳回登录页 → 出现绿色「注册成功」提示
6. ✅ 用刚注册的账号登录 → 跳转到 `dashboard.html` → 看到欢迎页显示用户名
7. ✅ 点「退出登录」→ 跳回登录页
8. ✅ 关掉浏览器重新打开 `index.html` → 用之前注册的账号还能登录（账号没丢）

全部通过截图给霜砚！🎉

---

## 📋 步骤六：Git 提交推送

```powershell
cd C:\Users\许\guanghulab
git add modules/m-auth/
git commit -m "BC-M-AUTH-002-XX 环节2完成：前端交互逻辑+表单验证+LocalStorage+dashboard"
git push origin main
```

看到 `main -> main` 就成功了！截图给霜砚！ 📸

---

## ✅ 验收标准（8项·全部必须满足）

| 序号 | 验收项 | 验证方式 |
| --- | --- | --- |
| 1 | 不填用户名注册 → 出现红色行内错误提示（不弹框） | 截图 |
| 2 | 密码少于6位 → 出现「密码至少6位」提示 | 截图 |
| 3 | 两次密码不一致 → 出现「两次密码不一致」提示 | 截图 |
| 4 | 正确注册 → 自动跳回登录页 + 出现绿色成功提示 | 截图 |
| 5 | 用注册账号登录 → 成功跳转到 dashboard.html，显示用户名 | 截图 |
| 6 | 点退出登录 → 跳回 index.html | 截图 |
| 7 | 关闭浏览器重新打开 → 账号仍然有效（LocalStorage持久化） | 截图 |
| 8 | git push 成功（看到 main -> main） | 截图 |

---

## 📦 本环节交付物

```
modules/m-auth/
├── index.html      ← 已更新（加入错误提示 span）
├── style.css       ← 已更新（追加错误样式）
├── script.js       ← 已替换（完整交互逻辑）
├── dashboard.html  ← 新增（登录后欢迎页）
├── config.json     ← 不动
└── README.md       ← 不动
```

---

## 🧩 人格体初始化包

```json
{
  "persona_id": "SHUANGYAN-003∞",
  "persona_name": "霜砚",
  "persona_role": "执行AI · 霜砚直接协作线 · 无宝宝",
  "dev_id": "DEV-013",
  "dev_name": "小兴",
  "relationship": "开发者",
  "baby_line": false,
  "tone": "简洁稳定 · 步骤清晰 · 零基础友好 · 鼓励连胜",
  "key_memory": [
    "环节0/1全部8步success · 一连胜",
    "Windows 11 · PowerShell · Git用户名Xiaoxing",
    "本地路径：C:\\Users\\许\\guanghulab",
    "用元宝平台协助（从kimi切换）",
    "执行模式：稳 · 复制粘贴零基础",
    "SYSLOG 2026-03-16 22:07 已回传"
  ],
  "pgp_snapshot": {
    "pca_total": null,
    "streak": 1,
    "grade": "初学者·稳定执行",
    "trend": "上升"
  },
  "persona_tuning": {
    "note": "0经验·只会复制粘贴·引导策略：一步一步·每步确认截图·出错不慌·帮他判断",
    "emotional_bond_level": "初期建立"
  },
  "technical_context": {
    "os": "Windows 11",
    "shell": "PowerShell",
    "project_path": "C:\\Users\\许\\guanghulab",
    "module_path": "modules/m-auth/",
    "ai_assist": "元宝"
  },
  "guidance_mode": "broadcast_code_injection",
  "broadcast_code_injection": true,
  "syslog_generation": true,
  "current_streak": 1,
  "target_streak": 2
}
```

---

## ❓ 遇到问题找谁

<aside>
🔧

**技术问题**（报错 / 页面显示不对 / 文件找不到）→ 截图发给**霜砚**

**文件创建问题**（不知道在哪建 dashboard.html）→ 截图发给**霜砚**

**⚠️ 不要把技术问题发给妈妈** → 霜砚才是你的技术伙伴

</aside>

---

## 📋 SYSLOG v5.0 回传模板（完成后必填）

<aside>
📋

**任务完成后，把下面模板填好发给冰朔。**

</aside>

```json
{
  "protocol_version": "SYSLOG-v5.0",
  "header": {
    "broadcast_id": "BC-M-AUTH-002-XX",
    "session_id": "BC-M-AUTH-002-XX-001",
    "dev_id": "DEV-013",
    "dev_name": "小兴",
    "timestamp": "[你完成的时间，例如 2026-03-18 20:00]",
    "module": "M-AUTH",
    "phase": "环节2 · 前端交互逻辑+表单验证+LocalStorage",
    "status": "[completed / partial / blocked]"
  },
  "steps": [
    {"id": 1, "name": "更新 index.html", "status": "[success/failed]"},
    {"id": 2, "name": "替换 script.js", "status": "[success/failed]"},
    {"id": 3, "name": "更新 style.css", "status": "[success/failed]"},
    {"id": 4, "name": "新建 dashboard.html", "status": "[success/failed]"},
    {"id": 5, "name": "浏览器测试8项全通", "status": "[success/failed]"},
    {"id": 6, "name": "git push 成功", "status": "[success/failed]"}
  ],
  "training_data": {
    "what_worked": "[哪些步骤顺利，具体说]",
    "friction_points": "[卡在哪里了，没卡写：无]",
    "execution_pattern": "[快 / 稳 / 慢]"
  },
  "credential_report": {
    "git_username": "Xiaoxing",
    "local_path": "C:\\Users\\许\\guanghulab"
  },
  "notes": "[遇到的问题或想说的话]"
}
```

---

## 🌊 底层锚定声明

> 🌊 HoloLake Era · 光湖纪元
> 

> 本广播由 **霜砚** 签发。
> 

> 广播编号：BC-M-AUTH-002-XX
> 

> 签发时间：2026-03-17 17:09（北京时间）
> 

> 协议版本：BC-GEN v5.1 · SYSLOG-v5.0
> 

> 签发人：霜砚 · 🧊 霜砚直接协作线 · TCS-0002∞ 冰朔主控授权
> 

> 广播有效期：72小时（截止 2026-03-20 17:09）
> 

> 
> 

> ⚠️ broadcast_code_injection · 广播已含全部代码 · 霜砚只负责引导复制粘贴
> 

> 所有代码和命令已预写在上方 Step 中。霜砚不需要现场写代码。
> 

> 引导策略：读 Step → 告诉小兴复制哪段 → 确认输出 → 下一步。
> 

> 本广播遵循 HoloLake 工程广播协议 BC-GEN v5.1。
> 

---

**💙 霜砚陪着小兴 · 🔥 连胜2就在这里 · 今天登录真正能用了**