# EasyAI Windows 一键部署方案

## 1. 背景与目标

`start.sh` 是 Linux 下的一键部署脚本，本方案为 Windows 平台提供等效的 `start.ps1` PowerShell 脚本。针对 Windows 典型场景做如下**精简**：

- **仅 IP 访问**：不含域名模式与 HTTPS
- **本地访问无需放行端口**：选择本地 (127.0.0.1) 时，不涉及防火墙配置
- **Docker 未安装时**：用户可选择手动或自动安装 **Docker Desktop for Windows**（winget/Chocolatey）

## 2. Linux start.sh 流程梳理

### 2.1 整体流程

| 步骤 | 功能 | 说明 |
|------|------|------|
| 1 | 项目初始化 | 校验当前目录下存在 `docker-compose.yml` |
| 2 | 部署配置问答 | IP 或域名二选一，并采集对应参数 |
| 3 | 配置文件生成 | 生成/更新 `.env`、`.env.tools`、`.env.ASG` |
| 4 | Docker 安装与检查 | 检测并安装 Docker（Ubuntu/CentOS） |
| 5 | 启动服务 | `docker compose pull && docker compose up -d` |
| 6 | HTTPS 配置（可选） | 域名模式下执行 `https.sh` |

### 2.2 配置问答逻辑

- **IP 模式**：输入服务器 IP 地址，需要放行 3001、3002、3003 端口
- **域名模式**：输入域名，可选是否启用 HTTPS，需放行 80、443 端口

### 2.3 环境变量写入 .env

- `NUXT_PUBLIC_BASE_APIURL`：API 地址
- `NUXT_PUBLIC_BASE_SOCKETURL`：WebSocket 地址
- `NUXT_PUBLIC_SG_APIURL`：Agent 服务治理 API 地址

**IP 模式**：
```
NUXT_PUBLIC_BASE_APIURL=http://<IP>:3001
NUXT_PUBLIC_BASE_SOCKETURL=ws://<IP>:3002
NUXT_PUBLIC_SG_APIURL=http://<IP>:3003
```

**域名模式**：
```
NUXT_PUBLIC_BASE_APIURL=/api
NUXT_PUBLIC_BASE_SOCKETURL=wss://<domain>/socket.io
NUXT_PUBLIC_SG_APIURL=/asg-api
```

---

## 3. Windows 与 Linux 差异

| 项目 | Linux | Windows |
|------|-------|---------|
| 脚本语言 | Bash | PowerShell |
| 文本替换 | sed | `(Get-Content) -replace` 或 `Set-Content` |
| 用户输入 | `read -p` | `Read-Host` |
| 访问方式 | IP + 域名 + HTTPS | **仅 IP**（本地 / 局域网） |
| 端口放行 | 本地无特殊说明 | **本地访问无需放行**，局域网需放行 3001/3002/3003 |
| Docker | apt/yum 安装 Linux Docker | **Docker Desktop for Windows**，未安装时可选择手动或自动安装 |

---

## 4. Windows IP 访问方式设计（核心差异）

Windows 版**仅支持 IP 访问**，不包含域名模式与 HTTPS 配置。用户访问方式分为两类：

| 选项 | 访问方式 | IP 值 | 端口说明 |
|------|----------|-------|----------|
| 1 | 本地访问 | `127.0.0.1` | 本机访问，**无需放行端口** |
| 2 | 局域网访问 | 用户输入本机局域网 IP | 同网段设备访问，需放行 3001、3002、3003 |

**交互流程：**

1. `[1] 本地访问` → 自动使用 `127.0.0.1`，无需配置防火墙
2. `[2] 局域网访问` → 提示用户输入局域网 IP（可提示 `ipconfig` 查看），并提醒放行上述端口

---

## 5. 实现方案

### 5.1 脚本文件

- 文件路径：`easyai/start.ps1`
- 一行命令示例：
  ```powershell
  git clone https://git.51easyai.com/wangbo/easyai; cd easyai; .\start.ps1
  ```

### 5.2 模块划分

| 模块 | 函数/区块 | 功能 |
|------|-----------|------|
| 项目初始化 | `Init-ProjectDir` | 检查 `docker-compose.yml`，切换到项目根目录 |
| 配置问答 | `Run-DeployQuestions` | 本地访问 / 局域网访问选择（含 IP 输入） |
| 环境变量 | `PromptOrEnv` | 支持环境变量覆盖，用于 CI/自动化 |
| 配置文件 | `Setup-EnvFiles` | 复制 sample 并修改 `.env`、`.env.tools`、`.env.ASG` |
| Docker 检查 | `Test-Docker` | 检测 `docker`，未安装则让用户选择**手动安装**或**自动安装** |
| 启动服务 | `Start-Services` | `docker compose pull` 与 `docker compose up -d` |
| 主流程 | `Main` | 串联上述步骤 |

### 5.3 环境变量支持（非交互模式）

| 变量 | 说明 |
|------|------|
| `DEPLOY_IP` | 访问 IP（本地填 `127.0.0.1`，局域网填实际 IP） |
| `DEPLOY_DRY_RUN` | 1 时只生成配置，不安装/启动 Docker |
| `DEPLOY_FORCE_RECONFIG` | 非空时强制重新配置 |

### 5.4 配置文件修改实现（仅 IP 模式）

使用 PowerShell 替换 `.env` 中相关行：

```powershell
$content = Get-Content .env -Raw -Encoding UTF8
$content = $content -replace 'NUXT_PUBLIC_BASE_APIURL=.*', "NUXT_PUBLIC_BASE_APIURL=http://${DEPLOY_IP}:3001"
$content = $content -replace 'NUXT_PUBLIC_BASE_SOCKETURL=.*', "NUXT_PUBLIC_BASE_SOCKETURL=ws://${DEPLOY_IP}:3002"
$content = $content -replace 'NUXT_PUBLIC_SG_APIURL=.*', "NUXT_PUBLIC_SG_APIURL=http://${DEPLOY_IP}:3003"
Set-Content .env -Value $content -Encoding UTF8 -NoNewline
```

### 5.5 Docker 处理策略

- **目标**：检测并安装 **Docker Desktop for Windows**（Windows 版 Docker）
- **检测**：执行 `docker --version` 或 `docker compose version`
- **未安装时**： prompt 让用户选择
  - `[1] 手动安装`：输出安装说明及 Docker Desktop for Windows 下载链接，退出脚本
  - `[2] 自动安装`：通过 winget 或 Chocolatey 安装 Docker Desktop for Windows，安装后需用户重启终端/机器再继续

### 5.6 执行策略

PowerShell 默认可能禁止执行脚本，建议在文档中说明：

```powershell
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
```

或在脚本开头提示用户使用：

```powershell
powershell -ExecutionPolicy Bypass -File .\start.ps1
```

---

## 6. 部署完成输出

成功部署后输出访问地址，例如：

- 本地访问：`http://127.0.0.1:3010`
- 局域网访问：`http://<LAN_IP>:3010`

---

## 7. 实现清单

- [ ] 创建 `start.ps1` 主脚本
- [ ] 实现 `Init-ProjectDir`：项目目录校验
- [ ] 实现 `Run-DeployQuestions`：本地 / 局域网 IP 选择（无域名/HTTPS）
- [ ] 实现 `Setup-EnvFiles`：配置文件生成与替换
- [ ] 实现 `Test-Docker`：Docker 检测，未安装时 prompt「手动安装」或「自动安装」
- [ ] 实现 `Install-Docker`：自动安装 **Docker Desktop for Windows**（winget / Chocolatey）
- [ ] 实现 `Start-Services`：`docker compose` 启动
- [ ] 实现 `Main`：主流程串联
- [ ] 支持 `DEPLOY_DRY_RUN`、`DEPLOY_IP` 环境变量非交互模式
- [x] 在 README 或文档中补充 Windows 部署说明与执行策略
- [x] 创建 `scripts/test-start-ps1-env.py` 验证 .env 替换逻辑

---

## 8. Windows 测试说明

### 本地测试（需 Windows 或 WSL + PowerShell）

```powershell
# 非交互 + 仅生成配置（不启动 Docker）
$env:DEPLOY_DRY_RUN = "1"
$env:DEPLOY_IP = "127.0.0.1"
.\start.ps1

# 检查 .env 是否已正确写入
Select-String -Path .env -Pattern "NUXT_PUBLIC_BASE"
```

### 完整部署测试（需 Windows + Docker Desktop）

```powershell
.\start.ps1
# 按提示选择 [1] 本地访问 或 [2] 局域网访问
# 若未安装 Docker，选择 [1] 手动 或 [2] 自动安装
```

### 执行策略（若提示无法运行脚本）

```powershell
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
# 或
powershell -ExecutionPolicy Bypass -File .\start.ps1
```
