# 局域网机器管理后台 — 需求文档

## 一、项目概述

搭建一个本地局域网机器管理后台，用于集中管理多台虚拟机/主机（20 台以内），直观展示机器信息、服务部署情况及机器之间的转发/依赖关系，解决"机器多、IP 多、服务分散、容易遗忘"的痛点。

系统分为**访客模式**和**管理员模式**：
- **访客**：无需登录，可查看机器的在线状态、已同步的系统数据（CPU/内存/磁盘等）、服务列表，但无法查看 IP 地址、MAC 地址、拓扑关系，也无法执行任何管理操作。
- **管理员**：登录后可查看完整信息（含 IP、MAC、拓扑关系），执行增删改、SSH 信息获取、导入导出等所有操作。

---

## 二、核心功能模块

### 1. 用户认证

- **管理员账号**：预设一组用户名/密码，通过环境变量或配置文件初始化
- **认证方式**：Session/Cookie 或简单 Token
- **未登录用户**：自动降级为访客模式，仅开放只读脱敏接口

### 2. 机器管理（增删改查）

| 字段 | 说明 | 是否必填 | 访客可见 |
|------|------|---------|---------|
| 主机名/别名 | 用户自定义的易记名称，如 `web-server-01` | 是 | ✅ 是 |
| IP 地址 | 机器在局域网中的固定 IP，如 `192.168.1.100` | 是 | ❌ 否（仅管理员） |
| MAC 地址 | 可选，用于辅助识别 | 否 | ❌ 否（仅管理员） |
| 操作系统 | Linux / Windows / macOS（可下拉选择 + 自定义） | 是 | ✅ 是 |
| 系统版本 | 如 `Ubuntu 22.04`、`Windows 11`、`macOS 14` | 否 | ✅ 是 |
| 备注/描述 | 自由文本，记录用途、负责人等信息 | 否 | ❌ 否（仅管理员） |
| 状态 | 在线 / 离线（自动检测） | 自动 | ✅ 是 |
| SSH 系统信息 | CPU / 内存 / 磁盘 / 运行时间等（手动触发获取，可同步到机器记录） | 按需 | ✅ 是（已同步的数据） |
| 创建时间 / 更新时间 | 系统自动记录 | 自动 | ❌ 否（仅管理员） |

### 3. 服务管理

- 每台机器可以关联**多个服务条目**
- 服务字段：
  - **服务名称**（如 `nginx`、`frps`、`docker`、`mysql`、`redis` 等）
  - **端口号**（如 `80`、`443`、`8080`）
  - **协议**（TCP / UDP / HTTP / HTTPS）
  - **备注**（自由描述，如 "反向代理到 192.168.1.50:8080"）
- 服务类型支持**预设常用服务** + **自定义服务**
- **访客可见性**：访客可以看到服务名称、端口、协议，但**不可查看备注**（备注可能包含敏感 IP 或内部信息）

### 4. 机器关系管理

- 机器之间可以建立**连接关系**，用于表达端口转发、代理、依赖等
- 关系字段：
  - **源机器** → **目标机器**
  - **关系类型**（预设 + 自定义）：
    - `端口转发`（如 Nginx 反代、FRP 穿透）
    - `依赖`（如 A 机器上的应用依赖 B 机器的数据库）
    - `主从`（如主从复制、集群节点）
    - `自定义`
  - **端口信息**：源端口 → 目标端口（如 `8080 → 80`）
  - **备注**：自由描述
- 关系应支持**双向可视化**（A→B 建立关系后，两边都能看到）
- **访客可见性**：❌ **完全不可见**，拓扑图和关系列表仅对管理员开放

### 5. 在线状态检测

- 定时对每台机器执行 **ICMP Ping** 检测
- 检测间隔：**1 分钟**
- 界面用颜色/图标直观展示在线状态：🟢 在线 / 🔴 离线
- **访客可见性**：✅ **可见**

### 6. SSH 系统信息获取（安全敏感）

- **不保存任何 SSH 凭据**（用户名、密码、密钥均不持久化）
- 仅支持 **密码认证**，不支持密钥认证
- **仅管理员可见和操作**：在机器详情页提供单独的按钮 **"获取系统信息"**
- 点击后弹窗要求输入 SSH **用户名**和**密码**
- 连接成功后获取以下信息并展示：
  - 主机名、操作系统版本（精确）
  - CPU 使用率 / 核心数
  内存使用率 / 总量
  - 磁盘使用率 / 各分区
  - 运行时间（uptime）
  - 监听中的端口列表
- **单次有效**：凭据仅在本次请求中使用，用完即销毁，不写入任何存储
- 获取到的信息可选择性地**同步到机器记录中**（如系统版本、CPU、内存、磁盘），同步后访客即可查看这些已缓存的数据
- SSH 连接超时时间：10 秒

### 7. 拓扑/关系图可视化

- 以**节点-连线图**的形式展示所有机器及其关系
- 节点颜色区分操作系统类型
- 连线标注关系类型和端口号
- 支持拖拽、缩放、点击节点查看详情
- 使用 G6 或类似的图可视化库
- **访客可见性**：❌ **完全不可见**，仅管理员可访问拓扑图页面

### 8. 数据导入/导出

- 支持 **JSON 格式**完整导出（机器 + 服务 + 关系）
- 支持 **JSON 格式**导入（覆盖或追加模式）
- 导出文件名带时间戳，如 `lan-manager-backup-20260414.json`
- **管理员专属功能**，访客无权限

### 9. 操作日志

- 记录所有增删改操作：
  - 操作时间
  - 操作类型（创建 / 修改 / 删除）
  - 操作对象（机器 / 服务 / 关系）
  - 变更内容（旧值 → 新值）
  - 来源 IP（请求的 IP）
  - 操作用户（管理员用户名）
- 日志只增不改，可在独立页面查看
- 支持按时间/操作类型筛选
- **管理员专属功能**

---

## 三、UI 界面设计

### 页面 1：机器列表（主页，访客/管理员共用）

```
┌─────────────────────────────────────────────────────────────────┐
│  🔍 搜索 IP / 主机名          [Linux▼]                           │
├─────────────────────────────────────────────────────────────────┤
│  ┌─────┐ ┌─────────────┐ ┌───────────┐ ┌──────────┐ ┌────────┐ │
│  │状态 │ │ 主机名      │ │ IP*       │ │ 系统     │ │ 服务数 │ │
│ ├─────┤ ├─────────────┤ ├───────────┤ ├──────────┤ ├────────┤ │
│  │ 🟢  │ │ nginx-proxy │ 192.168.*.* │ Linux     │ 2       │ │
│  │ 🟢  │ │ db-master   │ 192.168.*.* │ Linux     │ 1       │ │
│  │ 🔴  │ │ dev-win     │ 192.168.*.* │ Windows   │ 3       │ │
│  │ 🟢  │ │ mac-build   │ 192.168.*.* │ macOS     │ 0       │ │
│  └─────┘ └─────────────┘ └───────────┘ └──────────┘ └────────┘ │
│                                                                 │
│  底部导航: [机器列表] [拓扑图*] [操作日志*] [导入/导出*] [登录]    │
└─────────────────────────────────────────────────────────────────┘
```

> 注：带 `*` 的功能/数据仅管理员可见，访客访问时隐藏或显示为占位符（如 IP 显示为 `***`）。

- 支持按系统类型筛选、按 IP / 主机名搜索（访客搜索时只能匹配主机名，IP 对访客不可见）
- 点击某行进入**机器详情**

### 页面 2：机器详情（访客/管理员共用，但字段可见性不同）

```
┌──────────────────────────────────────────────────────────────┐
│  ← 返回           nginx-proxy                                 │
├──────────────────────────────────────────────────────────────┤
│  基本信息                                      [编辑*]        │
│    IP:    192.168.1.1              (访客显示: ***.***.*.*)    │
│    MAC:   AA:BB:CC:DD:EE:FF        (访客不可见)               │
│    系统:  Linux (Ubuntu 22.04)                                │
│    状态:  🟢 在线                                               │
│    备注:  主网关入口               (访客不可见)               │
│                                                               │
│  SSH 系统信息（管理员触发后展示）                               │
│    CPU: 12% (4 cores)                                         │
│    内存: 2.1G / 8G (26%)                                      │
│    磁盘: / 45G / 100G (45%), /data 120G / 500G (24%)         │
│    运行时间: 15 days, 3:22                                    │
│    监听端口: 22, 80, 443                                      │
│    [获取系统信息*]  [同步到记录*]                               │
│                                                               │
│  服务列表                                      [+ 添加服务*]   │
│    ┌─────────┬──────┬──────┬──────────────────────┐          │
│    │ 名称    │ 端口 │ 协议 │ 备注*                │          │
│    ├─────────┼──────┼──────┼──────────────────────┤          │
│    │ nginx   │ 80   │ TCP  │ 反代入口             │          │
│    │ nginx   │ 443  │ TCP  │ HTTPS                │          │
│    └─────────┴──────┴──────┴──────────────────────┘          │
│                                                               │
│  关联关系                                      [+ 添加关系*]   │
│    → db-master :80 → :3306  [端口转发]  [编辑*] [删除*]       │
│    → frps :8080 → :8080     [依赖]       [编辑*] [删除*]       │
└──────────────────────────────────────────────────────────────┘
```

> 注：带 `*` 的按钮/字段仅对管理员显示；关联关系区域对访客完全隐藏。

### 页面 3：拓扑图

- 力导向图（force-directed graph），节点可拖拽
- 节点颜色：Linux 蓝色、Windows 绿色、macOS 紫色
- 连线样式：
  - 端口转发：实线 + 端口标注
  - 依赖：虚线 + 文字标注
  - 主从：带箭头实线
- 点击节点高亮关联连线，其余淡化
- **仅管理员可访问**，访客访问时重定向到机器列表或提示登录

### 页面 4：操作日志

```
┌──────────────────────────────────────────────────────────────────┐
│  [全部▼] [2026-04-14]                    [导出日志*]              │
├──────────────────────────────────────────────────────────────────┤
│  2026-04-14 15:30:22  admin  修改   机器   nginx-proxy           │
│                        备注: "" → "主网关入口"                    │
│  2026-04-14 15:28:01  admin  创建   服务   nginx on nginx-proxy  │
│  2026-04-14 14:55:10  admin  删除   关系   db-master → cache-01 │
│  2026-04-14 14:30:00  admin  创建   机器   cache-01              │
└──────────────────────────────────────────────────────────────────┘
```

- **仅管理员可访问**

---

## 四、技术选型

| 层 | 技术 | 说明 |
|---|---|---|
| 后端 | **Go 1.21+** | 单二进制部署，内置 net/http 或 Gin 框架，SSH 客户端用 golang.org/x/crypto/ssh |
| 前端 | **Vue 3 + Vite** | 轻量，配合 Element Plus / Naive UI 组件库 |
| 拓扑图 | **AntV G6** | 专门的图可视化库，力导向图 + 自定义节点样式 |
| 存储 | **SQLite** | 单文件数据库，适合 20 台以内数据量 |
| 在线检测 | Go `net` 包 ICMP Ping / 系统 ping 命令回退 | 定时 goroutine，1 分钟间隔 |
| SSH | `golang.org/x/crypto/ssh` | 纯 Go 实现，不依赖系统 ssh 命令，仅密码认证 |
| 认证 | Session/Cookie | 简单用户名密码，预设单管理员账号 |

### 项目结构

```
lan-manager/
├── server/
│   ├── main.go              # 入口，HTTP 服务启动
│   ├── config/              # 配置管理
│   ├── db/                  # SQLite 数据库连接 + migration
│   ├── models/              # 数据模型 (Machine, Service, Relationship, Log, User)
│   ├── handlers/            # HTTP 请求处理
│   ├── services/            # 业务逻辑 (ping, ssh, import/export, auth)
│   └── middleware/          # CORS, 认证中间件, 日志中间件
├── web/
│   ├── src/
│   │   ├── views/           # 页面组件 (MachineList, MachineDetail, Topology, Logs, Login)
│   │   ├── components/      # 复用组件 (StatusBadge, ServiceTable, RelationEditor)
│   │   ├── api/             # 前端 API 封装
│   │   └── App.vue
│   └── index.html
├── scripts/
│   └── lan-manager.service  # Systemd 服务示例
├── go.mod
├── go.sum
├── Makefile                 # 构建脚本
└── README.md
```

---

## 五、数据存储设计

```sql
machines 表:
  id            INTEGER PRIMARY KEY AUTOINCREMENT
  hostname      TEXT NOT NULL              -- 主机名/别名
  ip            TEXT NOT NULL UNIQUE       -- IP 地址
  mac           TEXT                       -- MAC 地址
  os_type       TEXT NOT NULL              -- Linux / Windows / macOS / Other
  os_version    TEXT                       -- 系统版本
  notes         TEXT                       -- 备注
  is_online     INTEGER DEFAULT 0          -- 0=离线, 1=在线
  last_ping_at  DATETIME                   -- 最后一次 ping 时间
  -- SSH 系统信息字段（管理员获取后可选择同步到这里，供访客查看）
  cpu_info      TEXT                       -- CPU 信息 JSON
  memory_info   TEXT                       -- 内存信息 JSON
  disk_info     TEXT                       -- 磁盘信息 JSON
  uptime        TEXT                       -- 运行时间
  listen_ports  TEXT                       -- 监听端口列表，逗号分隔
  ssh_synced_at DATETIME                   -- 最后一次同步 SSH 数据的时间
  created_at    DATETIME DEFAULT CURRENT_TIMESTAMP
  updated_at    DATETIME DEFAULT CURRENT_TIMESTAMP

services 表:
  id            INTEGER PRIMARY KEY AUTOINCREMENT
  machine_id    INTEGER NOT NULL REFERENCES machines(id) ON DELETE CASCADE
  name          TEXT NOT NULL              -- 服务名称
  port          INTEGER NOT NULL           -- 端口号
  protocol      TEXT DEFAULT 'TCP'         -- TCP / UDP / HTTP / HTTPS
  notes         TEXT                       -- 备注

relationships 表:
  id                    INTEGER PRIMARY KEY AUTOINCREMENT
  source_machine_id     INTEGER NOT NULL REFERENCES machines(id) ON DELETE CASCADE
  target_machine_id     INTEGER NOT NULL REFERENCES machines(id) ON DELETE CASCADE
  relation_type         TEXT NOT NULL        -- port_forward / dependency / primary_secondary / custom
  source_port           INTEGER              -- 源端口
  target_port           INTEGER              -- 目标端口
  notes                 TEXT                 -- 备注

operation_logs 表:
  id            INTEGER PRIMARY KEY AUTOINCREMENT
  action        TEXT NOT NULL              -- create / update / delete
  entity_type   TEXT NOT NULL              -- machine / service / relationship
  entity_id     INTEGER                    -- 操作对象的 ID
  entity_name   TEXT                       -- 操作对象的名称描述
  old_value     TEXT                       -- 旧值 (JSON)
  new_value     TEXT                       -- 新值 (JSON)
  source_ip     TEXT                       -- 请求来源 IP
  username      TEXT                       -- 操作用户名（admin 或匿名）
  created_at    DATETIME DEFAULT CURRENT_TIMESTAMP
```

---

## 六、API 设计

### 认证

| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/api/auth/login` | 管理员登录（用户名/密码） |
| POST | `/api/auth/logout` | 退出登录 |
| GET | `/api/auth/me` | 获取当前登录状态 |

### 机器

| 方法 | 路径 | 说明 | 权限 |
|------|------|------|------|
| GET | `/api/machines` | 获取机器列表（支持 ?os_type=Linux 筛选） | 访客/管理员 |
| GET | `/api/machines/:id` | 获取单个机器详情（含服务，管理员额外含关系、IP、MAC、备注） | 访客/管理员 |
| POST | `/api/machines` | 创建机器 | 管理员 |
| PUT | `/api/machines/:id` | 更新机器 | 管理员 |
| DELETE | `/api/machines/:id` | 删除机器 | 管理员 |
| POST | `/api/machines/:id/ssh-info` | SSH 获取系统信息（需传用户名密码，单次有效） | 管理员 |
| POST | `/api/machines/:id/sync-ssh` | 将最近一次 SSH 获取的信息同步到机器记录 | 管理员 |

### 服务

| 方法 | 路径 | 说明 | 权限 |
|------|------|------|------|
| GET | `/api/machines/:machine_id/services` | 获取某机器的服务列表 | 访客/管理员 |
| POST | `/api/machines/:machine_id/services` | 添加服务 | 管理员 |
| PUT | `/api/services/:id` | 更新服务 | 管理员 |
| DELETE | `/api/services/:id` | 删除服务 | 管理员 |

### 关系

| 方法 | 路径 | 说明 | 权限 |
|------|------|------|------|
| GET | `/api/relationships` | 获取全部关系 | 管理员 |
| POST | `/api/relationships` | 创建关系 | 管理员 |
| PUT | `/api/relationships/:id` | 更新关系 | 管理员 |
| DELETE | `/api/relationships/:id` | 删除关系 | 管理员 |

### 日志 / 导入导出

| 方法 | 路径 | 说明 | 权限 |
|------|------|------|------|
| GET | `/api/logs` | 获取操作日志 | 管理员 |
| GET | `/api/export` | 导出数据（JSON 下载） | 管理员 |
| POST | `/api/import` | 导入数据（上传 JSON） | 管理员 |

### 其他

| 方法 | 路径 | 说明 | 权限 |
|------|------|------|------|
| GET | `/api/health` | 服务健康检查 | 公开 |

---

## 七、已确认的设计决策

| 项目 | 决定 |
|------|------|
| 部署方式 | Web 应用，源码部署，Linux Systemd 服务 |
| Ping 间隔 | 1 分钟 |
| SSH 系统信息 | 支持，**不保存凭据**，仅密码认证，手动输入用户名密码，单次有效，独立按钮触发，仅管理员可用 |
| SSH 密钥 | **不支持** |
| 自动发现机器 | 不需要，纯手动添加 |
| 用户认证 | **需要**，预设单管理员账号，访客免认证只读访问脱敏数据 |
| 拓扑图 | 保留，力导向图，**仅管理员可见** |
| 导入/导出 | 需要，JSON 格式，管理员专属 |
| 操作日志 | 需要，记录所有增删改 |
| 机器规模 | 20 台以内 |
| 前端技术 | Vue 3 + 组件库 + AntV G6 |
| 后端技术 | Go + SQLite |
| 数据自动备份 | **不需要** |
| 前端构建方式 | 支持 embed 打包 + 外置静态目录两种模式 |

---

## 八、待确认细节

1. **前端 UI 组件库**：Element Plus 还是 Naive UI？（或者你有其他偏好）
2. **前端构建方式**：把 Vue 打包后的静态文件嵌入 Go 二进制（`embed.FS`，单文件部署），还是前后端分别部署？（建议同时支持两种）
3. **操作日志保留策略**：永久保留还是定期清理（如只保留最近 90 天）？
