# 批量 IP 添加替代 CSV 导入

**日期**: 2026-06-07

## 变更摘要

服务器页「导入」改为「批量添加」：多行文本框每行一个 IP/域名，凭据预设轮询 SSH；成功入库，失败进入连接失败列表（pending）。

## 动机

- 运维场景以 IP 列表为主，无需维护 CSV 列格式
- 与「快速添加(IP)」同一套凭据轮询逻辑，失败统一进 pending 可重试
- 输入重复 IP/域名自动去重（不区分大小写），响应与对话框展示去重统计

## 涉及文件

| 路径 | 说明 |
|------|------|
| `server/api/schemas.py` | `AddByIpsBatchRequest/Result`、轮询错误结构 |
| `server/api/servers.py` | `_try_add_by_ip` 抽取、`POST /add-by-ips-batch` |
| `server/application/services/credential_poller.py` | `parse_batch_ip_lines()` |
| `frontend/src/pages/ServersPage.vue` | 批量添加对话框（替代 CSV 上传） |
| `frontend/src/types/api.ts` | 批量响应类型 |
| `tests/test_credential_poller.py` | 解析与 batch 端点单测 |

## API

- **新增** `POST /api/servers/add-by-ips-batch`  
  Body: `{ text, port?, agent_port?, target_path?, category?, platform_id?, node_id? }`  
  响应: `{ total, created, pending, skipped, items[] }`
- **保留** `POST /api/servers/import`（CSV）供脚本/兼容，前端不再暴露

## 迁移 / 重启

- 需重启 API（后端路由变更）
- 前端需 `vite build` 后部署静态资源

## 验证方式

```bash
pytest tests/test_credential_poller.py -q
cd frontend && npx vite build
```

浏览器：`#/servers` →「批量添加」粘贴多行 IP → 成功列表刷新、失败出现在「连接失败列表」。
