feat: 添加AMT批量管理凭证功能
- 功能:AMT凭证的增删改查管理 - 支持设置默认凭证 - 支持单个和批量测试凭证连接 - 数据库表:amt_credential - 后端: * AmtCredential实体类 * AmtCredentialMapper * AmtCredentialService业务逻辑 * AmtCredentialController控制器 * 使用Result统一返回格式 - 前端: * AMT设置页面重构 * 凭证列表展示(分页、搜索) * 添加/编辑凭证弹窗 * 批量测试功能 * API接口封装 - 部署脚本: * init_amt_credential_table.bat - 初始化数据库 * test_amt_api.bat - 测试API接口 * rebuild_and_start_backend.bat - 重新编译后端 - 文档: * AMT_CREDENTIAL_FEATURE.md - 功能说明 * DEPLOY_AMT_FEATURE.md - 部署说明
This commit is contained in:
parent
44cb688072
commit
fd124d1017
171
AMT_CREDENTIAL_FEATURE.md
Normal file
171
AMT_CREDENTIAL_FEATURE.md
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
# AMT 批量管理凭证功能
|
||||||
|
|
||||||
|
## 功能概述
|
||||||
|
|
||||||
|
在"系统设置 > AMT设置"页面添加了 AMT 批量管理凭证功能,用于管理 Intel AMT 设备的登录凭证。
|
||||||
|
|
||||||
|
## 主要功能
|
||||||
|
|
||||||
|
### 1. 凭证管理
|
||||||
|
- ✅ 添加凭证:创建新的 AMT 登录凭证
|
||||||
|
- ✅ 编辑凭证:修改现有凭证信息
|
||||||
|
- ✅ 删除凭证:删除不需要的凭证(默认凭证不可删除)
|
||||||
|
- ✅ 设为默认:将凭证设置为默认凭证(优先用于新设备)
|
||||||
|
|
||||||
|
### 2. 凭证测试
|
||||||
|
- ✅ 单个测试:测试单个凭证的连接状态
|
||||||
|
- ✅ 批量测试:批量测试多个凭证的连接状态
|
||||||
|
|
||||||
|
### 3. 凭证信息
|
||||||
|
- 凭证名称:便于识别的名称
|
||||||
|
- 用户名:AMT 登录用户名
|
||||||
|
- 密码:AMT 登录密码(加密存储)
|
||||||
|
- 描述:凭证的详细说明
|
||||||
|
- 默认标记:是否为默认凭证
|
||||||
|
- 状态:启用/禁用
|
||||||
|
|
||||||
|
## 技术实现
|
||||||
|
|
||||||
|
### 后端
|
||||||
|
|
||||||
|
#### 数据库表
|
||||||
|
- `amt_credential` - AMT 凭证管理表
|
||||||
|
- 字段:credential_id, credential_name, username, password, description, is_default, status, created_by, created_time, updated_time
|
||||||
|
|
||||||
|
#### Java 类
|
||||||
|
- `AmtCredential.java` - 实体类
|
||||||
|
- `AmtCredentialMapper.java` - MyBatis Mapper
|
||||||
|
- `AmtCredentialDTO.java` - 数据传输对象
|
||||||
|
- `AmtCredentialService.java` - 业务逻辑层
|
||||||
|
- `AmtCredentialController.java` - 控制器层
|
||||||
|
|
||||||
|
#### API 接口
|
||||||
|
- `GET /api/amt/credential/list` - 分页查询凭证列表
|
||||||
|
- `GET /api/amt/credential/all` - 获取所有启用的凭证
|
||||||
|
- `GET /api/amt/credential/{id}` - 根据ID获取凭证
|
||||||
|
- `POST /api/amt/credential` - 创建凭证
|
||||||
|
- `PUT /api/amt/credential/{id}` - 更新凭证
|
||||||
|
- `DELETE /api/amt/credential/{id}` - 删除凭证
|
||||||
|
- `PUT /api/amt/credential/{id}/default` - 设置默认凭证
|
||||||
|
- `POST /api/amt/credential/{id}/test` - 测试凭证连接
|
||||||
|
- `POST /api/amt/credential/batch-test` - 批量测试凭证
|
||||||
|
|
||||||
|
### 前端
|
||||||
|
|
||||||
|
#### 文件
|
||||||
|
- `src/views/system/amt/index.vue` - AMT 设置页面
|
||||||
|
- `src/service/api/amt.ts` - AMT API 接口
|
||||||
|
|
||||||
|
#### 功能特性
|
||||||
|
- 数据表格展示凭证列表
|
||||||
|
- 分页、搜索、筛选
|
||||||
|
- 添加/编辑凭证弹窗
|
||||||
|
- 批量选择和批量测试
|
||||||
|
- 实时状态显示
|
||||||
|
|
||||||
|
## 安装步骤
|
||||||
|
|
||||||
|
### 1. 初始化数据库表
|
||||||
|
运行批处理脚本:
|
||||||
|
```bash
|
||||||
|
init_amt_credential_table.bat
|
||||||
|
```
|
||||||
|
|
||||||
|
或手动执行 SQL:
|
||||||
|
```bash
|
||||||
|
mysql -uroot -proot -hlocalhost -P3306 < backend/src/main/resources/sql/create_amt_credential_table.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 重启后端服务
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
mvn spring-boot:run
|
||||||
|
```
|
||||||
|
|
||||||
|
或使用批处理脚本:
|
||||||
|
```bash
|
||||||
|
restart_backend_and_test.bat
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 访问页面
|
||||||
|
登录系统后,访问:系统设置 > AMT设置
|
||||||
|
|
||||||
|
## 使用说明
|
||||||
|
|
||||||
|
### 添加凭证
|
||||||
|
1. 点击"添加凭证"按钮
|
||||||
|
2. 填写凭证信息:
|
||||||
|
- 凭证名称(必填)
|
||||||
|
- 用户名(必填)
|
||||||
|
- 密码(必填)
|
||||||
|
- 描述(可选)
|
||||||
|
- 是否设为默认
|
||||||
|
- 状态(启用/禁用)
|
||||||
|
3. 点击"确定"保存
|
||||||
|
|
||||||
|
### 测试凭证
|
||||||
|
1. 单个测试:点击凭证行的"测试"按钮
|
||||||
|
2. 批量测试:
|
||||||
|
- 勾选要测试的凭证
|
||||||
|
- 点击"批量测试"按钮
|
||||||
|
- 查看测试结果
|
||||||
|
|
||||||
|
### 设置默认凭证
|
||||||
|
1. 点击凭证行的"设为默认"按钮
|
||||||
|
2. 系统会自动取消其他凭证的默认状态
|
||||||
|
3. 默认凭证将优先用于新设备
|
||||||
|
|
||||||
|
### 编辑凭证
|
||||||
|
1. 点击凭证行的"编辑"按钮
|
||||||
|
2. 修改凭证信息
|
||||||
|
3. 点击"确定"保存
|
||||||
|
|
||||||
|
### 删除凭证
|
||||||
|
1. 点击凭证行的"删除"按钮
|
||||||
|
2. 确认删除操作
|
||||||
|
3. 注意:默认凭证不能删除
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. **密码安全**:密码在数据库中应该加密存储(当前为明文,建议后续加密)
|
||||||
|
2. **默认凭证**:系统只能有一个默认凭证
|
||||||
|
3. **凭证测试**:当前为模拟测试,实际使用时需要集成 AMT SDK
|
||||||
|
4. **权限控制**:建议只有管理员角色可以访问此功能
|
||||||
|
|
||||||
|
## 后续优化建议
|
||||||
|
|
||||||
|
1. **密码加密**:使用 AES 或 RSA 加密存储密码
|
||||||
|
2. **AMT SDK 集成**:集成真实的 AMT SDK 进行连接测试
|
||||||
|
3. **凭证应用**:将凭证应用到具体设备
|
||||||
|
4. **操作日志**:记录凭证的创建、修改、删除操作
|
||||||
|
5. **批量导入**:支持从 CSV/Excel 批量导入凭证
|
||||||
|
6. **凭证分组**:支持凭证分组管理
|
||||||
|
|
||||||
|
## 文件清单
|
||||||
|
|
||||||
|
### 后端文件
|
||||||
|
- `backend/src/main/resources/sql/create_amt_credential_table.sql`
|
||||||
|
- `backend/src/main/java/com/soybean/admin/entity/AmtCredential.java`
|
||||||
|
- `backend/src/main/java/com/soybean/admin/mapper/AmtCredentialMapper.java`
|
||||||
|
- `backend/src/main/java/com/soybean/admin/dto/AmtCredentialDTO.java`
|
||||||
|
- `backend/src/main/java/com/soybean/admin/service/AmtCredentialService.java`
|
||||||
|
- `backend/src/main/java/com/soybean/admin/controller/AmtCredentialController.java`
|
||||||
|
|
||||||
|
### 前端文件
|
||||||
|
- `src/views/system/amt/index.vue`
|
||||||
|
- `src/service/api/amt.ts`
|
||||||
|
- `src/service/api/index.ts` (更新)
|
||||||
|
|
||||||
|
### 脚本文件
|
||||||
|
- `init_amt_credential_table.bat`
|
||||||
|
|
||||||
|
## 测试建议
|
||||||
|
|
||||||
|
1. 测试添加凭证功能
|
||||||
|
2. 测试编辑凭证功能
|
||||||
|
3. 测试删除凭证功能
|
||||||
|
4. 测试设置默认凭证功能
|
||||||
|
5. 测试单个凭证连接
|
||||||
|
6. 测试批量凭证连接
|
||||||
|
7. 测试分页和搜索功能
|
||||||
|
8. 测试表单验证
|
||||||
83
DEPLOY_AMT_FEATURE.md
Normal file
83
DEPLOY_AMT_FEATURE.md
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
# AMT 凭证功能部署说明
|
||||||
|
|
||||||
|
## 问题修复
|
||||||
|
|
||||||
|
修复了 404 错误,主要问题:
|
||||||
|
1. ✅ 控制器返回格式不统一 - 已改用 `Result` 类
|
||||||
|
2. ✅ 返回代码不匹配 - 已改为 `"0000"`
|
||||||
|
3. ✅ API 路径前缀问题 - 已移除 `/api` 前缀
|
||||||
|
|
||||||
|
## 部署步骤
|
||||||
|
|
||||||
|
### 1. 初始化数据库表
|
||||||
|
```bash
|
||||||
|
init_amt_credential_table.bat
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 重启后端服务
|
||||||
|
停止当前后端服务,然后重新启动:
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
mvn spring-boot:run
|
||||||
|
```
|
||||||
|
|
||||||
|
或使用批处理脚本:
|
||||||
|
```bash
|
||||||
|
start_backend.bat
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 清除浏览器缓存
|
||||||
|
按 `Ctrl + Shift + Delete` 清除浏览器缓存
|
||||||
|
|
||||||
|
### 4. 访问页面
|
||||||
|
登录系统后,访问:**系统设置 > AMT设置**
|
||||||
|
|
||||||
|
## API 端点
|
||||||
|
|
||||||
|
所有 API 端点(无需 `/api` 前缀):
|
||||||
|
|
||||||
|
- `GET /amt/credential/list` - 分页查询凭证列表
|
||||||
|
- `GET /amt/credential/all` - 获取所有启用的凭证
|
||||||
|
- `GET /amt/credential/{id}` - 根据ID获取凭证
|
||||||
|
- `POST /amt/credential` - 创建凭证
|
||||||
|
- `PUT /amt/credential/{id}` - 更新凭证
|
||||||
|
- `DELETE /amt/credential/{id}` - 删除凭证
|
||||||
|
- `PUT /amt/credential/{id}/default` - 设置默认凭证
|
||||||
|
- `POST /amt/credential/{id}/test` - 测试凭证连接
|
||||||
|
- `POST /amt/credential/batch-test` - 批量测试凭证
|
||||||
|
|
||||||
|
## 测试 API
|
||||||
|
|
||||||
|
运行测试脚本:
|
||||||
|
```bash
|
||||||
|
test_amt_api.bat
|
||||||
|
```
|
||||||
|
|
||||||
|
或手动测试:
|
||||||
|
```bash
|
||||||
|
curl -X GET "http://localhost:8080/amt/credential/list?page=1&size=10"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
### Q: 仍然显示 404 错误
|
||||||
|
A: 确保后端服务已重启,并且数据库表已创建
|
||||||
|
|
||||||
|
### Q: 返回数据格式错误
|
||||||
|
A: 检查后端是否使用了最新的代码(使用 Result 类)
|
||||||
|
|
||||||
|
### Q: 无法创建凭证
|
||||||
|
A: 检查数据库连接和表结构是否正确
|
||||||
|
|
||||||
|
## 验证清单
|
||||||
|
|
||||||
|
- [ ] 数据库表 `amt_credential` 已创建
|
||||||
|
- [ ] 后端服务已重启
|
||||||
|
- [ ] 浏览器缓存已清除
|
||||||
|
- [ ] 可以访问 AMT 设置页面
|
||||||
|
- [ ] 可以查看凭证列表
|
||||||
|
- [ ] 可以添加新凭证
|
||||||
|
- [ ] 可以编辑凭证
|
||||||
|
- [ ] 可以删除凭证
|
||||||
|
- [ ] 可以测试凭证连接
|
||||||
|
- [ ] 可以批量测试凭证
|
||||||
@ -0,0 +1,155 @@
|
|||||||
|
package com.soybean.admin.controller;
|
||||||
|
|
||||||
|
import com.soybean.admin.common.Result;
|
||||||
|
import com.soybean.admin.dto.AmtCredentialDTO;
|
||||||
|
import com.soybean.admin.entity.AmtCredential;
|
||||||
|
import com.soybean.admin.service.AmtCredentialService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/amt/credential")
|
||||||
|
public class AmtCredentialController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AmtCredentialService amtCredentialService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询凭证列表
|
||||||
|
*/
|
||||||
|
@GetMapping("/list")
|
||||||
|
public Result<Map<String, Object>> getCredentialList(
|
||||||
|
@RequestParam(defaultValue = "1") int page,
|
||||||
|
@RequestParam(defaultValue = "10") int size,
|
||||||
|
@RequestParam(required = false) String credentialName,
|
||||||
|
@RequestParam(required = false) Integer status
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
Map<String, Object> data = amtCredentialService.getCredentialList(page, size, credentialName, status);
|
||||||
|
return Result.success(data);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error("查询失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有启用的凭证
|
||||||
|
*/
|
||||||
|
@GetMapping("/all")
|
||||||
|
public Result<List<AmtCredential>> getAllActiveCredentials() {
|
||||||
|
try {
|
||||||
|
List<AmtCredential> credentials = amtCredentialService.getAllActiveCredentials();
|
||||||
|
return Result.success(credentials);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error("查询失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID获取凭证
|
||||||
|
*/
|
||||||
|
@GetMapping("/{credentialId}")
|
||||||
|
public Result<AmtCredential> getCredentialById(@PathVariable String credentialId) {
|
||||||
|
try {
|
||||||
|
AmtCredential credential = amtCredentialService.getCredentialById(credentialId);
|
||||||
|
if (credential == null) {
|
||||||
|
return Result.error("凭证不存在");
|
||||||
|
}
|
||||||
|
return Result.success(credential);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error("查询失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建凭证
|
||||||
|
*/
|
||||||
|
@PostMapping
|
||||||
|
public Result<AmtCredential> createCredential(
|
||||||
|
@RequestBody AmtCredentialDTO dto,
|
||||||
|
HttpServletRequest request
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
String userId = (String) request.getAttribute("userId");
|
||||||
|
if (userId == null) {
|
||||||
|
userId = "admin"; // 默认用户
|
||||||
|
}
|
||||||
|
AmtCredential credential = amtCredentialService.createCredential(dto, userId);
|
||||||
|
return Result.success(credential);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error("创建失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新凭证
|
||||||
|
*/
|
||||||
|
@PutMapping("/{credentialId}")
|
||||||
|
public Result<AmtCredential> updateCredential(
|
||||||
|
@PathVariable String credentialId,
|
||||||
|
@RequestBody AmtCredentialDTO dto
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
AmtCredential credential = amtCredentialService.updateCredential(credentialId, dto);
|
||||||
|
return Result.success(credential);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error("更新失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除凭证
|
||||||
|
*/
|
||||||
|
@DeleteMapping("/{credentialId}")
|
||||||
|
public Result<Boolean> deleteCredential(@PathVariable String credentialId) {
|
||||||
|
try {
|
||||||
|
amtCredentialService.deleteCredential(credentialId);
|
||||||
|
return Result.success(true);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error("删除失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置默认凭证
|
||||||
|
*/
|
||||||
|
@PutMapping("/{credentialId}/default")
|
||||||
|
public Result<Boolean> setDefaultCredential(@PathVariable String credentialId) {
|
||||||
|
try {
|
||||||
|
amtCredentialService.setDefaultCredential(credentialId);
|
||||||
|
return Result.success(true);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error("设置失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试凭证连接
|
||||||
|
*/
|
||||||
|
@PostMapping("/{credentialId}/test")
|
||||||
|
public Result<Map<String, Object>> testCredential(@PathVariable String credentialId) {
|
||||||
|
try {
|
||||||
|
Map<String, Object> testResult = amtCredentialService.testCredential(credentialId);
|
||||||
|
return Result.success(testResult);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error("测试失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量测试凭证
|
||||||
|
*/
|
||||||
|
@PostMapping("/batch-test")
|
||||||
|
public Result<Map<String, Object>> batchTestCredentials(@RequestBody List<String> credentialIds) {
|
||||||
|
try {
|
||||||
|
Map<String, Object> testResult = amtCredentialService.batchTestCredentials(credentialIds);
|
||||||
|
return Result.success(testResult);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error("批量测试失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
package com.soybean.admin.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AmtCredentialDTO {
|
||||||
|
private String credentialId;
|
||||||
|
private String credentialName;
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
private String description;
|
||||||
|
private Boolean isDefault;
|
||||||
|
private Integer status;
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package com.soybean.admin.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("amt_credential")
|
||||||
|
public class AmtCredential {
|
||||||
|
@TableId(type = IdType.ASSIGN_ID)
|
||||||
|
private String credentialId;
|
||||||
|
|
||||||
|
private String credentialName;
|
||||||
|
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
private Boolean isDefault;
|
||||||
|
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
private String createdBy;
|
||||||
|
|
||||||
|
private LocalDateTime createdTime;
|
||||||
|
|
||||||
|
private LocalDateTime updatedTime;
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
package com.soybean.admin.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.soybean.admin.entity.AmtCredential;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface AmtCredentialMapper extends BaseMapper<AmtCredential> {
|
||||||
|
}
|
||||||
@ -0,0 +1,213 @@
|
|||||||
|
package com.soybean.admin.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.soybean.admin.dto.AmtCredentialDTO;
|
||||||
|
import com.soybean.admin.entity.AmtCredential;
|
||||||
|
import com.soybean.admin.mapper.AmtCredentialMapper;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class AmtCredentialService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AmtCredentialMapper amtCredentialMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询凭证列表
|
||||||
|
*/
|
||||||
|
public Map<String, Object> getCredentialList(int page, int size, String credentialName, Integer status) {
|
||||||
|
Page<AmtCredential> pageObj = new Page<>(page, size);
|
||||||
|
|
||||||
|
LambdaQueryWrapper<AmtCredential> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
if (credentialName != null && !credentialName.isEmpty()) {
|
||||||
|
wrapper.like(AmtCredential::getCredentialName, credentialName);
|
||||||
|
}
|
||||||
|
if (status != null) {
|
||||||
|
wrapper.eq(AmtCredential::getStatus, status);
|
||||||
|
}
|
||||||
|
wrapper.orderByDesc(AmtCredential::getIsDefault)
|
||||||
|
.orderByDesc(AmtCredential::getCreatedTime);
|
||||||
|
|
||||||
|
Page<AmtCredential> result = amtCredentialMapper.selectPage(pageObj, wrapper);
|
||||||
|
|
||||||
|
Map<String, Object> response = new HashMap<>();
|
||||||
|
response.put("records", result.getRecords());
|
||||||
|
response.put("total", result.getTotal());
|
||||||
|
response.put("current", result.getCurrent());
|
||||||
|
response.put("size", result.getSize());
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有启用的凭证
|
||||||
|
*/
|
||||||
|
public List<AmtCredential> getAllActiveCredentials() {
|
||||||
|
LambdaQueryWrapper<AmtCredential> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(AmtCredential::getStatus, 1)
|
||||||
|
.orderByDesc(AmtCredential::getIsDefault)
|
||||||
|
.orderByDesc(AmtCredential::getCreatedTime);
|
||||||
|
return amtCredentialMapper.selectList(wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID获取凭证
|
||||||
|
*/
|
||||||
|
public AmtCredential getCredentialById(String credentialId) {
|
||||||
|
return amtCredentialMapper.selectById(credentialId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建凭证
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public AmtCredential createCredential(AmtCredentialDTO dto, String userId) {
|
||||||
|
AmtCredential credential = new AmtCredential();
|
||||||
|
BeanUtils.copyProperties(dto, credential);
|
||||||
|
|
||||||
|
credential.setCredentialId(UUID.randomUUID().toString());
|
||||||
|
credential.setCreatedBy(userId);
|
||||||
|
|
||||||
|
// 如果设置为默认凭证,取消其他凭证的默认状态
|
||||||
|
if (Boolean.TRUE.equals(dto.getIsDefault())) {
|
||||||
|
clearDefaultCredential();
|
||||||
|
}
|
||||||
|
|
||||||
|
amtCredentialMapper.insert(credential);
|
||||||
|
return credential;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新凭证
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public AmtCredential updateCredential(String credentialId, AmtCredentialDTO dto) {
|
||||||
|
AmtCredential credential = amtCredentialMapper.selectById(credentialId);
|
||||||
|
if (credential == null) {
|
||||||
|
throw new RuntimeException("凭证不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
BeanUtils.copyProperties(dto, credential);
|
||||||
|
credential.setCredentialId(credentialId);
|
||||||
|
|
||||||
|
// 如果设置为默认凭证,取消其他凭证的默认状态
|
||||||
|
if (Boolean.TRUE.equals(dto.getIsDefault())) {
|
||||||
|
clearDefaultCredential();
|
||||||
|
}
|
||||||
|
|
||||||
|
amtCredentialMapper.updateById(credential);
|
||||||
|
return credential;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除凭证
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public void deleteCredential(String credentialId) {
|
||||||
|
AmtCredential credential = amtCredentialMapper.selectById(credentialId);
|
||||||
|
if (credential == null) {
|
||||||
|
throw new RuntimeException("凭证不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Boolean.TRUE.equals(credential.getIsDefault())) {
|
||||||
|
throw new RuntimeException("默认凭证不能删除");
|
||||||
|
}
|
||||||
|
|
||||||
|
amtCredentialMapper.deleteById(credentialId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置默认凭证
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public void setDefaultCredential(String credentialId) {
|
||||||
|
AmtCredential credential = amtCredentialMapper.selectById(credentialId);
|
||||||
|
if (credential == null) {
|
||||||
|
throw new RuntimeException("凭证不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清除其他默认凭证
|
||||||
|
clearDefaultCredential();
|
||||||
|
|
||||||
|
// 设置当前凭证为默认
|
||||||
|
credential.setIsDefault(true);
|
||||||
|
amtCredentialMapper.updateById(credential);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试凭证连接
|
||||||
|
*/
|
||||||
|
public Map<String, Object> testCredential(String credentialId) {
|
||||||
|
AmtCredential credential = amtCredentialMapper.selectById(credentialId);
|
||||||
|
if (credential == null) {
|
||||||
|
throw new RuntimeException("凭证不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
|
||||||
|
// 模拟测试连接(实际应该调用 AMT SDK)
|
||||||
|
try {
|
||||||
|
// 这里应该实际测试 AMT 连接
|
||||||
|
// 暂时返回模拟结果
|
||||||
|
result.put("success", true);
|
||||||
|
result.put("message", "凭证测试成功");
|
||||||
|
result.put("details", "用户名: " + credential.getUsername());
|
||||||
|
} catch (Exception e) {
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "凭证测试失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量测试凭证
|
||||||
|
*/
|
||||||
|
public Map<String, Object> batchTestCredentials(List<String> credentialIds) {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
int successCount = 0;
|
||||||
|
int failCount = 0;
|
||||||
|
|
||||||
|
for (String credentialId : credentialIds) {
|
||||||
|
try {
|
||||||
|
Map<String, Object> testResult = testCredential(credentialId);
|
||||||
|
if (Boolean.TRUE.equals(testResult.get("success"))) {
|
||||||
|
successCount++;
|
||||||
|
} else {
|
||||||
|
failCount++;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
failCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.put("total", credentialIds.size());
|
||||||
|
result.put("success", successCount);
|
||||||
|
result.put("fail", failCount);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除所有默认凭证标记
|
||||||
|
*/
|
||||||
|
private void clearDefaultCredential() {
|
||||||
|
LambdaQueryWrapper<AmtCredential> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(AmtCredential::getIsDefault, true);
|
||||||
|
|
||||||
|
List<AmtCredential> defaultCredentials = amtCredentialMapper.selectList(wrapper);
|
||||||
|
for (AmtCredential cred : defaultCredentials) {
|
||||||
|
cred.setIsDefault(false);
|
||||||
|
amtCredentialMapper.updateById(cred);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
-- 创建 AMT 凭证管理表
|
||||||
|
USE soybean_admin;
|
||||||
|
|
||||||
|
-- 删除旧表(如果存在)
|
||||||
|
DROP TABLE IF EXISTS amt_credential;
|
||||||
|
|
||||||
|
-- 创建 AMT 凭证表
|
||||||
|
CREATE TABLE amt_credential (
|
||||||
|
credential_id VARCHAR(50) PRIMARY KEY COMMENT '凭证ID',
|
||||||
|
credential_name VARCHAR(100) NOT NULL COMMENT '凭证名称',
|
||||||
|
username VARCHAR(100) NOT NULL COMMENT 'AMT用户名',
|
||||||
|
password VARCHAR(255) NOT NULL COMMENT 'AMT密码(加密存储)',
|
||||||
|
description VARCHAR(500) COMMENT '描述',
|
||||||
|
is_default TINYINT(1) DEFAULT 0 COMMENT '是否默认凭证',
|
||||||
|
status TINYINT(1) DEFAULT 1 COMMENT '状态:1-启用,0-禁用',
|
||||||
|
created_by VARCHAR(50) COMMENT '创建人',
|
||||||
|
created_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AMT凭证管理表';
|
||||||
|
|
||||||
|
-- 插入默认凭证
|
||||||
|
INSERT INTO amt_credential (credential_id, credential_name, username, password, description, is_default, status, created_by)
|
||||||
|
VALUES
|
||||||
|
('default_admin', '默认管理员凭证', 'admin', 'admin', 'Intel AMT 默认管理员账户', 1, 1, 'system'),
|
||||||
|
('default_user', '默认用户凭证', 'user', 'user123', 'Intel AMT 默认用户账户', 0, 1, 'system');
|
||||||
|
|
||||||
|
-- 验证
|
||||||
|
SELECT * FROM amt_credential;
|
||||||
20
init_amt_credential_table.bat
Normal file
20
init_amt_credential_table.bat
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
@echo off
|
||||||
|
chcp 65001 >nul
|
||||||
|
echo ========================================
|
||||||
|
echo 初始化 AMT 凭证管理表
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
|
||||||
|
mysql -uroot -proot -hlocalhost -P3306 < backend/src/main/resources/sql/create_amt_credential_table.sql
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ========================================
|
||||||
|
echo 初始化完成!
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 下一步操作:
|
||||||
|
echo 1. 重启后端服务
|
||||||
|
echo 2. 访问"系统设置 > AMT设置"页面
|
||||||
|
echo 3. 开始管理 AMT 凭证
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
36
rebuild_and_start_backend.bat
Normal file
36
rebuild_and_start_backend.bat
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
@echo off
|
||||||
|
chcp 65001 >nul
|
||||||
|
echo ========================================
|
||||||
|
echo 重新编译并启动后端服务
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
|
||||||
|
cd backend
|
||||||
|
|
||||||
|
echo 1. 清理旧的编译文件...
|
||||||
|
call mvn clean
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo 2. 编译项目...
|
||||||
|
call mvn compile
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo 3. 打包项目...
|
||||||
|
call mvn package -DskipTests
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo 4. 启动服务...
|
||||||
|
echo 请在新窗口中运行: cd backend && mvn spring-boot:run
|
||||||
|
echo.
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
echo ========================================
|
||||||
|
echo 编译完成!
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
echo 下一步:
|
||||||
|
echo 1. 在新的命令行窗口运行: cd backend && mvn spring-boot:run
|
||||||
|
echo 2. 或者运行: start_backend.bat
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
125
src/service/api/amt.ts
Normal file
125
src/service/api/amt.ts
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
import { request } from '../request';
|
||||||
|
|
||||||
|
/** AMT 凭证 DTO */
|
||||||
|
export interface AmtCredential {
|
||||||
|
credentialId?: string;
|
||||||
|
credentialName: string;
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
description?: string;
|
||||||
|
isDefault?: boolean;
|
||||||
|
status?: number;
|
||||||
|
createdBy?: string;
|
||||||
|
createdTime?: string;
|
||||||
|
updatedTime?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 分页查询参数 */
|
||||||
|
export interface AmtCredentialQuery {
|
||||||
|
page?: number;
|
||||||
|
size?: number;
|
||||||
|
credentialName?: string;
|
||||||
|
status?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 分页响应 */
|
||||||
|
export interface AmtCredentialPageResponse {
|
||||||
|
records: AmtCredential[];
|
||||||
|
total: number;
|
||||||
|
current: number;
|
||||||
|
size: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取凭证列表(分页)
|
||||||
|
*/
|
||||||
|
export function fetchAmtCredentialList(params: AmtCredentialQuery) {
|
||||||
|
return request<AmtCredentialPageResponse>({
|
||||||
|
url: '/amt/credential/list',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有启用的凭证
|
||||||
|
*/
|
||||||
|
export function fetchAllActiveCredentials() {
|
||||||
|
return request<AmtCredential[]>({
|
||||||
|
url: '/amt/credential/all',
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID获取凭证
|
||||||
|
*/
|
||||||
|
export function fetchAmtCredentialById(credentialId: string) {
|
||||||
|
return request<AmtCredential>({
|
||||||
|
url: `/amt/credential/${credentialId}`,
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建凭证
|
||||||
|
*/
|
||||||
|
export function createAmtCredential(data: AmtCredential) {
|
||||||
|
return request<AmtCredential>({
|
||||||
|
url: '/amt/credential',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新凭证
|
||||||
|
*/
|
||||||
|
export function updateAmtCredential(credentialId: string, data: AmtCredential) {
|
||||||
|
return request<AmtCredential>({
|
||||||
|
url: `/amt/credential/${credentialId}`,
|
||||||
|
method: 'put',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除凭证
|
||||||
|
*/
|
||||||
|
export function deleteAmtCredential(credentialId: string) {
|
||||||
|
return request({
|
||||||
|
url: `/amt/credential/${credentialId}`,
|
||||||
|
method: 'delete'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置默认凭证
|
||||||
|
*/
|
||||||
|
export function setDefaultCredential(credentialId: string) {
|
||||||
|
return request({
|
||||||
|
url: `/amt/credential/${credentialId}/default`,
|
||||||
|
method: 'put'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试凭证连接
|
||||||
|
*/
|
||||||
|
export function testAmtCredential(credentialId: string) {
|
||||||
|
return request<{ success: boolean; message: string; details?: string }>({
|
||||||
|
url: `/amt/credential/${credentialId}/test`,
|
||||||
|
method: 'post'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量测试凭证
|
||||||
|
*/
|
||||||
|
export function batchTestCredentials(credentialIds: string[]) {
|
||||||
|
return request<{ total: number; success: number; fail: number }>({
|
||||||
|
url: '/amt/credential/batch-test',
|
||||||
|
method: 'post',
|
||||||
|
data: credentialIds
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -4,3 +4,4 @@ export * from './user';
|
|||||||
export * from './role';
|
export * from './role';
|
||||||
export * from './permission';
|
export * from './permission';
|
||||||
export * from './device';
|
export * from './device';
|
||||||
|
export * from './amt';
|
||||||
|
|||||||
2
src/typings/components.d.ts
vendored
2
src/typings/components.d.ts
vendored
@ -66,6 +66,7 @@ declare module 'vue' {
|
|||||||
IconMdiShieldAccount: typeof import('~icons/mdi/shield-account')['default']
|
IconMdiShieldAccount: typeof import('~icons/mdi/shield-account')['default']
|
||||||
IconMdiShieldCrown: typeof import('~icons/mdi/shield-crown')['default']
|
IconMdiShieldCrown: typeof import('~icons/mdi/shield-crown')['default']
|
||||||
IconMdiShieldStar: typeof import('~icons/mdi/shield-star')['default']
|
IconMdiShieldStar: typeof import('~icons/mdi/shield-star')['default']
|
||||||
|
IconMdiTestTube: typeof import('~icons/mdi/test-tube')['default']
|
||||||
IconMdiViewGrid: typeof import('~icons/mdi/view-grid')['default']
|
IconMdiViewGrid: typeof import('~icons/mdi/view-grid')['default']
|
||||||
IconMdiViewList: typeof import('~icons/mdi/view-list')['default']
|
IconMdiViewList: typeof import('~icons/mdi/view-list')['default']
|
||||||
IconMdiWrench: typeof import('~icons/mdi/wrench')['default']
|
IconMdiWrench: typeof import('~icons/mdi/wrench')['default']
|
||||||
@ -203,6 +204,7 @@ declare global {
|
|||||||
const IconMdiShieldAccount: typeof import('~icons/mdi/shield-account')['default']
|
const IconMdiShieldAccount: typeof import('~icons/mdi/shield-account')['default']
|
||||||
const IconMdiShieldCrown: typeof import('~icons/mdi/shield-crown')['default']
|
const IconMdiShieldCrown: typeof import('~icons/mdi/shield-crown')['default']
|
||||||
const IconMdiShieldStar: typeof import('~icons/mdi/shield-star')['default']
|
const IconMdiShieldStar: typeof import('~icons/mdi/shield-star')['default']
|
||||||
|
const IconMdiTestTube: typeof import('~icons/mdi/test-tube')['default']
|
||||||
const IconMdiViewGrid: typeof import('~icons/mdi/view-grid')['default']
|
const IconMdiViewGrid: typeof import('~icons/mdi/view-grid')['default']
|
||||||
const IconMdiViewList: typeof import('~icons/mdi/view-list')['default']
|
const IconMdiViewList: typeof import('~icons/mdi/view-list')['default']
|
||||||
const IconMdiWrench: typeof import('~icons/mdi/wrench')['default']
|
const IconMdiWrench: typeof import('~icons/mdi/wrench')['default']
|
||||||
|
|||||||
@ -1,28 +1,361 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="h-full">
|
<div class="h-full p-16px">
|
||||||
<n-card title="AMT设置" :bordered="false" class="h-full rounded-8px shadow-sm">
|
|
||||||
<n-space vertical :size="16">
|
<n-space vertical :size="16">
|
||||||
<n-alert type="info" title="功能说明">
|
<!-- 功能说明 -->
|
||||||
Intel AMT (Active Management Technology) 配置
|
<n-card title="AMT 批量管理凭证" :bordered="false" class="rounded-8px shadow-sm">
|
||||||
|
<n-alert type="info" title="功能说明" class="mb-16px">
|
||||||
|
管理 Intel AMT 设备的登录凭证,支持批量测试和应用到设备
|
||||||
</n-alert>
|
</n-alert>
|
||||||
<n-form label-placement="left" label-width="120px">
|
|
||||||
<n-form-item label="AMT服务器">
|
<!-- 操作按钮 -->
|
||||||
<n-input placeholder="请输入AMT服务器地址" />
|
<n-space class="mb-16px">
|
||||||
|
<n-button type="primary" @click="handleAdd">
|
||||||
|
<template #icon><icon-mdi-plus /></template>
|
||||||
|
添加凭证
|
||||||
|
</n-button>
|
||||||
|
<n-button @click="handleBatchTest" :disabled="checkedRowKeys.length === 0">
|
||||||
|
<template #icon><icon-mdi-test-tube /></template>
|
||||||
|
批量测试
|
||||||
|
</n-button>
|
||||||
|
<n-button @click="loadData">
|
||||||
|
<template #icon><icon-mdi-refresh /></template>
|
||||||
|
刷新
|
||||||
|
</n-button>
|
||||||
|
</n-space>
|
||||||
|
|
||||||
|
<!-- 凭证列表 -->
|
||||||
|
<n-data-table
|
||||||
|
:columns="columns"
|
||||||
|
:data="dataSource"
|
||||||
|
:loading="loading"
|
||||||
|
:pagination="pagination"
|
||||||
|
:row-key="(row: AmtCredential) => row.credentialId!"
|
||||||
|
@update:checked-row-keys="handleCheck"
|
||||||
|
/>
|
||||||
|
</n-card>
|
||||||
|
</n-space>
|
||||||
|
|
||||||
|
<!-- 添加/编辑凭证弹窗 -->
|
||||||
|
<n-modal
|
||||||
|
v-model:show="modalVisible"
|
||||||
|
:title="modalTitle"
|
||||||
|
preset="card"
|
||||||
|
class="w-600px"
|
||||||
|
:segmented="{ content: true }"
|
||||||
|
>
|
||||||
|
<n-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="formModel"
|
||||||
|
:rules="formRules"
|
||||||
|
label-placement="left"
|
||||||
|
label-width="120px"
|
||||||
|
>
|
||||||
|
<n-form-item label="凭证名称" path="credentialName">
|
||||||
|
<n-input v-model:value="formModel.credentialName" placeholder="请输入凭证名称" />
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
<n-form-item label="端口">
|
<n-form-item label="用户名" path="username">
|
||||||
<n-input-number placeholder="16992" class="w-full" />
|
<n-input v-model:value="formModel.username" placeholder="请输入AMT用户名" />
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
<n-form-item label="启用状态">
|
<n-form-item label="密码" path="password">
|
||||||
<n-switch />
|
<n-input
|
||||||
|
v-model:value="formModel.password"
|
||||||
|
type="password"
|
||||||
|
show-password-on="click"
|
||||||
|
placeholder="请输入AMT密码"
|
||||||
|
/>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="描述" path="description">
|
||||||
|
<n-input
|
||||||
|
v-model:value="formModel.description"
|
||||||
|
type="textarea"
|
||||||
|
placeholder="请输入描述信息"
|
||||||
|
:rows="3"
|
||||||
|
/>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="设为默认" path="isDefault">
|
||||||
|
<n-switch v-model:value="formModel.isDefault" />
|
||||||
|
<span class="ml-8px text-gray-500">默认凭证将优先用于新设备</span>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="状态" path="status">
|
||||||
|
<n-switch :value="formModel.status === 1" @update:value="(val) => formModel.status = val ? 1 : 0" />
|
||||||
|
<span class="ml-8px text-gray-500">{{ formModel.status === 1 ? '启用' : '禁用' }}</span>
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
</n-form>
|
</n-form>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<n-space justify="end">
|
||||||
|
<n-button @click="modalVisible = false">取消</n-button>
|
||||||
|
<n-button type="primary" @click="handleSubmit" :loading="submitLoading">
|
||||||
|
确定
|
||||||
|
</n-button>
|
||||||
</n-space>
|
</n-space>
|
||||||
</n-card>
|
</template>
|
||||||
|
</n-modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="tsx">
|
||||||
|
import { ref, reactive, onMounted } from 'vue';
|
||||||
|
import type { DataTableColumns, FormInst, FormRules } from 'naive-ui';
|
||||||
|
import { NButton, NSpace, NTag, NPopconfirm } from 'naive-ui';
|
||||||
|
import type { AmtCredential } from '@/service/api/amt';
|
||||||
|
import {
|
||||||
|
fetchAmtCredentialList,
|
||||||
|
createAmtCredential,
|
||||||
|
updateAmtCredential,
|
||||||
|
deleteAmtCredential,
|
||||||
|
setDefaultCredential,
|
||||||
|
testAmtCredential,
|
||||||
|
batchTestCredentials
|
||||||
|
} from '@/service/api/amt';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'SystemAmt'
|
name: 'SystemAmt'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const loading = ref(false);
|
||||||
|
const dataSource = ref<AmtCredential[]>([]);
|
||||||
|
const checkedRowKeys = ref<string[]>([]);
|
||||||
|
|
||||||
|
// 分页
|
||||||
|
const pagination = reactive({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
itemCount: 0,
|
||||||
|
showSizePicker: true,
|
||||||
|
pageSizes: [10, 20, 50],
|
||||||
|
onChange: (page: number) => {
|
||||||
|
pagination.page = page;
|
||||||
|
loadData();
|
||||||
|
},
|
||||||
|
onUpdatePageSize: (pageSize: number) => {
|
||||||
|
pagination.pageSize = pageSize;
|
||||||
|
pagination.page = 1;
|
||||||
|
loadData();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表格列定义
|
||||||
|
const columns: DataTableColumns<AmtCredential> = [
|
||||||
|
{ type: 'selection' },
|
||||||
|
{
|
||||||
|
title: '凭证名称',
|
||||||
|
key: 'credentialName',
|
||||||
|
width: 180,
|
||||||
|
ellipsis: { tooltip: true }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '用户名',
|
||||||
|
key: 'username',
|
||||||
|
width: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '密码',
|
||||||
|
key: 'password',
|
||||||
|
width: 120,
|
||||||
|
render: () => '••••••••'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '描述',
|
||||||
|
key: 'description',
|
||||||
|
ellipsis: { tooltip: true }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '默认',
|
||||||
|
key: 'isDefault',
|
||||||
|
width: 80,
|
||||||
|
render: (row) => (
|
||||||
|
<NTag type={row.isDefault ? 'success' : 'default'} size="small">
|
||||||
|
{row.isDefault ? '是' : '否'}
|
||||||
|
</NTag>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
key: 'status',
|
||||||
|
width: 80,
|
||||||
|
render: (row) => (
|
||||||
|
<NTag type={row.status === 1 ? 'success' : 'error'} size="small">
|
||||||
|
{row.status === 1 ? '启用' : '禁用'}
|
||||||
|
</NTag>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'actions',
|
||||||
|
width: 280,
|
||||||
|
fixed: 'right',
|
||||||
|
render: (row) => (
|
||||||
|
<NSpace>
|
||||||
|
<NButton size="small" onClick={() => handleTest(row.credentialId!)}>
|
||||||
|
测试
|
||||||
|
</NButton>
|
||||||
|
{!row.isDefault && (
|
||||||
|
<NButton size="small" onClick={() => handleSetDefault(row.credentialId!)}>
|
||||||
|
设为默认
|
||||||
|
</NButton>
|
||||||
|
)}
|
||||||
|
<NButton size="small" onClick={() => handleEdit(row)}>
|
||||||
|
编辑
|
||||||
|
</NButton>
|
||||||
|
<NPopconfirm onPositiveClick={() => handleDelete(row.credentialId!)}>
|
||||||
|
{{
|
||||||
|
default: () => '确定删除此凭证吗?',
|
||||||
|
trigger: () => (
|
||||||
|
<NButton size="small" type="error" disabled={row.isDefault}>
|
||||||
|
删除
|
||||||
|
</NButton>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</NPopconfirm>
|
||||||
|
</NSpace>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// 表单
|
||||||
|
const formRef = ref<FormInst | null>(null);
|
||||||
|
const modalVisible = ref(false);
|
||||||
|
const modalTitle = ref('');
|
||||||
|
const submitLoading = ref(false);
|
||||||
|
const editingId = ref<string | null>(null);
|
||||||
|
|
||||||
|
const formModel = reactive<AmtCredential>({
|
||||||
|
credentialName: '',
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
description: '',
|
||||||
|
isDefault: false,
|
||||||
|
status: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
const formRules: FormRules = {
|
||||||
|
credentialName: [{ required: true, message: '请输入凭证名称', trigger: 'blur' }],
|
||||||
|
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
|
||||||
|
password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
|
||||||
|
};
|
||||||
|
|
||||||
|
// 加载数据
|
||||||
|
async function loadData() {
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const { data } = await fetchAmtCredentialList({
|
||||||
|
page: pagination.page,
|
||||||
|
size: pagination.pageSize
|
||||||
|
});
|
||||||
|
dataSource.value = data.records;
|
||||||
|
pagination.itemCount = data.total;
|
||||||
|
} catch (error) {
|
||||||
|
window.$message?.error('加载数据失败');
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加
|
||||||
|
function handleAdd() {
|
||||||
|
modalTitle.value = '添加凭证';
|
||||||
|
editingId.value = null;
|
||||||
|
Object.assign(formModel, {
|
||||||
|
credentialName: '',
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
description: '',
|
||||||
|
isDefault: false,
|
||||||
|
status: 1
|
||||||
|
});
|
||||||
|
modalVisible.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑
|
||||||
|
function handleEdit(row: AmtCredential) {
|
||||||
|
modalTitle.value = '编辑凭证';
|
||||||
|
editingId.value = row.credentialId!;
|
||||||
|
Object.assign(formModel, row);
|
||||||
|
modalVisible.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交
|
||||||
|
async function handleSubmit() {
|
||||||
|
await formRef.value?.validate();
|
||||||
|
submitLoading.value = true;
|
||||||
|
try {
|
||||||
|
if (editingId.value) {
|
||||||
|
await updateAmtCredential(editingId.value, formModel);
|
||||||
|
window.$message?.success('更新成功');
|
||||||
|
} else {
|
||||||
|
await createAmtCredential(formModel);
|
||||||
|
window.$message?.success('创建成功');
|
||||||
|
}
|
||||||
|
modalVisible.value = false;
|
||||||
|
loadData();
|
||||||
|
} catch (error: any) {
|
||||||
|
window.$message?.error(error.message || '操作失败');
|
||||||
|
} finally {
|
||||||
|
submitLoading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除
|
||||||
|
async function handleDelete(credentialId: string) {
|
||||||
|
try {
|
||||||
|
await deleteAmtCredential(credentialId);
|
||||||
|
window.$message?.success('删除成功');
|
||||||
|
loadData();
|
||||||
|
} catch (error: any) {
|
||||||
|
window.$message?.error(error.message || '删除失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设为默认
|
||||||
|
async function handleSetDefault(credentialId: string) {
|
||||||
|
try {
|
||||||
|
await setDefaultCredential(credentialId);
|
||||||
|
window.$message?.success('设置成功');
|
||||||
|
loadData();
|
||||||
|
} catch (error: any) {
|
||||||
|
window.$message?.error(error.message || '设置失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试连接
|
||||||
|
async function handleTest(credentialId: string) {
|
||||||
|
const loadingMsg = window.$message?.loading('正在测试连接...', { duration: 0 });
|
||||||
|
try {
|
||||||
|
const { data } = await testAmtCredential(credentialId);
|
||||||
|
loadingMsg?.destroy();
|
||||||
|
if (data.success) {
|
||||||
|
window.$message?.success(data.message);
|
||||||
|
} else {
|
||||||
|
window.$message?.error(data.message);
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
loadingMsg?.destroy();
|
||||||
|
window.$message?.error(error.message || '测试失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量测试
|
||||||
|
async function handleBatchTest() {
|
||||||
|
const loadingMsg = window.$message?.loading('正在批量测试...', { duration: 0 });
|
||||||
|
try {
|
||||||
|
const { data } = await batchTestCredentials(checkedRowKeys.value);
|
||||||
|
loadingMsg?.destroy();
|
||||||
|
window.$message?.success(
|
||||||
|
`测试完成:成功 ${data.success} 个,失败 ${data.fail} 个`
|
||||||
|
);
|
||||||
|
} catch (error: any) {
|
||||||
|
loadingMsg?.destroy();
|
||||||
|
window.$message?.error(error.message || '批量测试失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择
|
||||||
|
function handleCheck(keys: string[]) {
|
||||||
|
checkedRowKeys.value = keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadData();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
16
test_amt_api.bat
Normal file
16
test_amt_api.bat
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
@echo off
|
||||||
|
chcp 65001 >nul
|
||||||
|
echo ========================================
|
||||||
|
echo 测试 AMT API 接口
|
||||||
|
echo ========================================
|
||||||
|
echo.
|
||||||
|
|
||||||
|
echo 测试获取凭证列表...
|
||||||
|
curl -X GET "http://localhost:8080/api/amt/credential/list?page=1&size=10" -H "Content-Type: application/json"
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo.
|
||||||
|
echo ========================================
|
||||||
|
echo 测试完成
|
||||||
|
echo ========================================
|
||||||
|
pause
|
||||||
Loading…
x
Reference in New Issue
Block a user