# 接口清单 · 登录鉴权 · 乐观锁 · 状态码

平台默认地址：`http://devops.test.yljr.com`（`BASE`）。所有写操作只走 HTTP 接口，禁止经 MCP。

> ⛔ **`commitDeliver`（提交）严禁调用**，无论用户是否要求或授权。提交只能由用户本人在页面上手动点击。下表刻意不列该接口。

## 登录鉴权（加盐 MD5）

密码不是明文，前端一套自定义加盐 MD5（已还原并验证）：

```
盐 = "CHIANABEIJINGXINSANYOURUANJIANZHONGLIANXINXINGFILSOFT20081127XSY"
① 明文中数字替换：0→~ 1→$ 2→! 3→@ 4→: 5→] 6→[ 7→{ 8→} 9→`
② 盐取前 (盐长 - 变换后密码长) 个字符
③ MD5( 截断盐 + 变换后密码 ) 转大写
```

登录接口（成功后响应头下发 `Authorization` 等 Cookie，后续请求携带）：

```
POST /zqyl-devops-base-api/user/login
Content-Type: application/json
{"username":"<操作者账号>","password":"<上面算法算出的密文>"}
```

未带/失效 Cookie 时接口返回 `M0401 登录过期请重新登录`。

**账号密码来源**：必须由用户在本次会话里提供（或环境变量 `DEVOPS_USER` / `DEVOPS_PWD`）。密码只在内存里参与加盐 MD5，**不写文件、不回显、不落日志**。登录失败原样报错让用户重给，不许换账号试。

## 录制权限校验 checkEditDeliver

定位到 `deliverId` 之后、读配置/组装报文/保存**之前**必须调用，确认当前账号有权限录制这张交付单：

```
GET /zqyl-devops-deliver-api/deliver/checkEditDeliver?deliverId={deliverId}
例：http://devops.test.yljr.com/zqyl-devops-deliver-api/deliver/checkEditDeliver?deliverId=3832950772694255120
```

| 返回 | 含义 | 动作 |
|---|---|---|
| `status == "M0200"` | 有权限、可编辑 | 继续后续步骤 |
| 其它任何 status | 无录制权限 / 别人正在编辑 / 单据已锁定 | **停**，把 `msg` 原样告诉用户，请其确认权限或联系单据创建人 |

⛔ 不许跳过、不许换账号重试、不许用 MCP 点页面绕开。校验不过就终止。

## 乐观锁 optimistic

`saveDeliver` 报文里的 `optimistic` 必须等于服务端当前值；保存成功返回新值。
若返回 `M0600`（并发冲突），用返回的 `data.optimistic` 覆盖后重试（等价页面「强制保存」）。
**稳妥做法：保存前先 `getDeliverDetail` 取最新 `optimistic`。**

## 状态码

`M0200` 成功 ｜ `M0401` 登录过期 ｜ `M0600` 乐观锁冲突。

## 接口清单

| 用途 | 方法 & 路径 |
|---|---|
| 登录 | `POST /zqyl-devops-base-api/user/login` |
| 上线窗口 | `GET /zqyl-devops-base-api/onlinetime/getOnlineTime` |
| 时间戳→测试环境 | `GET /zqyl-devops-base-api/onlinetime/queryOnlineTimelist?time={时间戳}`（取 `environmentType`） |
| 定位交付单 | `GET /zqyl-devops-deliver-api/deliver/queryDeliverList?serverName=&onlineTime=&createName=` |
| 查服务全部历史单 | 同上，**`onlineTime` 留空**（用于抄该服务历史配置，见 [../tabs/sql.md](../tabs/sql.md)） |
| **录制权限校验**（定位到单后必做） | `GET /zqyl-devops-deliver-api/deliver/checkEditDeliver?deliverId=` |
| 交付详情 | `GET /zqyl-devops-deliver-api/deliver/getDeliverDetail?deliverId=` |
| **保存**（写操作的终点） | `POST /zqyl-devops-deliver-api/deliver/saveDeliver` |
| 配置类型字典 | `GET /zqyl-devops-deliver-api/deliver/getConfigTypeAndNameList` |
| SQL 库类型 | `GET /zqyl-devops-base-api/base/data/getDictionary?type=FEEDBACK_TYPE` |
| SQL 地址/库级联 | `GET /zqyl-devops-base-api/base/data/getDictionaryById?id=` |
| MQ 集群 | `GET /zqyl-devops-deliver-api/deliver/MQInfo` |
| **防火墙 服务/端口字典** | `GET /zqyl-devops-compose-api/environment/server/queryServerName?serverName=&useType=firewall`（必须带 `useType=firewall`；返回 `id`/`serverEnName`/`serverType`/`aotuSelection`/`portList[]`，见 [../tabs/firewall.md](../tabs/firewall.md)） |
| 服务端口（备用） | `GET /zqyl-devops-compose-api/environment/server/queryServerPort` |
| 定时任务执行器 | `GET /zqyl-devops-deliver-api/deliver/queryJobHandlerList` |
| nacos 文本解析 | `POST /zqyl-devops-continuous-api/script/nacos/parse` |
| 文件上传（网关/错误码/附件） | `POST /zqyl-devops-file-api/file/uploadFile`（multipart：`file` + `bizType`） |

## 关键映射

- `onlineTime` 过滤参数 = **毫秒时间戳**（当天 0 点，东八区）。
- `queryDeliverList` 返回行 `id` = `deliverId`；`lockVersion` = 详情里的 `optimistic`。
- 同一「服务名 + 时间戳」多条 → 让用户补「创建人」再唯一定位。
