|
|
|
@@ -733,7 +733,7 @@
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue';
|
|
|
|
|
import { ref, reactive, onMounted, onBeforeUnmount, watch, nextTick } from 'vue';
|
|
|
|
|
import { useRouter, useRoute } from 'vue-router';
|
|
|
|
|
import {getUserInfo, userLogin} from "@/api/login.js";
|
|
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
|
|
|
@@ -801,6 +801,92 @@ const route = useRoute();
|
|
|
|
|
const vmInfo = ref({});
|
|
|
|
|
const loading = ref(false);
|
|
|
|
|
|
|
|
|
|
// 缓存相关
|
|
|
|
|
const dataCache = ref(new Map()); // 缓存不同instance_id的数据
|
|
|
|
|
const currentInstanceId = ref(route.query.instance_id);
|
|
|
|
|
const isFromNavigation = ref(false); // 标记是否来自导航返回
|
|
|
|
|
|
|
|
|
|
// 缓存管理函数
|
|
|
|
|
const getCacheKey = (instanceId) => `vm_${instanceId}`;
|
|
|
|
|
|
|
|
|
|
const getCachedData = (instanceId) => {
|
|
|
|
|
const cacheKey = getCacheKey(instanceId);
|
|
|
|
|
return dataCache.value.get(cacheKey);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const setCachedData = (instanceId, data) => {
|
|
|
|
|
const cacheKey = getCacheKey(instanceId);
|
|
|
|
|
const cacheData = {
|
|
|
|
|
...data,
|
|
|
|
|
timestamp: Date.now(),
|
|
|
|
|
instanceId: instanceId
|
|
|
|
|
};
|
|
|
|
|
dataCache.value.set(cacheKey, cacheData);
|
|
|
|
|
console.log(`缓存虚拟机数据: ${instanceId}`, cacheData);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const isCacheValid = (cachedData, maxAge = 5 * 60 * 1000) => { // 默认5分钟有效期
|
|
|
|
|
if (!cachedData || !cachedData.timestamp) return false;
|
|
|
|
|
return (Date.now() - cachedData.timestamp) < maxAge;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const shouldUseCache = (instanceId) => {
|
|
|
|
|
// 检查是否来自列表页面的新进入
|
|
|
|
|
const fromSource = sessionStorage.getItem('vmDetailFrom');
|
|
|
|
|
const fromTimestamp = sessionStorage.getItem('vmDetailTimestamp');
|
|
|
|
|
|
|
|
|
|
// 如果是从列表页面新进入的,不使用缓存
|
|
|
|
|
if (fromSource === 'list' && fromTimestamp) {
|
|
|
|
|
const timeDiff = Date.now() - parseInt(fromTimestamp);
|
|
|
|
|
if (timeDiff < 2000) { // 2秒内的新进入
|
|
|
|
|
console.log('从列表页面新进入,不使用缓存');
|
|
|
|
|
// 清除标记
|
|
|
|
|
sessionStorage.removeItem('vmDetailFrom');
|
|
|
|
|
sessionStorage.removeItem('vmDetailTimestamp');
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果是相同的instance_id且来自导航返回,优先使用缓存
|
|
|
|
|
if (isFromNavigation.value && instanceId === currentInstanceId.value) {
|
|
|
|
|
const cachedData = getCachedData(instanceId);
|
|
|
|
|
const isValid = cachedData && isCacheValid(cachedData);
|
|
|
|
|
console.log(`缓存检查结果: instanceId=${instanceId}, isValid=${isValid}`);
|
|
|
|
|
return isValid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 保存当前数据到缓存
|
|
|
|
|
const saveDataToCache = (instanceId = null) => {
|
|
|
|
|
const targetInstanceId = instanceId || route.query.instance_id;
|
|
|
|
|
if (!targetInstanceId) return;
|
|
|
|
|
|
|
|
|
|
const dataToCache = {
|
|
|
|
|
vmInfo: { ...vmInfo.value },
|
|
|
|
|
logsList: [...logsList.value],
|
|
|
|
|
portsList: [...portsList.value],
|
|
|
|
|
networkRulesList: [...networkRulesList.value],
|
|
|
|
|
snapshotsList: [...snapshotsList.value],
|
|
|
|
|
dataVolumes: [...dataVolumes.value],
|
|
|
|
|
// 分页状态
|
|
|
|
|
logsPage: logsPage.value,
|
|
|
|
|
logsPageSize: logsPageSize.value,
|
|
|
|
|
portsPage: portsPage.value,
|
|
|
|
|
portsPageSize: portsPageSize.value,
|
|
|
|
|
networkRulesPage: networkRulesPage.value,
|
|
|
|
|
networkRulesPageSize: networkRulesPageSize.value,
|
|
|
|
|
// 总数
|
|
|
|
|
logsTotal: logsTotal.value,
|
|
|
|
|
portsTotal: portsTotal.value,
|
|
|
|
|
networkRulesTotal: networkRulesTotal.value,
|
|
|
|
|
volumesTotal: volumesTotal.value
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
setCachedData(targetInstanceId, dataToCache);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 标签页相关
|
|
|
|
|
const activeTabName = ref('0'); // 默认选中第一个标签
|
|
|
|
|
|
|
|
|
@@ -1136,6 +1222,107 @@ const fetchInstanceStatus = async () => {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 初始化数据
|
|
|
|
|
// 加载所有数据的统一函数
|
|
|
|
|
const loadAllData = async (instanceId = null, useCache = true) => {
|
|
|
|
|
const targetInstanceId = instanceId || route.query.instance_id;
|
|
|
|
|
|
|
|
|
|
// 检查是否使用缓存
|
|
|
|
|
if (useCache && shouldUseCache(targetInstanceId)) {
|
|
|
|
|
const cachedData = getCachedData(targetInstanceId);
|
|
|
|
|
console.log(`使用缓存数据加载所有信息: ${targetInstanceId}`);
|
|
|
|
|
|
|
|
|
|
// 从缓存恢复所有数据
|
|
|
|
|
vmInfo.value = cachedData.vmInfo || {};
|
|
|
|
|
logsList.value = cachedData.logsList || [];
|
|
|
|
|
portsList.value = cachedData.portsList || [];
|
|
|
|
|
networkRulesList.value = cachedData.networkRulesList || [];
|
|
|
|
|
snapshotsList.value = cachedData.snapshotsList || [];
|
|
|
|
|
dataVolumes.value = cachedData.dataVolumes || [];
|
|
|
|
|
|
|
|
|
|
// 恢复分页状态
|
|
|
|
|
if (cachedData.logsPage) logsPage.value = cachedData.logsPage;
|
|
|
|
|
if (cachedData.logsPageSize) logsPageSize.value = cachedData.logsPageSize;
|
|
|
|
|
if (cachedData.portsPage) portsPage.value = cachedData.portsPage;
|
|
|
|
|
if (cachedData.portsPageSize) portsPageSize.value = cachedData.portsPageSize;
|
|
|
|
|
if (cachedData.networkRulesPage) networkRulesPage.value = cachedData.networkRulesPage;
|
|
|
|
|
if (cachedData.networkRulesPageSize) networkRulesPageSize.value = cachedData.networkRulesPageSize;
|
|
|
|
|
|
|
|
|
|
// 恢复总数
|
|
|
|
|
if (cachedData.logsTotal) logsTotal.value = cachedData.logsTotal;
|
|
|
|
|
if (cachedData.portsTotal) portsTotal.value = cachedData.portsTotal;
|
|
|
|
|
if (cachedData.networkRulesTotal) networkRulesTotal.value = cachedData.networkRulesTotal;
|
|
|
|
|
if (cachedData.volumesTotal) volumesTotal.value = cachedData.volumesTotal;
|
|
|
|
|
|
|
|
|
|
// 重置loading状态
|
|
|
|
|
loading.value = false;
|
|
|
|
|
logsLoading.value = false;
|
|
|
|
|
portsLoading.value = false;
|
|
|
|
|
networkRulesLoading.value = false;
|
|
|
|
|
snapshotsLoading.value = false;
|
|
|
|
|
volumesLoading.value = false;
|
|
|
|
|
|
|
|
|
|
// 延迟初始化图表
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
initCharts();
|
|
|
|
|
fetchMonitorData();
|
|
|
|
|
}, 500);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 重新请求所有数据
|
|
|
|
|
console.log(`重新请求所有数据: ${targetInstanceId}`);
|
|
|
|
|
await Promise.all([
|
|
|
|
|
fetchVmInfo(targetInstanceId, false),
|
|
|
|
|
fetchPortsList(),
|
|
|
|
|
fetchLogsList(),
|
|
|
|
|
fetchAccessControlList(),
|
|
|
|
|
fetchNetworkRulesList(),
|
|
|
|
|
fetchSnapshotsList(),
|
|
|
|
|
fetchDataVolumesList(),
|
|
|
|
|
fetchInstanceStatus()
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
// 延迟初始化图表,确保DOM已经渲染
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
initCharts();
|
|
|
|
|
fetchMonitorData();
|
|
|
|
|
}, 500);
|
|
|
|
|
|
|
|
|
|
// 保存到缓存
|
|
|
|
|
saveDataToCache(targetInstanceId);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 监听路由参数变化
|
|
|
|
|
watch(() => route.query.instance_id, async (newInstanceId, oldInstanceId) => {
|
|
|
|
|
if (!newInstanceId) return;
|
|
|
|
|
|
|
|
|
|
// 保存旧数据到缓存(如果存在)
|
|
|
|
|
if (oldInstanceId && oldInstanceId !== newInstanceId) {
|
|
|
|
|
console.log(`保存旧虚拟机数据到缓存: ${oldInstanceId}`);
|
|
|
|
|
saveDataToCache(oldInstanceId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检测是否是instance_id变化
|
|
|
|
|
const isInstanceIdChanged = newInstanceId !== currentInstanceId.value;
|
|
|
|
|
|
|
|
|
|
if (isInstanceIdChanged) {
|
|
|
|
|
console.log(`虚拟机ID变化: ${currentInstanceId.value} -> ${newInstanceId}`);
|
|
|
|
|
currentInstanceId.value = newInstanceId;
|
|
|
|
|
isFromNavigation.value = false; // 重置导航标记
|
|
|
|
|
|
|
|
|
|
// 加载新的虚拟机数据(不使用缓存)
|
|
|
|
|
await loadAllData(newInstanceId, false);
|
|
|
|
|
} else {
|
|
|
|
|
// 相同的instance_id,可能是从其他页面返回
|
|
|
|
|
isFromNavigation.value = true;
|
|
|
|
|
console.log(`返回相同虚拟机: ${newInstanceId}`);
|
|
|
|
|
|
|
|
|
|
// 尝试使用缓存
|
|
|
|
|
await loadAllData(newInstanceId, true);
|
|
|
|
|
}
|
|
|
|
|
}, { immediate: false });
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
if (route.query.instance_id) {
|
|
|
|
|
// 恢复上次选中的标签页
|
|
|
|
@@ -1144,20 +1331,12 @@ onMounted(() => {
|
|
|
|
|
activeTabName.value = savedTab;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fetchVmInfo();
|
|
|
|
|
fetchPortsList();
|
|
|
|
|
fetchLogsList();
|
|
|
|
|
fetchAccessControlList();
|
|
|
|
|
fetchNetworkRulesList();
|
|
|
|
|
fetchSnapshotsList();
|
|
|
|
|
fetchDataVolumesList();
|
|
|
|
|
fetchInstanceStatus();
|
|
|
|
|
// 设置当前instance_id
|
|
|
|
|
currentInstanceId.value = route.query.instance_id;
|
|
|
|
|
isFromNavigation.value = false;
|
|
|
|
|
|
|
|
|
|
// 延迟初始化图表,确保DOM已经渲染
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
initCharts();
|
|
|
|
|
fetchMonitorData();
|
|
|
|
|
}, 500);
|
|
|
|
|
// 加载数据
|
|
|
|
|
loadAllData();
|
|
|
|
|
} else {
|
|
|
|
|
ElMessage.error('缺少虚拟机ID参数');
|
|
|
|
|
goBack();
|
|
|
|
@@ -1165,10 +1344,38 @@ onMounted(() => {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 获取虚拟机信息
|
|
|
|
|
const fetchVmInfo = async () => {
|
|
|
|
|
const fetchVmInfo = async (instanceId = null, useCache = true) => {
|
|
|
|
|
const targetInstanceId = instanceId || route.query.instance_id;
|
|
|
|
|
|
|
|
|
|
// 检查是否应该使用缓存
|
|
|
|
|
if (useCache && shouldUseCache(targetInstanceId)) {
|
|
|
|
|
const cachedData = getCachedData(targetInstanceId);
|
|
|
|
|
console.log(`使用缓存数据加载虚拟机: ${targetInstanceId}`);
|
|
|
|
|
|
|
|
|
|
// 从缓存恢复数据
|
|
|
|
|
vmInfo.value = cachedData.vmInfo || {};
|
|
|
|
|
logsList.value = cachedData.logsList || [];
|
|
|
|
|
portsList.value = cachedData.portsList || [];
|
|
|
|
|
networkRulesList.value = cachedData.networkRulesList || [];
|
|
|
|
|
snapshotsList.value = cachedData.snapshotsList || [];
|
|
|
|
|
dataVolumes.value = cachedData.dataVolumes || [];
|
|
|
|
|
|
|
|
|
|
// 重置loading状态
|
|
|
|
|
loading.value = false;
|
|
|
|
|
logsLoading.value = false;
|
|
|
|
|
portsLoading.value = false;
|
|
|
|
|
networkRulesLoading.value = false;
|
|
|
|
|
snapshotsLoading.value = false;
|
|
|
|
|
volumesLoading.value = false;
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
loading.value = true;
|
|
|
|
|
try {
|
|
|
|
|
const res = await getVmAdminContainer(route.query.instance_id);
|
|
|
|
|
console.log(`重新请求虚拟机数据: ${targetInstanceId}`);
|
|
|
|
|
|
|
|
|
|
const res = await getVmAdminContainer(targetInstanceId);
|
|
|
|
|
const serverRes = await selectServer({server_id:res.data.data.server_id})
|
|
|
|
|
const planRes = await selectServerPlan({plan_id:res.data.data.plan_id,server_type:"hyperV"})
|
|
|
|
|
const imageRes= await Mirrorinfo({image_id:res.data.data.image_id,server_type:"hyperV"})
|
|
|
|
@@ -1286,7 +1493,9 @@ const submitAddPort = async () => {
|
|
|
|
|
if (res && res.data && res.data.code === 200) {
|
|
|
|
|
ElMessage.success('添加端口成功');
|
|
|
|
|
showAddPortDialog.value = false;
|
|
|
|
|
fetchPortsList();
|
|
|
|
|
await fetchPortsList();
|
|
|
|
|
// 更新缓存
|
|
|
|
|
saveDataToCache();
|
|
|
|
|
} else {
|
|
|
|
|
ElMessage.error(res.data.message || '添加端口失败');
|
|
|
|
|
}
|
|
|
|
@@ -1311,7 +1520,9 @@ const handleDeletePort = async (port) => {
|
|
|
|
|
const res = await deletePort({ port_forward_id: port.id });
|
|
|
|
|
if (res && res.data && res.data.code === 200) {
|
|
|
|
|
ElMessage.success('删除成功');
|
|
|
|
|
fetchPortsList();
|
|
|
|
|
await fetchPortsList();
|
|
|
|
|
// 更新缓存
|
|
|
|
|
saveDataToCache();
|
|
|
|
|
} else {
|
|
|
|
|
ElMessage.error(res.data.message || '删除失败');
|
|
|
|
|
}
|
|
|
|
@@ -1324,14 +1535,23 @@ const handleDeletePort = async (port) => {
|
|
|
|
|
|
|
|
|
|
// 返回上一页
|
|
|
|
|
const goBack = () => {
|
|
|
|
|
// 标记这是返回操作,为了后续可能的缓存使用
|
|
|
|
|
sessionStorage.setItem('vmDetailFrom', 'back');
|
|
|
|
|
sessionStorage.setItem('vmDetailTimestamp', Date.now().toString());
|
|
|
|
|
router.go(-1);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 刷新数据
|
|
|
|
|
const refreshData = () => {
|
|
|
|
|
fetchVmInfo();
|
|
|
|
|
fetchPortsList();
|
|
|
|
|
fetchLogsList();
|
|
|
|
|
const instanceId = route.query.instance_id;
|
|
|
|
|
console.log(`手动刷新数据,清除缓存: ${instanceId}`);
|
|
|
|
|
|
|
|
|
|
// 清除当前虚拟机的缓存
|
|
|
|
|
const cacheKey = getCacheKey(instanceId);
|
|
|
|
|
dataCache.value.delete(cacheKey);
|
|
|
|
|
|
|
|
|
|
// 重新加载数据(不使用缓存)
|
|
|
|
|
loadAllData(instanceId, false);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 启动虚拟机
|
|
|
|
@@ -2234,6 +2454,12 @@ window.addEventListener('resize', resizeCharts);
|
|
|
|
|
|
|
|
|
|
// 组件卸载前清理
|
|
|
|
|
onBeforeUnmount(() => {
|
|
|
|
|
// 保存当前数据到缓存
|
|
|
|
|
if (route.query.instance_id) {
|
|
|
|
|
console.log(`组件卸载,保存数据到缓存: ${route.query.instance_id}`);
|
|
|
|
|
saveDataToCache();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 移除事件监听
|
|
|
|
|
window.removeEventListener('resize', resizeCharts);
|
|
|
|
|
|
|
|
|
|