添加DNS接口
This commit is contained in:
parent
a936352962
commit
f4abc5cd88
|
|
@ -0,0 +1,873 @@
|
|||
# DNS 管理 API 文档
|
||||
|
||||
## 概述
|
||||
|
||||
本文档描述了 DNS 管理系统的 API 接口,包括 DNS 服务器、DNS 区域和 DNS 记录的增删改查操作。
|
||||
|
||||
## 基础信息
|
||||
|
||||
- 基础路径: `/dns`
|
||||
- 请求方法: POST
|
||||
- 认证: 需要在请求头中携带认证 token
|
||||
|
||||
## 常量定义
|
||||
|
||||
### DNS 服务器状态
|
||||
|
||||
| 值 | 说明 |
|
||||
|----|------|
|
||||
| 0 | 已停止 |
|
||||
| 1 | 运行中 |
|
||||
| 2 | 错误 |
|
||||
|
||||
### DNS 记录类型
|
||||
|
||||
| 值 | 类型 | 说明 |
|
||||
|----|------|------|
|
||||
| 1 | A | IPv4 地址记录 |
|
||||
| 28 | AAAA | IPv6 地址记录 |
|
||||
| 5 | CNAME | 别名记录 |
|
||||
| 15 | MX | 邮件交换记录 |
|
||||
| 2 | NS | 名称服务器记录 |
|
||||
| 6 | SOA | 起始授权记录 |
|
||||
| 16 | TXT | 文本记录 |
|
||||
| 33 | SRV | 服务位置记录 |
|
||||
|
||||
## DNS 服务器接口
|
||||
|
||||
### 1. 创建 DNS 服务器
|
||||
|
||||
**接口路径**: `/dns/server/create`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| name | string | 是 | DNS 服务器名称 |
|
||||
| port | uint | 否 | 监听端口,默认 53 |
|
||||
| listen_ip | string | 否 | 监听 IP,默认 0.0.0.0 |
|
||||
| upstream_dns | string | 否 | 上游 DNS 服务器,多个用逗号分隔 |
|
||||
| enable_recursion | bool | 否 | 是否启用递归查询 |
|
||||
| description | string | 否 | 描述 |
|
||||
|
||||
**请求示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "我的 DNS 服务器",
|
||||
"port": 53,
|
||||
"listen_ip": "0.0.0.0",
|
||||
"upstream_dns": "8.8.8.8,8.8.4.4",
|
||||
"enable_recursion": true,
|
||||
"description": "个人 DNS 服务器"
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "创建DNS服务器成功",
|
||||
"data": {
|
||||
"ID": 1,
|
||||
"CreatedAt": "2024-01-01T00:00:00Z",
|
||||
"UpdatedAt": "2024-01-01T00:00:00Z",
|
||||
"DeletedAt": null,
|
||||
"user_id": 1,
|
||||
"name": "我的 DNS 服务器",
|
||||
"port": 53,
|
||||
"listen_ip": "0.0.0.0",
|
||||
"upstream_dns": "8.8.8.8,8.8.4.4",
|
||||
"enable_recursion": true,
|
||||
"status": 0,
|
||||
"description": "个人 DNS 服务器"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 获取 DNS 服务器
|
||||
|
||||
**接口路径**: `/dns/server/get`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| server_id | uint | 否 | DNS 服务器 ID,0 表示获取全部 |
|
||||
| get_type | int | 否 | 获取类型:0 获取自己的,1 获取全部(管理员) |
|
||||
|
||||
**请求示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"server_id": 1,
|
||||
"get_type": 0
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "获取DNS服务器成功",
|
||||
"data": [
|
||||
{
|
||||
"ID": 1,
|
||||
"CreatedAt": "2024-01-01T00:00:00Z",
|
||||
"UpdatedAt": "2024-01-01T00:00:00Z",
|
||||
"DeletedAt": null,
|
||||
"user_id": 1,
|
||||
"name": "我的 DNS 服务器",
|
||||
"port": 53,
|
||||
"listen_ip": "0.0.0.0",
|
||||
"upstream_dns": "8.8.8.8,8.8.4.4",
|
||||
"enable_recursion": true,
|
||||
"status": 0,
|
||||
"description": "个人 DNS 服务器"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 更新 DNS 服务器
|
||||
|
||||
**接口路径**: `/dns/server/update`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| server_id | uint | 是 | DNS 服务器 ID |
|
||||
| name | string | 否 | DNS 服务器名称 |
|
||||
| port | uint | 否 | 监听端口 |
|
||||
| listen_ip | string | 否 | 监听 IP |
|
||||
| upstream_dns | string | 否 | 上游 DNS 服务器 |
|
||||
| enable_recursion | bool | 否 | 是否启用递归查询 |
|
||||
| status | uint | 否 | 状态:0 停止,1 运行中,2 错误 |
|
||||
| description | string | 否 | 描述 |
|
||||
|
||||
**请求示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"server_id": 1,
|
||||
"name": "更新后的 DNS 服务器",
|
||||
"status": 1
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "更新DNS服务器成功",
|
||||
"data": {
|
||||
"ID": 1,
|
||||
"CreatedAt": "2024-01-01T00:00:00Z",
|
||||
"UpdatedAt": "2024-01-01T01:00:00Z",
|
||||
"DeletedAt": null,
|
||||
"user_id": 1,
|
||||
"name": "更新后的 DNS 服务器",
|
||||
"port": 53,
|
||||
"listen_ip": "0.0.0.0",
|
||||
"upstream_dns": "8.8.8.8,8.8.4.4",
|
||||
"enable_recursion": true,
|
||||
"status": 1,
|
||||
"description": "个人 DNS 服务器"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 删除 DNS 服务器
|
||||
|
||||
**接口路径**: `/dns/server/delete`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| server_id | uint | 否 | DNS 服务器 ID |
|
||||
| del_type | uint | 是 | 删除类型:0 删除单条,1 删除所有 |
|
||||
|
||||
**请求示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"server_id": 1,
|
||||
"del_type": 0
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "删除DNS服务器成功"
|
||||
}
|
||||
```
|
||||
|
||||
## DNS 区域接口
|
||||
|
||||
### 5. 创建 DNS 区域
|
||||
|
||||
**接口路径**: `/dns/zone/create`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| server_id | uint | 是 | 所属 DNS 服务器 ID |
|
||||
| domain | string | 是 | 域名,如 example.com |
|
||||
| soa_mname | string | 否 | SOA 记录的主域名服务器 |
|
||||
| soa_rname | string | 否 | SOA 记录的管理员邮箱 |
|
||||
| soa_serial | uint | 否 | SOA 记录的序列号,默认 1 |
|
||||
| soa_refresh | uint | 否 | SOA 记录的刷新时间(秒),默认 86400 |
|
||||
| soa_retry | uint | 否 | SOA 记录的重试时间(秒),默认 7200 |
|
||||
| soa_expire | uint | 否 | SOA 记录的过期时间(秒),默认 3600000 |
|
||||
| soa_minimum | uint | 否 | SOA 记录的最小 TTL(秒),默认 3600 |
|
||||
| ttl | uint | 否 | 默认 TTL(秒),默认 3600 |
|
||||
| description | string | 否 | 描述 |
|
||||
|
||||
**请求示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"server_id": 1,
|
||||
"domain": "example.com",
|
||||
"soa_mname": "ns1.example.com",
|
||||
"soa_rname": "admin.example.com",
|
||||
"description": "示例域名"
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "创建DNS区域成功",
|
||||
"data": {
|
||||
"ID": 1,
|
||||
"CreatedAt": "2024-01-01T00:00:00Z",
|
||||
"UpdatedAt": "2024-01-01T00:00:00Z",
|
||||
"DeletedAt": null,
|
||||
"server_id": 1,
|
||||
"domain": "example.com",
|
||||
"soa_mname": "ns1.example.com",
|
||||
"soa_rname": "admin.example.com",
|
||||
"soa_serial": 1,
|
||||
"soa_refresh": 86400,
|
||||
"soa_retry": 7200,
|
||||
"soa_expire": 3600000,
|
||||
"soa_minimum": 3600,
|
||||
"ttl": 3600,
|
||||
"description": "示例域名"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6. 获取 DNS 区域
|
||||
|
||||
**接口路径**: `/dns/zone/get`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| zone_id | uint | 否 | Zone ID,0 表示获取全部 |
|
||||
| server_id | uint | 否 | DNS 服务器 ID,用于过滤 |
|
||||
| get_type | int | 否 | 获取类型:0 获取自己的,1 获取全部(管理员) |
|
||||
|
||||
**请求示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"zone_id": 1,
|
||||
"get_type": 0
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "获取DNS区域成功",
|
||||
"data": [
|
||||
{
|
||||
"ID": 1,
|
||||
"CreatedAt": "2024-01-01T00:00:00Z",
|
||||
"UpdatedAt": "2024-01-01T00:00:00Z",
|
||||
"DeletedAt": null,
|
||||
"server_id": 1,
|
||||
"domain": "example.com",
|
||||
"soa_mname": "ns1.example.com",
|
||||
"soa_rname": "admin.example.com",
|
||||
"soa_serial": 1,
|
||||
"soa_refresh": 86400,
|
||||
"soa_retry": 7200,
|
||||
"soa_expire": 3600000,
|
||||
"soa_minimum": 3600,
|
||||
"ttl": 3600,
|
||||
"description": "示例域名"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 7. 更新 DNS 区域
|
||||
|
||||
**接口路径**: `/dns/zone/update`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| zone_id | uint | 是 | Zone ID |
|
||||
| domain | string | 否 | 域名 |
|
||||
| soa_mname | string | 否 | SOA 记录的主域名服务器 |
|
||||
| soa_rname | string | 否 | SOA 记录的管理员邮箱 |
|
||||
| soa_serial | uint | 否 | SOA 记录的序列号 |
|
||||
| soa_refresh | uint | 否 | SOA 记录的刷新时间(秒) |
|
||||
| soa_retry | uint | 否 | SOA 记录的重试时间(秒) |
|
||||
| soa_expire | uint | 否 | SOA 记录的过期时间(秒) |
|
||||
| soa_minimum | uint | 否 | SOA 记录的最小 TTL(秒) |
|
||||
| ttl | uint | 否 | 默认 TTL(秒) |
|
||||
| description | string | 否 | 描述 |
|
||||
|
||||
**请求示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"zone_id": 1,
|
||||
"description": "更新后的描述"
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "更新DNS区域成功",
|
||||
"data": {
|
||||
"ID": 1,
|
||||
"CreatedAt": "2024-01-01T00:00:00Z",
|
||||
"UpdatedAt": "2024-01-01T01:00:00Z",
|
||||
"DeletedAt": null,
|
||||
"server_id": 1,
|
||||
"domain": "example.com",
|
||||
"soa_mname": "ns1.example.com",
|
||||
"soa_rname": "admin.example.com",
|
||||
"soa_serial": 1,
|
||||
"soa_refresh": 86400,
|
||||
"soa_retry": 7200,
|
||||
"soa_expire": 3600000,
|
||||
"soa_minimum": 3600,
|
||||
"ttl": 3600,
|
||||
"description": "更新后的描述"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8. 删除 DNS 区域
|
||||
|
||||
**接口路径**: `/dns/zone/delete`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| zone_id | uint | 否 | Zone ID |
|
||||
| del_type | uint | 是 | 删除类型:0 删除单条,1 删除所有 |
|
||||
|
||||
**请求示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"zone_id": 1,
|
||||
"del_type": 0
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "删除DNS区域成功"
|
||||
}
|
||||
```
|
||||
|
||||
## DNS 记录接口
|
||||
|
||||
### 9. 创建 DNS 记录
|
||||
|
||||
**接口路径**: `/dns/record/create`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| zone_id | uint | 是 | 所属 Zone ID |
|
||||
| name | string | 是 | 记录名称,如 www 或 @ |
|
||||
| type | uint | 是 | 记录类型:1=A, 28=AAAA, 5=CNAME, 15=MX 等 |
|
||||
| value | string | 否 | 记录值 |
|
||||
| ttl | uint | 否 | TTL(秒),如果为 0 则使用 Zone 的默认 TTL |
|
||||
| priority | uint | 否 | 优先级(用于 MX、SRV 等记录) |
|
||||
| weight | uint | 否 | 权重(用于 SRV 记录) |
|
||||
| port | uint | 否 | 端口(用于 SRV 记录) |
|
||||
| target | string | 否 | 目标(用于 SRV 记录) |
|
||||
|
||||
**请求示例 - A 记录**:
|
||||
|
||||
```json
|
||||
{
|
||||
"zone_id": 1,
|
||||
"name": "www",
|
||||
"type": 1,
|
||||
"value": "192.168.1.1",
|
||||
"ttl": 3600
|
||||
}
|
||||
```
|
||||
|
||||
**请求示例 - CNAME 记录**:
|
||||
|
||||
```json
|
||||
{
|
||||
"zone_id": 1,
|
||||
"name": "mail",
|
||||
"type": 5,
|
||||
"value": "mailserver.example.com",
|
||||
"ttl": 3600
|
||||
}
|
||||
```
|
||||
|
||||
**请求示例 - MX 记录**:
|
||||
|
||||
```json
|
||||
{
|
||||
"zone_id": 1,
|
||||
"name": "@",
|
||||
"type": 15,
|
||||
"value": "mx1.example.com",
|
||||
"ttl": 3600,
|
||||
"priority": 10
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "创建DNS记录成功",
|
||||
"data": {
|
||||
"ID": 1,
|
||||
"CreatedAt": "2024-01-01T00:00:00Z",
|
||||
"UpdatedAt": "2024-01-01T00:00:00Z",
|
||||
"DeletedAt": null,
|
||||
"zone_id": 1,
|
||||
"name": "www",
|
||||
"type": 1,
|
||||
"value": "192.168.1.1",
|
||||
"ttl": 3600,
|
||||
"priority": 0,
|
||||
"weight": 0,
|
||||
"port": 0,
|
||||
"target": ""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 10. 获取 DNS 记录
|
||||
|
||||
**接口路径**: `/dns/record/get`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| record_id | uint | 否 | 记录 ID,0 表示获取全部 |
|
||||
| zone_id | uint | 否 | Zone ID,用于过滤 |
|
||||
| get_type | int | 否 | 获取类型:0 获取自己的,1 获取全部(管理员) |
|
||||
|
||||
**请求示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"record_id": 1,
|
||||
"get_type": 0
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "获取DNS记录成功",
|
||||
"data": [
|
||||
{
|
||||
"ID": 1,
|
||||
"CreatedAt": "2024-01-01T00:00:00Z",
|
||||
"UpdatedAt": "2024-01-01T00:00:00Z",
|
||||
"DeletedAt": null,
|
||||
"zone_id": 1,
|
||||
"name": "www",
|
||||
"type": 1,
|
||||
"value": "192.168.1.1",
|
||||
"ttl": 3600,
|
||||
"priority": 0,
|
||||
"weight": 0,
|
||||
"port": 0,
|
||||
"target": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 11. 更新 DNS 记录
|
||||
|
||||
**接口路径**: `/dns/record/update`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| record_id | uint | 是 | 记录 ID |
|
||||
| name | string | 否 | 记录名称 |
|
||||
| type | uint | 否 | 记录类型 |
|
||||
| value | string | 否 | 记录值 |
|
||||
| ttl | uint | 否 | TTL(秒) |
|
||||
| priority | uint | 否 | 优先级 |
|
||||
| weight | uint | 否 | 权重 |
|
||||
| port | uint | 否 | 端口 |
|
||||
| target | string | 否 | 目标 |
|
||||
|
||||
**请求示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"record_id": 1,
|
||||
"value": "192.168.1.2"
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "更新DNS记录成功",
|
||||
"data": {
|
||||
"ID": 1,
|
||||
"CreatedAt": "2024-01-01T00:00:00Z",
|
||||
"UpdatedAt": "2024-01-01T01:00:00Z",
|
||||
"DeletedAt": null,
|
||||
"zone_id": 1,
|
||||
"name": "www",
|
||||
"type": 1,
|
||||
"value": "192.168.1.2",
|
||||
"ttl": 3600,
|
||||
"priority": 0,
|
||||
"weight": 0,
|
||||
"port": 0,
|
||||
"target": ""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 12. 删除 DNS 记录
|
||||
|
||||
**接口路径**: `/dns/record/delete`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| record_id | uint | 否 | 记录 ID |
|
||||
| del_type | uint | 是 | 删除类型:0 删除单条,1 删除所有 |
|
||||
|
||||
**请求示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"record_id": 1,
|
||||
"del_type": 0
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "删除DNS记录成功"
|
||||
}
|
||||
```
|
||||
|
||||
## DNS 服务运行管理接口
|
||||
|
||||
### 13. 启动 DNS 服务器
|
||||
|
||||
**接口路径**: `/dns/server/start`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| server_id | uint | 是 | DNS 服务器 ID |
|
||||
|
||||
**请求示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"server_id": 1
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "启动DNS服务器成功",
|
||||
"data": {
|
||||
"server_id": 1,
|
||||
"config": {
|
||||
"ID": 1,
|
||||
"CreatedAt": "2024-01-01T00:00:00Z",
|
||||
"UpdatedAt": "2024-01-01T00:00:00Z",
|
||||
"DeletedAt": null,
|
||||
"user_id": 1,
|
||||
"name": "我的 DNS 服务器",
|
||||
"port": 53,
|
||||
"listen_ip": "0.0.0.0",
|
||||
"upstream_dns": "8.8.8.8,8.8.4.4",
|
||||
"enable_recursion": true,
|
||||
"status": 1,
|
||||
"description": "个人 DNS 服务器"
|
||||
},
|
||||
"running": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 14. 停止 DNS 服务器
|
||||
|
||||
**接口路径**: `/dns/server/stop`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| server_id | uint | 是 | DNS 服务器 ID |
|
||||
|
||||
**请求示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"server_id": 1
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "停止DNS服务器成功"
|
||||
}
|
||||
```
|
||||
|
||||
### 15. 重启 DNS 服务器
|
||||
|
||||
**接口路径**: `/dns/server/restart`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| server_id | uint | 是 | DNS 服务器 ID |
|
||||
|
||||
**请求示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"server_id": 1
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "重启DNS服务器成功",
|
||||
"data": {
|
||||
"server_id": 1,
|
||||
"config": {
|
||||
"ID": 1,
|
||||
"CreatedAt": "2024-01-01T00:00:00Z",
|
||||
"UpdatedAt": "2024-01-01T00:00:00Z",
|
||||
"DeletedAt": null,
|
||||
"user_id": 1,
|
||||
"name": "我的 DNS 服务器",
|
||||
"port": 53,
|
||||
"listen_ip": "0.0.0.0",
|
||||
"upstream_dns": "8.8.8.8,8.8.4.4",
|
||||
"enable_recursion": true,
|
||||
"status": 1,
|
||||
"description": "个人 DNS 服务器"
|
||||
},
|
||||
"running": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 16. 获取 DNS 服务器运行状态
|
||||
|
||||
**接口路径**: `/dns/server/status`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| server_id | uint | 是 | DNS 服务器 ID |
|
||||
|
||||
**请求示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"server_id": 1
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "获取DNS服务器状态成功",
|
||||
"data": {
|
||||
"server_id": 1,
|
||||
"config": {
|
||||
"ID": 1,
|
||||
"CreatedAt": "2024-01-01T00:00:00Z",
|
||||
"UpdatedAt": "2024-01-01T00:00:00Z",
|
||||
"DeletedAt": null,
|
||||
"user_id": 1,
|
||||
"name": "我的 DNS 服务器",
|
||||
"port": 53,
|
||||
"listen_ip": "0.0.0.0",
|
||||
"upstream_dns": "8.8.8.8,8.8.4.4",
|
||||
"enable_recursion": true,
|
||||
"status": 1,
|
||||
"description": "个人 DNS 服务器"
|
||||
},
|
||||
"running": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 数据模型
|
||||
|
||||
### DNSServer
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| ID | uint | 主键 ID |
|
||||
| CreatedAt | time.Time | 创建时间 |
|
||||
| UpdatedAt | time.Time | 更新时间 |
|
||||
| DeletedAt | *time.Time | 删除时间 |
|
||||
| user_id | uint | 用户 ID |
|
||||
| name | string | DNS 服务器名称 |
|
||||
| port | uint | 监听端口 |
|
||||
| listen_ip | string | 监听 IP |
|
||||
| upstream_dns | string | 上游 DNS 服务器 |
|
||||
| enable_recursion | bool | 是否启用递归查询 |
|
||||
| status | uint | 状态:0 停止,1 运行中,2 错误 |
|
||||
| description | string | 描述 |
|
||||
|
||||
### DNSZone
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| ID | uint | 主键 ID |
|
||||
| CreatedAt | time.Time | 创建时间 |
|
||||
| UpdatedAt | time.Time | 更新时间 |
|
||||
| DeletedAt | *time.Time | 删除时间 |
|
||||
| server_id | uint | 所属 DNS 服务器 ID |
|
||||
| domain | string | 域名 |
|
||||
| soa_mname | string | SOA 记录的主域名服务器 |
|
||||
| soa_rname | string | SOA 记录的管理员邮箱 |
|
||||
| soa_serial | uint | SOA 记录的序列号 |
|
||||
| soa_refresh | uint | SOA 记录的刷新时间(秒) |
|
||||
| soa_retry | uint | SOA 记录的重试时间(秒) |
|
||||
| soa_expire | uint | SOA 记录的过期时间(秒) |
|
||||
| soa_minimum | uint | SOA 记录的最小 TTL(秒) |
|
||||
| ttl | uint | 默认 TTL(秒) |
|
||||
| description | string | 描述 |
|
||||
|
||||
### DNSRecord
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| ID | uint | 主键 ID |
|
||||
| CreatedAt | time.Time | 创建时间 |
|
||||
| UpdatedAt | time.Time | 更新时间 |
|
||||
| DeletedAt | *time.Time | 删除时间 |
|
||||
| zone_id | uint | 所属 Zone ID |
|
||||
| name | string | 记录名称 |
|
||||
| type | uint | 记录类型 |
|
||||
| value | string | 记录值 |
|
||||
| ttl | uint | TTL(秒) |
|
||||
| priority | uint | 优先级 |
|
||||
| weight | uint | 权重 |
|
||||
| port | uint | 端口 |
|
||||
| target | string | 目标 |
|
||||
|
||||
### DNSServiceInstance
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| server_id | uint | DNS 服务器 ID |
|
||||
| config | DNSServer | DNS 服务器配置 |
|
||||
| running | bool | 是否正在运行 |
|
||||
|
||||
## 错误码说明
|
||||
|
||||
| 错误码 | 说明 |
|
||||
|--------|------|
|
||||
| 0 | 成功 |
|
||||
| 1 | 参数错误 |
|
||||
| 2 | 系统错误 |
|
||||
|
||||
## 功能特性
|
||||
|
||||
### 基础功能
|
||||
- 支持多 DNS 服务器实例管理
|
||||
- 每个 DNS 服务器可以管理多个域名区域(Zone)
|
||||
- 每个域名区域可以添加多条 DNS 记录
|
||||
- 支持常见 DNS 记录类型:A、AAAA、CNAME、MX、NS、TXT、SRV、SOA
|
||||
- 完整的 SOA 记录配置
|
||||
|
||||
### 运行时管理
|
||||
- 支持 DNS 服务的启动、停止、重启操作
|
||||
- 同时支持 UDP 和 TCP 协议
|
||||
- 配置修改后自动重启运行中的服务
|
||||
- 实时获取服务运行状态
|
||||
- 支持递归查询,可配置上游 DNS 服务器
|
||||
|
||||
### 权限说明
|
||||
- 普通用户只能操作自己创建的 DNS 服务器、区域和记录
|
||||
- 管理员可以操作所有 DNS 服务器、区域和记录
|
||||
- 删除操作会级联删除相关的子资源(删除服务器会删除其下的区域,删除区域会删除其下的记录)
|
||||
|
||||
### 自动重启特性
|
||||
当 DNS 服务器的配置(端口、监听IP、上游DNS等)被修改时,如果服务正在运行,系统会自动重启服务以应用新的配置。
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
import request from '@/utils/request.js'
|
||||
|
||||
// 转换数据为 URLSearchParams 格式
|
||||
const toFormData = (data) => {
|
||||
const params = new URLSearchParams();
|
||||
for (let key in data) {
|
||||
if (data[key] !== null && data[key] !== undefined && data[key] !== '') {
|
||||
params.append(key, data[key]);
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
// DNS 服务器接口
|
||||
export const createDNSServer = (data) => {
|
||||
return request.post('/dns/server/create', toFormData(data))
|
||||
}
|
||||
|
||||
export const getDNSServerList = (data) => {
|
||||
return request.post('/dns/server/get', toFormData(data))
|
||||
}
|
||||
|
||||
export const updateDNSServer = (data) => {
|
||||
return request.post('/dns/server/update', toFormData(data))
|
||||
}
|
||||
|
||||
export const deleteDNSServer = (data) => {
|
||||
return request.post('/dns/server/delete', toFormData(data))
|
||||
}
|
||||
|
||||
export const startDNSServer = (data) => {
|
||||
return request.post('/dns/server/start', toFormData(data))
|
||||
}
|
||||
|
||||
export const stopDNSServer = (data) => {
|
||||
return request.post('/dns/server/stop', toFormData(data))
|
||||
}
|
||||
|
||||
export const restartDNSServer = (data) => {
|
||||
return request.post('/dns/server/restart', toFormData(data))
|
||||
}
|
||||
|
||||
export const getDNSServerStatus = (data) => {
|
||||
return request.post('/dns/server/status', toFormData(data))
|
||||
}
|
||||
|
||||
// DNS 区域接口
|
||||
export const createDNSZone = (data) => {
|
||||
return request.post('/dns/zone/create', toFormData(data))
|
||||
}
|
||||
|
||||
export const getDNSZoneList = (data) => {
|
||||
return request.post('/dns/zone/get', toFormData(data))
|
||||
}
|
||||
|
||||
export const updateDNSZone = (data) => {
|
||||
return request.post('/dns/zone/update', toFormData(data))
|
||||
}
|
||||
|
||||
export const deleteDNSZone = (data) => {
|
||||
return request.post('/dns/zone/delete', toFormData(data))
|
||||
}
|
||||
|
||||
// DNS 记录接口
|
||||
export const createDNSRecord = (data) => {
|
||||
return request.post('/dns/record/create', toFormData(data))
|
||||
}
|
||||
|
||||
export const getDNSRecordList = (data) => {
|
||||
return request.post('/dns/record/get', toFormData(data))
|
||||
}
|
||||
|
||||
export const updateDNSRecord = (data) => {
|
||||
return request.post('/dns/record/update', toFormData(data))
|
||||
}
|
||||
|
||||
export const deleteDNSRecord = (data) => {
|
||||
return request.post('/dns/record/delete', toFormData(data))
|
||||
}
|
||||
|
|
@ -69,6 +69,9 @@ import {
|
|||
UserFilled,
|
||||
OfficeBuilding,
|
||||
Connection,
|
||||
Setting as ServerIcon,
|
||||
Link as ZoneIcon,
|
||||
DocumentCopy as RecordIcon,
|
||||
} from "@element-plus/icons-vue";
|
||||
|
||||
const router = useRouter();
|
||||
|
|
@ -139,6 +142,24 @@ const menuList = ref([
|
|||
icon: Connection,
|
||||
show: true,
|
||||
},
|
||||
{
|
||||
path: "/dnsServer",
|
||||
title: "DNS服务器配置",
|
||||
icon: ServerIcon,
|
||||
show: true,
|
||||
},
|
||||
{
|
||||
path: "/dnsZone",
|
||||
title: "DNS区域管理",
|
||||
icon: ZoneIcon,
|
||||
show: true,
|
||||
},
|
||||
{
|
||||
path: "/dnsRecord",
|
||||
title: "DNS记录管理",
|
||||
icon: RecordIcon,
|
||||
show: true,
|
||||
},
|
||||
]);
|
||||
|
||||
const toggleCollapse = () => {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@ import Chat from "@/views/Chat.vue"
|
|||
import Group from "@/views/Group.vue"
|
||||
import File from "@/views/FileList.vue"
|
||||
import Shell from "@/views/ShellList.vue"
|
||||
import DNSServer from "@/views/DNSServer.vue"
|
||||
import DNSZone from "@/views/DNSZone.vue"
|
||||
import DNSRecord from "@/views/DNSRecord.vue"
|
||||
|
||||
import callback from "@/views/callback.vue";
|
||||
import projectSelect from "@/views/project-select.vue";
|
||||
|
|
@ -94,6 +97,21 @@ const routes = [
|
|||
path: 'projectSelect',
|
||||
name: 'projectSelect',
|
||||
component: projectSelect
|
||||
},
|
||||
{
|
||||
path: 'dnsServer',
|
||||
name: 'DNSServer',
|
||||
component: DNSServer
|
||||
},
|
||||
{
|
||||
path: 'dnsZone',
|
||||
name: 'DNSZone',
|
||||
component: DNSZone
|
||||
},
|
||||
{
|
||||
path: 'dnsRecord',
|
||||
name: 'DNSRecord',
|
||||
component: DNSRecord
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,472 @@
|
|||
<template>
|
||||
<div class="dns-record-container">
|
||||
<el-card class="box-card">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>DNS 记录管理</span>
|
||||
<el-button type="primary" size="small" @click="handleAdd">
|
||||
<el-icon><Plus /></el-icon>
|
||||
添加记录
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 搜索筛选 -->
|
||||
<el-form :inline="true" :model="searchForm" class="search-form">
|
||||
<el-form-item label="DNS服务器">
|
||||
<el-select v-model="searchForm.server_id" placeholder="请选择服务器" @change="handleServerChange">
|
||||
<el-option
|
||||
v-for="server in serverList"
|
||||
:key="server.ID"
|
||||
:label="server.name"
|
||||
:value="server.ID"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="区域">
|
||||
<el-select v-model="searchForm.zone_id" placeholder="请选择区域">
|
||||
<el-option
|
||||
v-for="zone in filteredZoneList"
|
||||
:key="zone.ID"
|
||||
:label="zone.domain"
|
||||
:value="zone.ID"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleSearch">搜索</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-table v-loading="loading" :data="recordList" style="width: 100%">
|
||||
<el-table-column prop="server_name" label="服务器" width="150" />
|
||||
<el-table-column prop="zone_domain" label="区域" width="150" />
|
||||
<el-table-column prop="name" label="记录名称" width="120" />
|
||||
<el-table-column prop="type" label="记录类型" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="getRecordTypeColor(row.type)">
|
||||
{{ getRecordTypeName(row.type) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="value" label="记录值" show-overflow-tooltip />
|
||||
<el-table-column prop="ttl" label="TTL" width="80">
|
||||
<template #default="{ row }">
|
||||
{{ row.ttl }} 秒
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="priority" label="优先级" width="80" v-if="showPriority">
|
||||
<template #default="{ row }">
|
||||
{{ row.priority || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="weight" label="权重" width="80" v-if="showWeight">
|
||||
<template #default="{ row }">
|
||||
{{ row.weight || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="port" label="端口" width="80" v-if="showPort">
|
||||
<template #default="{ row }">
|
||||
{{ row.port || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="target" label="目标" width="150" v-if="showTarget">
|
||||
<template #default="{ row }">
|
||||
{{ row.target || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="120" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" size="small" @click="handleEdit(row)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button link type="danger" size="small" @click="handleDelete(row)">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<!-- 新增/编辑对话框 -->
|
||||
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="700px">
|
||||
<el-form ref="recordFormRef" :model="recordForm" label-width="100px">
|
||||
<el-form-item label="DNS服务器" prop="server_id">
|
||||
<el-select v-model="formServerId" placeholder="请选择服务器" @change="handleFormServerChange">
|
||||
<el-option
|
||||
v-for="server in serverList"
|
||||
:key="server.ID"
|
||||
:label="server.name"
|
||||
:value="server.ID"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="区域" prop="zone_id">
|
||||
<el-select v-model="recordForm.zone_id" placeholder="请选择区域">
|
||||
<el-option
|
||||
v-for="zone in formZoneList"
|
||||
:key="zone.ID"
|
||||
:label="zone.domain"
|
||||
:value="zone.ID"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="记录名称" prop="name">
|
||||
<el-input v-model="recordForm.name" placeholder="请输入记录名称,如 www 或 @" />
|
||||
</el-form-item>
|
||||
<el-form-item label="记录类型" prop="type">
|
||||
<el-select v-model="recordForm.type" placeholder="请选择记录类型">
|
||||
<el-option
|
||||
v-for="item in recordTypeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="记录值" prop="value">
|
||||
<el-input v-model="recordForm.value" :type="recordForm.type === 16 ? 'textarea' : 'text'" :rows="recordForm.type === 16 ? 3 : 1" placeholder="请输入记录值" />
|
||||
</el-form-item>
|
||||
<el-form-item label="TTL" prop="ttl">
|
||||
<el-input-number v-model="recordForm.ttl" :min="0" :max="31536000" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="优先级" prop="priority" v-if="showPriorityInput">
|
||||
<el-input-number v-model="recordForm.priority" :min="0" :max="65535" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="权重" prop="weight" v-if="showWeightInput">
|
||||
<el-input-number v-model="recordForm.weight" :min="0" :max="65535" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="端口" prop="port" v-if="showPortInput">
|
||||
<el-input-number v-model="recordForm.port" :min="0" :max="65535" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="目标" prop="target" v-if="showTargetInput">
|
||||
<el-input v-model="recordForm.target" placeholder="请输入目标" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, computed, onMounted, watch } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { Plus } from '@element-plus/icons-vue'
|
||||
import {
|
||||
createDNSRecord,
|
||||
getDNSRecordList,
|
||||
updateDNSRecord,
|
||||
deleteDNSRecord
|
||||
} from '@/api/dns.js'
|
||||
import { getDNSServerList } from '@/api/dns.js'
|
||||
import { getDNSZoneList } from '@/api/dns.js'
|
||||
|
||||
const loading = ref(false)
|
||||
const recordList = ref([])
|
||||
const serverList = ref([])
|
||||
const zoneList = ref([])
|
||||
const dialogVisible = ref(false)
|
||||
const dialogTitle = ref('')
|
||||
const recordFormRef = ref()
|
||||
|
||||
// 搜索表单
|
||||
const searchForm = reactive({
|
||||
server_id: null,
|
||||
zone_id: null
|
||||
})
|
||||
|
||||
// 记录表单
|
||||
const recordForm = reactive({
|
||||
record_id: null,
|
||||
zone_id: null,
|
||||
name: '',
|
||||
type: 1,
|
||||
value: '',
|
||||
ttl: 0,
|
||||
priority: 0,
|
||||
weight: 0,
|
||||
port: 0,
|
||||
target: ''
|
||||
})
|
||||
|
||||
// 临时存储服务器ID,用于前端展示
|
||||
const formServerId = ref(null)
|
||||
|
||||
// 记录类型选项
|
||||
const recordTypeOptions = [
|
||||
{ value: 1, label: 'A' },
|
||||
{ value: 28, label: 'AAAA' },
|
||||
{ value: 5, label: 'CNAME' },
|
||||
{ value: 15, label: 'MX' },
|
||||
{ value: 2, label: 'NS' },
|
||||
{ value: 6, label: 'SOA' },
|
||||
{ value: 16, label: 'TXT' },
|
||||
{ value: 33, label: 'SRV' }
|
||||
]
|
||||
|
||||
// 筛选后的区域列表
|
||||
const filteredZoneList = computed(() => {
|
||||
if (!searchForm.server_id) {
|
||||
return zoneList.value
|
||||
}
|
||||
return zoneList.value.filter(zone => zone.server_id === searchForm.server_id)
|
||||
})
|
||||
|
||||
// 表单区域列表
|
||||
const formZoneList = computed(() => {
|
||||
if (!formServerId.value) {
|
||||
return []
|
||||
}
|
||||
return zoneList.value.filter(zone => zone.server_id === formServerId.value)
|
||||
})
|
||||
|
||||
// 根据记录类型显示不同的字段
|
||||
const showPriority = ref(false)
|
||||
const showWeight = ref(false)
|
||||
const showPort = ref(false)
|
||||
const showTarget = ref(false)
|
||||
const showPriorityInput = ref(false)
|
||||
const showWeightInput = ref(false)
|
||||
const showPortInput = ref(false)
|
||||
const showTargetInput = ref(false)
|
||||
|
||||
// 监听记录类型变化
|
||||
watch(() => recordForm.type, (newType) => {
|
||||
showPriorityInput.value = [15, 33].includes(newType) // MX, SRV
|
||||
showWeightInput.value = [33].includes(newType) // SRV
|
||||
showPortInput.value = [33].includes(newType) // SRV
|
||||
showTargetInput.value = [33].includes(newType) // SRV
|
||||
})
|
||||
|
||||
// 获取服务器列表
|
||||
const fetchServerList = async () => {
|
||||
try {
|
||||
const res = await getDNSServerList({ server_id: 0, get_type: 0 })
|
||||
if (res.code === 0) {
|
||||
serverList.value = res.data
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('获取服务器列表失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 获取区域列表
|
||||
const fetchZoneList = async () => {
|
||||
try {
|
||||
const res = await getDNSZoneList({ zone_id: 0, get_type: 0 })
|
||||
if (res.code === 0) {
|
||||
zoneList.value = res.data
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('获取区域列表失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 获取记录列表
|
||||
const fetchRecordList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const params = {
|
||||
record_id: 0,
|
||||
zone_id: searchForm.zone_id || 0,
|
||||
get_type: 0
|
||||
}
|
||||
|
||||
const res = await getDNSRecordList(params)
|
||||
if (res.code === 0) {
|
||||
// 合并服务器和区域信息
|
||||
const records = res.data.map(record => {
|
||||
const zone = zoneList.value.find(z => z.ID === record.zone_id)
|
||||
const server = serverList.value.find(s => s.ID === (zone ? zone.server_id : null))
|
||||
return {
|
||||
...record,
|
||||
server_name: server ? server.name : '未知服务器',
|
||||
zone_domain: zone ? zone.domain : '未知区域'
|
||||
}
|
||||
})
|
||||
recordList.value = records
|
||||
|
||||
// 确定需要显示的列
|
||||
showPriority.value = records.some(record => [15, 33].includes(record.type))
|
||||
showWeight.value = records.some(record => [33].includes(record.type))
|
||||
showPort.value = records.some(record => [33].includes(record.type))
|
||||
showTarget.value = records.some(record => [33].includes(record.type))
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('获取记录列表失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 服务器选择变化
|
||||
const handleServerChange = () => {
|
||||
searchForm.zone_id = null
|
||||
}
|
||||
|
||||
// 搜索
|
||||
const handleSearch = () => {
|
||||
fetchRecordList()
|
||||
}
|
||||
|
||||
// 添加记录
|
||||
const handleAdd = () => {
|
||||
dialogTitle.value = '添加 DNS 记录'
|
||||
// 重置表单,确保数字字段有默认值
|
||||
recordForm.record_id = null
|
||||
recordForm.zone_id = null
|
||||
recordForm.name = ''
|
||||
recordForm.type = 1
|
||||
recordForm.value = ''
|
||||
recordForm.ttl = 0
|
||||
recordForm.priority = 0
|
||||
recordForm.weight = 0
|
||||
recordForm.port = 0
|
||||
recordForm.target = ''
|
||||
formServerId.value = null
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
// 编辑记录
|
||||
const handleEdit = (row) => {
|
||||
dialogTitle.value = '编辑 DNS 记录'
|
||||
Object.assign(recordForm, row)
|
||||
recordForm.record_id = row.ID
|
||||
|
||||
// 设置服务器ID
|
||||
const zone = zoneList.value.find(z => z.ID === row.zone_id)
|
||||
if (zone) {
|
||||
formServerId.value = zone.server_id
|
||||
}
|
||||
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
// 表单服务器选择变化
|
||||
const handleFormServerChange = () => {
|
||||
recordForm.zone_id = null
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
const handleSubmit = async () => {
|
||||
await recordFormRef.value.validate()
|
||||
|
||||
try {
|
||||
// 准备发送到接口的参数,只包含接口需要的字段
|
||||
const submitData = {
|
||||
zone_id: recordForm.zone_id,
|
||||
name: recordForm.name,
|
||||
type: recordForm.type,
|
||||
value: recordForm.value,
|
||||
ttl: recordForm.ttl,
|
||||
priority: recordForm.priority,
|
||||
weight: recordForm.weight,
|
||||
port: recordForm.port,
|
||||
target: recordForm.target
|
||||
}
|
||||
|
||||
let res
|
||||
if (recordForm.record_id) {
|
||||
submitData.record_id = recordForm.record_id
|
||||
res = await updateDNSRecord(submitData)
|
||||
} else {
|
||||
res = await createDNSRecord(submitData)
|
||||
}
|
||||
|
||||
if (res.code === 0) {
|
||||
ElMessage.success(recordForm.record_id ? '更新成功' : '创建成功')
|
||||
dialogVisible.value = false
|
||||
fetchRecordList()
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('操作失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 删除记录
|
||||
const handleDelete = async (row) => {
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
'确定要删除该记录吗?',
|
||||
'删除确认',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}
|
||||
)
|
||||
|
||||
const res = await deleteDNSRecord({ record_id: row.ID, del_type: 0 })
|
||||
if (res.code === 0) {
|
||||
ElMessage.success('删除成功')
|
||||
fetchRecordList()
|
||||
}
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
ElMessage.error('删除失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取记录类型名称
|
||||
const getRecordTypeName = (type) => {
|
||||
const typeMap = {
|
||||
1: 'A',
|
||||
28: 'AAAA',
|
||||
5: 'CNAME',
|
||||
15: 'MX',
|
||||
2: 'NS',
|
||||
6: 'SOA',
|
||||
16: 'TXT',
|
||||
33: 'SRV'
|
||||
}
|
||||
return typeMap[type] || '未知类型'
|
||||
}
|
||||
|
||||
// 获取记录类型颜色
|
||||
const getRecordTypeColor = (type) => {
|
||||
const colorMap = {
|
||||
1: 'primary',
|
||||
28: 'success',
|
||||
5: 'warning',
|
||||
15: 'danger',
|
||||
2: 'info',
|
||||
6: 'info',
|
||||
16: 'info',
|
||||
33: 'info'
|
||||
}
|
||||
return colorMap[type] || 'info'
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
Promise.all([fetchServerList(), fetchZoneList()]).then(() => {
|
||||
fetchRecordList()
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dns-record-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.search-form {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,290 @@
|
|||
<template>
|
||||
<div class="dns-server-container">
|
||||
<el-card class="box-card">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>DNS 服务器配置</span>
|
||||
<el-button type="primary" size="small" @click="handleAdd">
|
||||
<el-icon><Plus /></el-icon>
|
||||
添加服务器
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-table v-loading="loading" :data="serverList" style="width: 100%">
|
||||
<el-table-column prop="name" label="服务器名称" width="180" />
|
||||
<el-table-column prop="listen_ip" label="监听IP" width="120" />
|
||||
<el-table-column prop="port" label="端口" width="80" />
|
||||
<el-table-column prop="upstream_dns" label="上游DNS" show-overflow-tooltip />
|
||||
<el-table-column prop="enable_recursion" label="递归查询" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.enable_recursion ? 'success' : 'danger'">
|
||||
{{ row.enable_recursion ? '开启' : '关闭' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" label="状态" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="getStatusType(row.status)">
|
||||
{{ getStatusText(row.status) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="description" label="描述" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="200" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" size="small" @click="handleEdit(row)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button link type="success" size="small" @click="handleStart(row)" v-if="row.status === 0">
|
||||
启动
|
||||
</el-button>
|
||||
<el-button link type="warning" size="small" @click="handleStop(row)" v-if="row.status === 1">
|
||||
停止
|
||||
</el-button>
|
||||
<el-button link type="info" size="small" @click="handleRestart(row)" v-if="row.status === 1">
|
||||
重启
|
||||
</el-button>
|
||||
<el-button link type="danger" size="small" @click="handleDelete(row)">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<!-- 新增/编辑对话框 -->
|
||||
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="600px">
|
||||
<el-form ref="serverFormRef" :model="serverForm" label-width="100px">
|
||||
<el-form-item label="服务器名称" prop="name">
|
||||
<el-input v-model="serverForm.name" placeholder="请输入服务器名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="监听IP" prop="listen_ip">
|
||||
<el-input v-model="serverForm.listen_ip" placeholder="请输入监听IP" />
|
||||
</el-form-item>
|
||||
<el-form-item label="端口" prop="port">
|
||||
<el-input-number v-model="serverForm.port" :min="1" :max="65535" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="上游DNS" prop="upstream_dns">
|
||||
<el-input v-model="serverForm.upstream_dns" placeholder="多个DNS用逗号分隔" />
|
||||
</el-form-item>
|
||||
<el-form-item label="递归查询" prop="enable_recursion">
|
||||
<el-switch v-model="serverForm.enable_recursion" />
|
||||
</el-form-item>
|
||||
<el-form-item label="描述" prop="description">
|
||||
<el-input v-model="serverForm.description" type="textarea" :rows="3" placeholder="请输入描述" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { Plus } from '@element-plus/icons-vue'
|
||||
import {
|
||||
createDNSServer,
|
||||
getDNSServerList,
|
||||
updateDNSServer,
|
||||
deleteDNSServer,
|
||||
startDNSServer,
|
||||
stopDNSServer,
|
||||
restartDNSServer
|
||||
} from '@/api/dns.js'
|
||||
|
||||
const loading = ref(false)
|
||||
const serverList = ref([])
|
||||
const dialogVisible = ref(false)
|
||||
const dialogTitle = ref('')
|
||||
const serverFormRef = ref()
|
||||
const serverForm = reactive({
|
||||
server_id: null,
|
||||
name: '',
|
||||
listen_ip: '0.0.0.0',
|
||||
port: 53,
|
||||
upstream_dns: '8.8.8.8,8.8.4.4',
|
||||
enable_recursion: true,
|
||||
description: ''
|
||||
})
|
||||
|
||||
// 获取服务器列表
|
||||
const fetchServerList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await getDNSServerList({ server_id: 0, get_type: 0 })
|
||||
if (res.code === 0) {
|
||||
serverList.value = res.data
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('获取服务器列表失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 添加服务器
|
||||
const handleAdd = () => {
|
||||
dialogTitle.value = '添加 DNS 服务器'
|
||||
Object.keys(serverForm).forEach(key => {
|
||||
if (key === 'listen_ip') serverForm[key] = '0.0.0.0'
|
||||
else if (key === 'port') serverForm[key] = 53
|
||||
else if (key === 'upstream_dns') serverForm[key] = '8.8.8.8,8.8.4.4'
|
||||
else if (key === 'enable_recursion') serverForm[key] = true
|
||||
else serverForm[key] = ''
|
||||
})
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
// 编辑服务器
|
||||
const handleEdit = (row) => {
|
||||
dialogTitle.value = '编辑 DNS 服务器'
|
||||
Object.assign(serverForm, row)
|
||||
serverForm.server_id = row.ID
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
const handleSubmit = async () => {
|
||||
await serverFormRef.value.validate()
|
||||
|
||||
try {
|
||||
// 准备发送到接口的参数,只包含接口需要的字段
|
||||
const submitData = {
|
||||
name: serverForm.name,
|
||||
listen_ip: serverForm.listen_ip,
|
||||
port: serverForm.port,
|
||||
upstream_dns: serverForm.upstream_dns,
|
||||
enable_recursion: serverForm.enable_recursion,
|
||||
description: serverForm.description
|
||||
}
|
||||
|
||||
let res
|
||||
if (serverForm.server_id) {
|
||||
submitData.server_id = serverForm.server_id
|
||||
res = await updateDNSServer(submitData)
|
||||
} else {
|
||||
res = await createDNSServer(submitData)
|
||||
}
|
||||
|
||||
if (res.code === 0) {
|
||||
ElMessage.success(serverForm.server_id ? '更新成功' : '创建成功')
|
||||
dialogVisible.value = false
|
||||
fetchServerList()
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('操作失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 启动服务器
|
||||
const handleStart = async (row) => {
|
||||
try {
|
||||
const res = await startDNSServer({ server_id: row.ID })
|
||||
if (res.code === 0) {
|
||||
ElMessage.success('启动成功')
|
||||
fetchServerList()
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('启动失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 停止服务器
|
||||
const handleStop = async (row) => {
|
||||
try {
|
||||
const res = await stopDNSServer({ server_id: row.ID })
|
||||
if (res.code === 0) {
|
||||
ElMessage.success('停止成功')
|
||||
fetchServerList()
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('停止失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 重启服务器
|
||||
const handleRestart = async (row) => {
|
||||
try {
|
||||
const res = await restartDNSServer({ server_id: row.ID })
|
||||
if (res.code === 0) {
|
||||
ElMessage.success('重启成功')
|
||||
fetchServerList()
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('重启失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 删除服务器
|
||||
const handleDelete = async (row) => {
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
'确定要删除该服务器吗?',
|
||||
'删除确认',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}
|
||||
)
|
||||
|
||||
const res = await deleteDNSServer({ server_id: row.ID, del_type: 0 })
|
||||
if (res.code === 0) {
|
||||
ElMessage.success('删除成功')
|
||||
fetchServerList()
|
||||
}
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
ElMessage.error('删除失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取状态文本
|
||||
const getStatusText = (status) => {
|
||||
const statusMap = {
|
||||
0: '已停止',
|
||||
1: '运行中',
|
||||
2: '错误'
|
||||
}
|
||||
return statusMap[status] || '未知'
|
||||
}
|
||||
|
||||
// 获取状态类型
|
||||
const getStatusType = (status) => {
|
||||
const typeMap = {
|
||||
0: 'danger',
|
||||
1: 'success',
|
||||
2: 'warning'
|
||||
}
|
||||
return typeMap[status] || 'info'
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchServerList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dns-server-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,251 @@
|
|||
<template>
|
||||
<div class="dns-zone-container">
|
||||
<el-card class="box-card">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>DNS 区域管理</span>
|
||||
<el-button type="primary" size="small" @click="handleAdd">
|
||||
<el-icon><Plus /></el-icon>
|
||||
添加区域
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-table v-loading="loading" :data="zoneList" style="width: 100%">
|
||||
<el-table-column prop="domain" label="域名" width="200" />
|
||||
<el-table-column prop="server_name" label="所属服务器" width="180" />
|
||||
<el-table-column prop="soa_mname" label="主域名服务器" width="180" />
|
||||
<el-table-column prop="soa_rname" label="管理员邮箱" width="180" />
|
||||
<el-table-column prop="ttl" label="默认TTL" width="100">
|
||||
<template #default="{ row }">
|
||||
{{ row.ttl }} 秒
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="description" label="描述" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="150" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" size="small" @click="handleEdit(row)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button link type="danger" size="small" @click="handleDelete(row)">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<!-- 新增/编辑对话框 -->
|
||||
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="700px">
|
||||
<el-form ref="zoneFormRef" :model="zoneForm" label-width="120px">
|
||||
<el-form-item label="DNS服务器" prop="server_id">
|
||||
<el-select v-model="zoneForm.server_id" placeholder="请选择DNS服务器" style="width: 100%">
|
||||
<el-option
|
||||
v-for="server in serverList"
|
||||
:key="server.ID"
|
||||
:label="server.name"
|
||||
:value="server.ID"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="域名" prop="domain">
|
||||
<el-input v-model="zoneForm.domain" placeholder="请输入域名,如 example.com" />
|
||||
</el-form-item>
|
||||
<el-form-item label="主域名服务器" prop="soa_mname">
|
||||
<el-input v-model="zoneForm.soa_mname" placeholder="请输入主域名服务器" />
|
||||
</el-form-item>
|
||||
<el-form-item label="管理员邮箱" prop="soa_rname">
|
||||
<el-input v-model="zoneForm.soa_rname" placeholder="请输入管理员邮箱" />
|
||||
</el-form-item>
|
||||
<el-form-item label="默认TTL" prop="ttl">
|
||||
<el-input-number v-model="zoneForm.ttl" :min="1" :max="31536000" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="描述" prop="description">
|
||||
<el-input v-model="zoneForm.description" type="textarea" :rows="3" placeholder="请输入描述" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { Plus } from '@element-plus/icons-vue'
|
||||
import {
|
||||
createDNSZone,
|
||||
getDNSZoneList,
|
||||
updateDNSZone,
|
||||
deleteDNSZone
|
||||
} from '@/api/dns.js'
|
||||
import { getDNSServerList } from '@/api/dns.js'
|
||||
|
||||
const loading = ref(false)
|
||||
const zoneList = ref([])
|
||||
const serverList = ref([])
|
||||
const dialogVisible = ref(false)
|
||||
const dialogTitle = ref('')
|
||||
const zoneFormRef = ref()
|
||||
const zoneForm = reactive({
|
||||
zone_id: null,
|
||||
server_id: null,
|
||||
domain: '',
|
||||
soa_mname: '',
|
||||
soa_rname: '',
|
||||
soa_serial: 1,
|
||||
soa_refresh: 86400,
|
||||
soa_retry: 7200,
|
||||
soa_expire: 3600000,
|
||||
soa_minimum: 3600,
|
||||
ttl: 3600,
|
||||
description: ''
|
||||
})
|
||||
|
||||
// 获取服务器列表
|
||||
const fetchServerList = async () => {
|
||||
try {
|
||||
const res = await getDNSServerList({ server_id: 0, get_type: 0 })
|
||||
if (res.code === 0) {
|
||||
serverList.value = res.data
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('获取服务器列表失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 获取区域列表
|
||||
const fetchZoneList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await getDNSZoneList({ zone_id: 0, get_type: 0 })
|
||||
if (res.code === 0) {
|
||||
// 合并服务器名称
|
||||
const zones = res.data.map(zone => {
|
||||
const server = serverList.value.find(s => s.ID === zone.server_id)
|
||||
return {
|
||||
...zone,
|
||||
server_name: server ? server.name : '未知服务器'
|
||||
}
|
||||
})
|
||||
zoneList.value = zones
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('获取区域列表失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 添加区域
|
||||
const handleAdd = () => {
|
||||
dialogTitle.value = '添加 DNS 区域'
|
||||
Object.keys(zoneForm).forEach(key => {
|
||||
if (['soa_serial', 'soa_refresh', 'soa_retry', 'soa_expire', 'soa_minimum', 'ttl'].includes(key)) {
|
||||
zoneForm[key] = key === 'ttl' ? 3600 : 1
|
||||
} else {
|
||||
zoneForm[key] = ''
|
||||
}
|
||||
})
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
// 编辑区域
|
||||
const handleEdit = (row) => {
|
||||
dialogTitle.value = '编辑 DNS 区域'
|
||||
Object.assign(zoneForm, row)
|
||||
zoneForm.zone_id = row.ID
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
const handleSubmit = async () => {
|
||||
await zoneFormRef.value.validate()
|
||||
|
||||
try {
|
||||
// 准备发送到接口的参数,只包含接口需要的字段
|
||||
const submitData = {
|
||||
domain: zoneForm.domain,
|
||||
soa_mname: zoneForm.soa_mname,
|
||||
soa_rname: zoneForm.soa_rname,
|
||||
soa_serial: zoneForm.soa_serial,
|
||||
soa_refresh: zoneForm.soa_refresh,
|
||||
soa_retry: zoneForm.soa_retry,
|
||||
soa_expire: zoneForm.soa_expire,
|
||||
soa_minimum: zoneForm.soa_minimum,
|
||||
ttl: zoneForm.ttl,
|
||||
description: zoneForm.description
|
||||
}
|
||||
|
||||
let res
|
||||
if (zoneForm.zone_id) {
|
||||
submitData.zone_id = zoneForm.zone_id
|
||||
res = await updateDNSZone(submitData)
|
||||
} else {
|
||||
submitData.server_id = zoneForm.server_id
|
||||
res = await createDNSZone(submitData)
|
||||
}
|
||||
|
||||
if (res.code === 0) {
|
||||
ElMessage.success(zoneForm.zone_id ? '更新成功' : '创建成功')
|
||||
dialogVisible.value = false
|
||||
fetchZoneList()
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('操作失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 删除区域
|
||||
const handleDelete = async (row) => {
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
'确定要删除该区域吗?',
|
||||
'删除确认',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}
|
||||
)
|
||||
|
||||
const res = await deleteDNSZone({ zone_id: row.ID, del_type: 0 })
|
||||
if (res.code === 0) {
|
||||
ElMessage.success('删除成功')
|
||||
fetchZoneList()
|
||||
}
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
ElMessage.error('删除失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchServerList().then(() => {
|
||||
fetchZoneList()
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dns-zone-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -58,6 +58,24 @@
|
|||
@click.prevent="handleMenuSelect('/projectSelect')"
|
||||
>项目选择</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
@click.prevent="handleMenuSelect('/dnsServer')"
|
||||
>DNS服务器配置</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
@click.prevent="handleMenuSelect('/dnsZone')"
|
||||
>DNS区域管理</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
@click.prevent="handleMenuSelect('/dnsRecord')"
|
||||
>DNS记录管理</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
|
|
|
|||
Loading…
Reference in New Issue