Compare commits
No commits in common. "019634423996f1db8d87e2bbd61d0d01c7cfd626" and "8acd7b0ab6d472e1a45eeac4ab4b5db62b8fbff4" have entirely different histories.
0196344239
...
8acd7b0ab6
@ -105,14 +105,6 @@ export const deviceApi = {
|
|||||||
data: data,
|
data: data,
|
||||||
showSuccessMessage: true
|
showSuccessMessage: true
|
||||||
})
|
})
|
||||||
},
|
|
||||||
|
|
||||||
// 批量获取/更新设备 UUID
|
|
||||||
batchFetchUuid(deviceIds: number[]) {
|
|
||||||
return request.post({
|
|
||||||
url: '/api/devices/batch-fetch-uuid',
|
|
||||||
data: { deviceIds }
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,14 +407,6 @@ export const osDeviceApi = {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
// 批量 AMT 绑定
|
|
||||||
batchBindAmt(deviceIds: number[]) {
|
|
||||||
return request.post({
|
|
||||||
url: '/api/os-devices/batch-bind-amt',
|
|
||||||
data: { deviceIds }
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
// 设置 Windows 登录凭据
|
// 设置 Windows 登录凭据
|
||||||
setCredentials(id: number, credentials: { username: string; password: string }) {
|
setCredentials(id: number, credentials: { username: string; password: string }) {
|
||||||
return request.put({
|
return request.put({
|
||||||
|
|||||||
@ -35,10 +35,6 @@
|
|||||||
<span v-else class="hint-text">请勾选设备进行操作</span>
|
<span v-else class="hint-text">请勾选设备进行操作</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="batch-actions">
|
<div class="batch-actions">
|
||||||
<ElButton type="primary" :disabled="selectedDevices.length === 0" :loading="batchFetchingUuid" @click="handleBatchFetchUuid">
|
|
||||||
<el-icon><Connection /></el-icon>
|
|
||||||
获取UUID
|
|
||||||
</ElButton>
|
|
||||||
<ElButton type="info" :disabled="selectedDevices.length === 0" @click="handleBatchSetCredentials">
|
<ElButton type="info" :disabled="selectedDevices.length === 0" @click="handleBatchSetCredentials">
|
||||||
<el-icon><Key /></el-icon>
|
<el-icon><Key /></el-icon>
|
||||||
配置AMT账号
|
配置AMT账号
|
||||||
@ -175,7 +171,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, onUnmounted } from 'vue'
|
import { ref, onMounted, onUnmounted } from 'vue'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { Search, Refresh, ArrowDown, VideoPlay, VideoPause, RefreshRight, CircleClose, Delete, Lightning, Key, Connection } from '@element-plus/icons-vue'
|
import { Search, Refresh, ArrowDown, VideoPlay, VideoPause, RefreshRight, CircleClose, Delete, Lightning, Key } from '@element-plus/icons-vue'
|
||||||
import { deviceApi, powerApi, hardwareApi } from '@/api/amt'
|
import { deviceApi, powerApi, hardwareApi } from '@/api/amt'
|
||||||
import HardwareInfoModal from './modules/hardware-info-modal.vue'
|
import HardwareInfoModal from './modules/hardware-info-modal.vue'
|
||||||
import RemoteDesktopModal from './modules/remote-desktop-modal.vue'
|
import RemoteDesktopModal from './modules/remote-desktop-modal.vue'
|
||||||
@ -195,7 +191,6 @@ const selectedDevice = ref<any>(null)
|
|||||||
const credentialsTargetDevices = ref<any[]>([])
|
const credentialsTargetDevices = ref<any[]>([])
|
||||||
const credentialsForm = ref({ username: '', password: '' })
|
const credentialsForm = ref({ username: '', password: '' })
|
||||||
const savingCredentials = ref(false)
|
const savingCredentials = ref(false)
|
||||||
const batchFetchingUuid = ref(false)
|
|
||||||
|
|
||||||
let statusCheckInterval: number | null = null
|
let statusCheckInterval: number | null = null
|
||||||
|
|
||||||
@ -398,41 +393,6 @@ const handleFetchUuid = async (device: any) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 批量获取 UUID
|
|
||||||
const handleBatchFetchUuid = async () => {
|
|
||||||
if (selectedDevices.value.length === 0) return
|
|
||||||
|
|
||||||
batchFetchingUuid.value = true
|
|
||||||
try {
|
|
||||||
const deviceIds = selectedDevices.value.map(d => d.id)
|
|
||||||
const response = await deviceApi.batchFetchUuid(deviceIds)
|
|
||||||
|
|
||||||
// 更新本地数据
|
|
||||||
if (response.results) {
|
|
||||||
for (const result of response.results) {
|
|
||||||
if (result.success && result.uuid) {
|
|
||||||
const device = devices.value.find(d => d.id === result.deviceId)
|
|
||||||
if (device) {
|
|
||||||
device.systemUuid = result.uuid
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.successCount > 0 && response.failCount === 0) {
|
|
||||||
ElMessage.success(`成功获取 ${response.successCount} 台设备的 UUID`)
|
|
||||||
} else if (response.successCount > 0) {
|
|
||||||
ElMessage.warning(`成功 ${response.successCount} 台,失败 ${response.failCount} 台`)
|
|
||||||
} else {
|
|
||||||
ElMessage.error('获取 UUID 失败')
|
|
||||||
}
|
|
||||||
} catch (error: any) {
|
|
||||||
ElMessage.error('批量获取 UUID 失败: ' + (error.message || '未知错误'))
|
|
||||||
} finally {
|
|
||||||
batchFetchingUuid.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 电源操作
|
// 电源操作
|
||||||
const handleBatchPowerCommand = async (command: string) => {
|
const handleBatchPowerCommand = async (command: string) => {
|
||||||
|
|||||||
@ -35,10 +35,6 @@
|
|||||||
<span v-else class="hint-text">请勾选设备进行操作</span>
|
<span v-else class="hint-text">请勾选设备进行操作</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="batch-actions">
|
<div class="batch-actions">
|
||||||
<ElButton type="primary" :disabled="selectedDevices.length === 0" :loading="batchBindingAmt" @click="handleBatchBindAmt">
|
|
||||||
<el-icon><Link /></el-icon>
|
|
||||||
AMT绑定
|
|
||||||
</ElButton>
|
|
||||||
<ElButton type="info" :disabled="selectedDevices.length === 0" @click="handleBatchSetCredentials">
|
<ElButton type="info" :disabled="selectedDevices.length === 0" @click="handleBatchSetCredentials">
|
||||||
<el-icon><Key /></el-icon>
|
<el-icon><Key /></el-icon>
|
||||||
配置Windows账号
|
配置Windows账号
|
||||||
@ -175,7 +171,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { Search, Refresh, ArrowDown, VideoPlay, VideoPause, RefreshRight, CircleClose, Delete, Key, Link } from '@element-plus/icons-vue'
|
import { Search, Refresh, ArrowDown, VideoPlay, VideoPause, RefreshRight, CircleClose, Delete, Key } from '@element-plus/icons-vue'
|
||||||
import { osDeviceApi, powerApi } from '@/api/amt'
|
import { osDeviceApi, powerApi } from '@/api/amt'
|
||||||
import RemoteDesktopModal from '@/views/amt/modules/remote-desktop-modal.vue'
|
import RemoteDesktopModal from '@/views/amt/modules/remote-desktop-modal.vue'
|
||||||
|
|
||||||
@ -200,7 +196,6 @@ const showCredentialsDialog = ref(false)
|
|||||||
const credentialsTargetDevices = ref<any[]>([])
|
const credentialsTargetDevices = ref<any[]>([])
|
||||||
const credentialsForm = ref({ username: '', password: '' })
|
const credentialsForm = ref({ username: '', password: '' })
|
||||||
const savingCredentials = ref(false)
|
const savingCredentials = ref(false)
|
||||||
const batchBindingAmt = ref(false)
|
|
||||||
|
|
||||||
let statusCheckInterval: number | null = null
|
let statusCheckInterval: number | null = null
|
||||||
|
|
||||||
@ -313,35 +308,6 @@ const handleBatchSetCredentials = () => {
|
|||||||
showCredentialsDialog.value = true
|
showCredentialsDialog.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// 批量 AMT 绑定
|
|
||||||
const handleBatchBindAmt = async () => {
|
|
||||||
if (selectedDevices.value.length === 0) return
|
|
||||||
|
|
||||||
batchBindingAmt.value = true
|
|
||||||
try {
|
|
||||||
const deviceIds = selectedDevices.value.map(d => d.id)
|
|
||||||
const response = await osDeviceApi.batchBindAmt(deviceIds)
|
|
||||||
|
|
||||||
// 刷新设备列表以获取最新的绑定状态
|
|
||||||
await fetchDevices()
|
|
||||||
|
|
||||||
if (response.successCount > 0 && response.failCount === 0) {
|
|
||||||
ElMessage.success(`成功绑定 ${response.successCount} 台设备`)
|
|
||||||
} else if (response.successCount > 0) {
|
|
||||||
// 显示详细结果
|
|
||||||
const failedDevices = response.results.filter((r: any) => !r.success)
|
|
||||||
const failedIps = failedDevices.map((r: any) => r.ipAddress).join(', ')
|
|
||||||
ElMessage.warning(`成功 ${response.successCount} 台,失败 ${response.failCount} 台\n失败设备: ${failedIps}`)
|
|
||||||
} else {
|
|
||||||
ElMessage.error('绑定失败,请确保设备有相同的 UUID 或 IP 地址')
|
|
||||||
}
|
|
||||||
} catch (error: any) {
|
|
||||||
ElMessage.error('批量绑定失败: ' + (error.message || '未知错误'))
|
|
||||||
} finally {
|
|
||||||
batchBindingAmt.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const saveCredentials = async () => {
|
const saveCredentials = async () => {
|
||||||
if (!credentialsForm.value.username) {
|
if (!credentialsForm.value.username) {
|
||||||
ElMessage.warning('请输入用户名')
|
ElMessage.warning('请输入用户名')
|
||||||
|
|||||||
@ -235,76 +235,6 @@ public class DevicesController : ControllerBase
|
|||||||
return Ok(ApiResponse<object>.Success(null, "AMT凭据设置成功"));
|
return Ok(ApiResponse<object>.Success(null, "AMT凭据设置成功"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 批量获取/更新设备 UUID
|
|
||||||
/// </summary>
|
|
||||||
[HttpPost("batch-fetch-uuid")]
|
|
||||||
public async Task<ActionResult<ApiResponse<BatchFetchUuidResponse>>> BatchFetchUuid([FromBody] BatchFetchUuidRequest request)
|
|
||||||
{
|
|
||||||
if (request.DeviceIds == null || request.DeviceIds.Count == 0)
|
|
||||||
{
|
|
||||||
return Ok(ApiResponse<BatchFetchUuidResponse>.Fail(400, "请选择要获取 UUID 的设备"));
|
|
||||||
}
|
|
||||||
|
|
||||||
var results = new List<FetchUuidResult>();
|
|
||||||
var hardwareService = HttpContext.RequestServices.GetRequiredService<IHardwareInfoService>();
|
|
||||||
|
|
||||||
foreach (var deviceId in request.DeviceIds)
|
|
||||||
{
|
|
||||||
var result = new FetchUuidResult { DeviceId = deviceId };
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var device = await _context.AmtDevices.FindAsync(deviceId);
|
|
||||||
if (device == null)
|
|
||||||
{
|
|
||||||
result.Success = false;
|
|
||||||
result.Error = "设备不存在";
|
|
||||||
results.Add(result);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.IpAddress = device.IpAddress;
|
|
||||||
|
|
||||||
// 获取硬件信息(强制刷新)
|
|
||||||
var hardwareInfo = await hardwareService.GetHardwareInfoAsync(deviceId, true);
|
|
||||||
|
|
||||||
if (hardwareInfo?.SystemInfo?.Uuid != null)
|
|
||||||
{
|
|
||||||
device.SystemUuid = hardwareInfo.SystemInfo.Uuid;
|
|
||||||
await _context.SaveChangesAsync();
|
|
||||||
|
|
||||||
result.Success = true;
|
|
||||||
result.Uuid = hardwareInfo.SystemInfo.Uuid;
|
|
||||||
_logger.LogInformation("Successfully fetched UUID for device {Ip}: {Uuid}", device.IpAddress, device.SystemUuid);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.Success = false;
|
|
||||||
result.Error = "未能从设备获取 UUID";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
result.Success = false;
|
|
||||||
result.Error = ex.Message;
|
|
||||||
_logger.LogWarning(ex, "Failed to fetch UUID for device {DeviceId}", deviceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
results.Add(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
var successCount = results.Count(r => r.Success);
|
|
||||||
var failCount = results.Count(r => !r.Success);
|
|
||||||
|
|
||||||
return Ok(ApiResponse<BatchFetchUuidResponse>.Success(new BatchFetchUuidResponse
|
|
||||||
{
|
|
||||||
Results = results,
|
|
||||||
SuccessCount = successCount,
|
|
||||||
FailCount = failCount
|
|
||||||
}, $"成功获取 {successCount} 台设备的 UUID,失败 {failCount} 台"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 检测所有设备的在线状态
|
/// 检测所有设备的在线状态
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -537,33 +467,3 @@ public class SetAmtCredentialsRequest
|
|||||||
public string Username { get; set; } = string.Empty;
|
public string Username { get; set; } = string.Empty;
|
||||||
public string Password { get; set; } = string.Empty;
|
public string Password { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 批量获取 UUID 请求
|
|
||||||
/// </summary>
|
|
||||||
public class BatchFetchUuidRequest
|
|
||||||
{
|
|
||||||
public List<long> DeviceIds { get; set; } = new();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 批量获取 UUID 响应
|
|
||||||
/// </summary>
|
|
||||||
public class BatchFetchUuidResponse
|
|
||||||
{
|
|
||||||
public List<FetchUuidResult> Results { get; set; } = new();
|
|
||||||
public int SuccessCount { get; set; }
|
|
||||||
public int FailCount { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 单个设备获取 UUID 结果
|
|
||||||
/// </summary>
|
|
||||||
public class FetchUuidResult
|
|
||||||
{
|
|
||||||
public long DeviceId { get; set; }
|
|
||||||
public string? IpAddress { get; set; }
|
|
||||||
public bool Success { get; set; }
|
|
||||||
public string? Uuid { get; set; }
|
|
||||||
public string? Error { get; set; }
|
|
||||||
}
|
|
||||||
|
|||||||
@ -335,107 +335,6 @@ public class OsDevicesController : ControllerBase
|
|||||||
return Ok(ApiResponse<object>.Success(null, "自动绑定完成"));
|
return Ok(ApiResponse<object>.Success(null, "自动绑定完成"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 批量 AMT 绑定(通过 UUID 匹配)
|
|
||||||
/// </summary>
|
|
||||||
[HttpPost("batch-bind-amt")]
|
|
||||||
public async Task<ActionResult<ApiResponse<BatchBindAmtResponse>>> BatchBindAmt([FromBody] BatchBindAmtRequest request)
|
|
||||||
{
|
|
||||||
if (request.DeviceIds == null || request.DeviceIds.Count == 0)
|
|
||||||
{
|
|
||||||
return Ok(ApiResponse<BatchBindAmtResponse>.Fail(400, "请选择要绑定的设备"));
|
|
||||||
}
|
|
||||||
|
|
||||||
var results = new List<BindAmtResult>();
|
|
||||||
|
|
||||||
// 获取所有 AMT 设备,用于 UUID 匹配
|
|
||||||
var amtDevices = await _context.AmtDevices.ToListAsync();
|
|
||||||
var amtDevicesByUuid = amtDevices
|
|
||||||
.Where(a => !string.IsNullOrEmpty(a.SystemUuid))
|
|
||||||
.ToDictionary(a => a.SystemUuid!.ToUpperInvariant(), a => a);
|
|
||||||
var amtDevicesByIp = amtDevices.ToDictionary(a => a.IpAddress, a => a);
|
|
||||||
|
|
||||||
foreach (var deviceId in request.DeviceIds)
|
|
||||||
{
|
|
||||||
var result = new BindAmtResult { DeviceId = deviceId };
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var osDevice = await _context.OsDevices.FindAsync(deviceId);
|
|
||||||
if (osDevice == null)
|
|
||||||
{
|
|
||||||
result.Success = false;
|
|
||||||
result.Error = "设备不存在";
|
|
||||||
results.Add(result);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.IpAddress = osDevice.IpAddress;
|
|
||||||
result.PreviousAmtDeviceId = osDevice.AmtDeviceId;
|
|
||||||
|
|
||||||
AmtDevice? matchedAmtDevice = null;
|
|
||||||
string matchMethod = "";
|
|
||||||
|
|
||||||
// 优先通过 UUID 匹配
|
|
||||||
if (!string.IsNullOrEmpty(osDevice.SystemUuid))
|
|
||||||
{
|
|
||||||
var uuidKey = osDevice.SystemUuid.ToUpperInvariant();
|
|
||||||
if (amtDevicesByUuid.TryGetValue(uuidKey, out var amtDevice))
|
|
||||||
{
|
|
||||||
matchedAmtDevice = amtDevice;
|
|
||||||
matchMethod = "UUID";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果 UUID 匹配失败,尝试通过 IP 匹配
|
|
||||||
if (matchedAmtDevice == null)
|
|
||||||
{
|
|
||||||
if (amtDevicesByIp.TryGetValue(osDevice.IpAddress, out var amtDevice))
|
|
||||||
{
|
|
||||||
matchedAmtDevice = amtDevice;
|
|
||||||
matchMethod = "IP";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matchedAmtDevice != null)
|
|
||||||
{
|
|
||||||
osDevice.AmtDeviceId = matchedAmtDevice.Id;
|
|
||||||
await _context.SaveChangesAsync();
|
|
||||||
|
|
||||||
result.Success = true;
|
|
||||||
result.AmtDeviceId = matchedAmtDevice.Id;
|
|
||||||
result.AmtDeviceIp = matchedAmtDevice.IpAddress;
|
|
||||||
result.MatchMethod = matchMethod;
|
|
||||||
_logger.LogInformation("Bound OS device {OsIp} to AMT device {AmtIp} via {Method}",
|
|
||||||
osDevice.IpAddress, matchedAmtDevice.IpAddress, matchMethod);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.Success = false;
|
|
||||||
result.Error = "未找到匹配的 AMT 设备(需要相同的 UUID 或 IP)";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
result.Success = false;
|
|
||||||
result.Error = ex.Message;
|
|
||||||
_logger.LogWarning(ex, "Failed to bind AMT for device {DeviceId}", deviceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
results.Add(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
var successCount = results.Count(r => r.Success);
|
|
||||||
var failCount = results.Count(r => !r.Success);
|
|
||||||
|
|
||||||
return Ok(ApiResponse<BatchBindAmtResponse>.Success(new BatchBindAmtResponse
|
|
||||||
{
|
|
||||||
Results = results,
|
|
||||||
SuccessCount = successCount,
|
|
||||||
FailCount = failCount
|
|
||||||
}, $"成功绑定 {successCount} 台设备,失败 {failCount} 台"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置 Windows 登录凭据
|
/// 设置 Windows 登录凭据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -538,36 +437,3 @@ public class WindowsCredentialsRequest
|
|||||||
public string Username { get; set; } = string.Empty;
|
public string Username { get; set; } = string.Empty;
|
||||||
public string Password { get; set; } = string.Empty;
|
public string Password { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 批量 AMT 绑定请求
|
|
||||||
/// </summary>
|
|
||||||
public class BatchBindAmtRequest
|
|
||||||
{
|
|
||||||
public List<long> DeviceIds { get; set; } = new();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 批量 AMT 绑定响应
|
|
||||||
/// </summary>
|
|
||||||
public class BatchBindAmtResponse
|
|
||||||
{
|
|
||||||
public List<BindAmtResult> Results { get; set; } = new();
|
|
||||||
public int SuccessCount { get; set; }
|
|
||||||
public int FailCount { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 单个设备 AMT 绑定结果
|
|
||||||
/// </summary>
|
|
||||||
public class BindAmtResult
|
|
||||||
{
|
|
||||||
public long DeviceId { get; set; }
|
|
||||||
public string? IpAddress { get; set; }
|
|
||||||
public bool Success { get; set; }
|
|
||||||
public long? PreviousAmtDeviceId { get; set; }
|
|
||||||
public long? AmtDeviceId { get; set; }
|
|
||||||
public string? AmtDeviceIp { get; set; }
|
|
||||||
public string? MatchMethod { get; set; }
|
|
||||||
public string? Error { get; set; }
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user