【feat】 优化快照比对
This commit is contained in:
parent
d5b5f11aef
commit
ea83fd6f0d
@ -298,15 +298,23 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 处理下拉菜单点击
|
// 处理下拉菜单点击
|
||||||
|
// 处理下拉菜单点击
|
||||||
const handleLoginUrlPreset = (command) => {
|
const handleLoginUrlPreset = (command) => {
|
||||||
if (command === 'custom') {
|
if (command === 'custom') {
|
||||||
// 场景:用户选择了“自定义”
|
isCustomLoginUrl.value = true;
|
||||||
isCustomLoginUrl.value = true; // 解锁输入框
|
loginForm.value.loginUrl = ''; // 建议加上 .value
|
||||||
loginForm.loginUrl = ''; // 可选:清空当前值方便用户输入,或者保留原值
|
|
||||||
} else {
|
} else {
|
||||||
// 场景:用户选择了“生产”或“沙盒”
|
isCustomLoginUrl.value = false;
|
||||||
isCustomLoginUrl.value = false; // 锁定输入框
|
|
||||||
loginForm.loginUrl = command; // 填入预设 URL
|
// 核心逻辑:如果是沙盒环境且是账密模式,将 login 替换为 test
|
||||||
|
let targetUrl = command;
|
||||||
|
if (command === 'https://test.salesforce.com' && loginForm.value.loginType === 'legacy_credential') {
|
||||||
|
// 确保此处逻辑符合你的后端/API需求
|
||||||
|
// 如果后端要求账密模式下沙盒必须用 test.salesforce.com,这里已经正确
|
||||||
|
targetUrl = 'https://test.salesforce.com';
|
||||||
|
}
|
||||||
|
|
||||||
|
loginForm.value.loginUrl = targetUrl;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -352,6 +360,10 @@
|
|||||||
const handleLoginTypeChange = () => {
|
const handleLoginTypeChange = () => {
|
||||||
loginForm.value.grantType = 'password';
|
loginForm.value.grantType = 'password';
|
||||||
resetFormFields();
|
resetFormFields();
|
||||||
|
|
||||||
|
// 默认给一个生产环境地址
|
||||||
|
loginForm.value.loginUrl = 'https://login.salesforce.com';
|
||||||
|
isCustomLoginUrl.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleGrantTypeChange = () => {
|
const handleGrantTypeChange = () => {
|
||||||
|
|||||||
@ -7,12 +7,12 @@
|
|||||||
|
|
||||||
<el-table :data="snapshotList" v-loading="loading" border stripe>
|
<el-table :data="snapshotList" v-loading="loading" border stripe>
|
||||||
<el-table-column prop="id" label="快照ID" width="80" />
|
<el-table-column prop="id" label="快照ID" width="80" />
|
||||||
<el-table-column prop="snapshotName" label="快照名称" min-width="150" />
|
<el-table-column prop="snapshotNumber" label="快照名称" min-width="150" />
|
||||||
<el-table-column prop="environmentName" label="环境" width="120" />
|
<el-table-column prop="environmentName" label="环境" width="120" />
|
||||||
<el-table-column prop="description" label="描述" min-width="200" show-overflow-tooltip />
|
<el-table-column prop="snapshotDesc" label="描述" min-width="200" show-overflow-tooltip />
|
||||||
<el-table-column prop="configCount" label="配置数量" width="100" align="center" />
|
<el-table-column prop="configCount" label="配置数量" width="100" align="center" />
|
||||||
<el-table-column prop="createdBy" label="创建人" width="120" />
|
<el-table-column prop="createBy" label="创建人" width="120" />
|
||||||
<el-table-column prop="createTime" label="创建时间" width="180" />
|
<el-table-column prop="createTime" label="创建时间" width="180" :formatter="(row) => formatDate(row.createTime)" />
|
||||||
<el-table-column label="操作" width="280" fixed="right">
|
<el-table-column label="操作" width="280" fixed="right">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-button type="primary" link :icon="View" @click="handleViewDetail(row)">查看</el-button>
|
<el-button type="primary" link :icon="View" @click="handleViewDetail(row)">查看</el-button>
|
||||||
@ -33,8 +33,8 @@
|
|||||||
|
|
||||||
<el-dialog v-model="createDialogVisible" title="创建快照" width="600px" @close="resetCreateForm">
|
<el-dialog v-model="createDialogVisible" title="创建快照" width="600px" @close="resetCreateForm">
|
||||||
<el-form :model="createForm" :rules="createRules" ref="createFormRef" label-width="100px">
|
<el-form :model="createForm" :rules="createRules" ref="createFormRef" label-width="100px">
|
||||||
<el-form-item label="快照名称" prop="snapshotName">
|
<el-form-item label="快照名称" prop="snapshotNumber">
|
||||||
<el-input v-model="createForm.snapshotName" placeholder="请输入快照名称" maxlength="50" />
|
<el-input v-model="createForm.snapshotNumber" placeholder="请输入快照名称" maxlength="50" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="环境" prop="environmentId">
|
<el-form-item label="环境" prop="environmentId">
|
||||||
<el-select v-model="createForm.environmentId" placeholder="请选择环境" style="width: 100%">
|
<el-select v-model="createForm.environmentId" placeholder="请选择环境" style="width: 100%">
|
||||||
@ -46,9 +46,9 @@
|
|||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="描述" prop="description">
|
<el-form-item label="描述" prop="snapshotDesc">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="createForm.description"
|
v-model="createForm.snapshotDesc"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
:rows="3"
|
:rows="3"
|
||||||
placeholder="请输入快照描述"
|
placeholder="请输入快照描述"
|
||||||
@ -62,21 +62,24 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog v-model="detailDialogVisible" title="快照详情" width="800px">
|
<el-dialog v-model="detailDialogVisible" title="快照详情" width="800px" :close-on-click-modal="false">
|
||||||
|
<div v-loading="detailLoading">
|
||||||
<el-descriptions :column="2" border>
|
<el-descriptions :column="2" border>
|
||||||
<el-descriptions-item label="快照ID">{{ currentSnapshot.id }}</el-descriptions-item>
|
<el-descriptions-item label="快照ID">{{ currentSnapshot.id }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="快照名称">{{ currentSnapshot.snapshotName }}</el-descriptions-item>
|
<el-descriptions-item label="快照名称">{{ currentSnapshot.snapshotNumber }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="环境">{{ currentSnapshot.environmentName }}</el-descriptions-item>
|
<el-descriptions-item label="环境">{{ currentSnapshot.environmentName }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="配置数量">{{ currentSnapshot.configCount }}</el-descriptions-item>
|
<el-descriptions-item label="配置数量">{{ currentSnapshot.configCount }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="创建人">{{ currentSnapshot.createdBy }}</el-descriptions-item>
|
<el-descriptions-item label="创建人">{{ currentSnapshot.createBy }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="创建时间">{{ currentSnapshot.createTime }}</el-descriptions-item>
|
<el-descriptions-item label="创建时间">{{ formatDate(currentSnapshot.createTime) }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="描述" :span="2">{{ currentSnapshot.description }}</el-descriptions-item>
|
<el-descriptions-item label="描述" :span="2">{{ currentSnapshot.snapshotDesc }}</el-descriptions-item>
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
|
|
||||||
<el-divider>配置详情</el-divider>
|
<el-divider>配置详情</el-divider>
|
||||||
|
|
||||||
<el-table :data="snapshotConfigList" border stripe max-height="400">
|
<el-empty v-if="!detailLoading && snapshotConfigList.length === 0" description="暂无配置数据" />
|
||||||
<el-table-column prop="configKey" label="配置键" min-width="200" />
|
|
||||||
|
<el-table v-else :data="snapshotConfigList" border stripe max-height="400">
|
||||||
|
<el-table-column prop="configKey" label="配置键" min-width="200" show-overflow-tooltip />
|
||||||
<el-table-column prop="configValue" label="配置值" min-width="250" show-overflow-tooltip />
|
<el-table-column prop="configValue" label="配置值" min-width="250" show-overflow-tooltip />
|
||||||
<el-table-column prop="isSensitive" label="敏感配置" width="100" align="center">
|
<el-table-column prop="isSensitive" label="敏感配置" width="100" align="center">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
@ -85,7 +88,9 @@
|
|||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column prop="createBy" label="创建人" width="120" show-overflow-tooltip />
|
||||||
</el-table>
|
</el-table>
|
||||||
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog v-model="compareDialogVisible" title="快照对比" width="900px">
|
<el-dialog v-model="compareDialogVisible" title="快照对比" width="900px">
|
||||||
@ -94,7 +99,7 @@
|
|||||||
<el-option
|
<el-option
|
||||||
v-for="snap in snapshotList"
|
v-for="snap in snapshotList"
|
||||||
:key="snap.id"
|
:key="snap.id"
|
||||||
:label="snap.snapshotName"
|
:label="snap.snapshotNumber"
|
||||||
:value="snap.id"
|
:value="snap.id"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
@ -103,14 +108,18 @@
|
|||||||
<el-option
|
<el-option
|
||||||
v-for="snap in snapshotList"
|
v-for="snap in snapshotList"
|
||||||
:key="snap.id"
|
:key="snap.id"
|
||||||
:label="snap.snapshotName"
|
:label="snap.snapshotNumber"
|
||||||
:value="snap.id"
|
:value="snap.id"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
<el-button type="primary" @click="handleExecuteCompare" :loading="compareLoading">对比</el-button>
|
<el-button type="primary" @click="handleExecuteCompare" :loading="compareLoading">对比</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-table :data="compareResult" border stripe v-if="compareResult.length > 0">
|
<div v-if="compareReport" class="compare-report">
|
||||||
|
<pre>{{ compareReport }}</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-table v-else-if="compareResult.length > 0" :data="compareResult" border stripe>
|
||||||
<el-table-column prop="configKey" label="配置键" min-width="200" />
|
<el-table-column prop="configKey" label="配置键" min-width="200" />
|
||||||
<el-table-column prop="value1" label="快照1值" min-width="200" show-overflow-tooltip />
|
<el-table-column prop="value1" label="快照1值" min-width="200" show-overflow-tooltip />
|
||||||
<el-table-column prop="value2" label="快照2值" min-width="200" show-overflow-tooltip />
|
<el-table-column prop="value2" label="快照2值" min-width="200" show-overflow-tooltip />
|
||||||
@ -122,6 +131,8 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
|
<el-empty v-else-if="!compareLoading" description="请选择两个快照进行对比" />
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -145,6 +156,7 @@
|
|||||||
DocumentCopy,
|
DocumentCopy,
|
||||||
Delete
|
Delete
|
||||||
} from '@element-plus/icons-vue';
|
} from '@element-plus/icons-vue';
|
||||||
|
import { formatDate } from '@/utils/index';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
currentEnvironment: {
|
currentEnvironment: {
|
||||||
@ -156,11 +168,13 @@
|
|||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const createLoading = ref(false);
|
const createLoading = ref(false);
|
||||||
const compareLoading = ref(false);
|
const compareLoading = ref(false);
|
||||||
|
const detailLoading = ref(false);
|
||||||
const snapshotList = ref([]);
|
const snapshotList = ref([]);
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
const environmentList = ref([]);
|
const environmentList = ref([]);
|
||||||
const snapshotConfigList = ref([]);
|
const snapshotConfigList = ref([]);
|
||||||
const compareResult = ref([]);
|
const compareResult = ref([]);
|
||||||
|
const compareReport = ref('');
|
||||||
|
|
||||||
const queryParams = ref({
|
const queryParams = ref({
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
@ -176,13 +190,13 @@
|
|||||||
const currentSnapshot = ref({});
|
const currentSnapshot = ref({});
|
||||||
|
|
||||||
const createForm = ref({
|
const createForm = ref({
|
||||||
snapshotName: '',
|
snapshotNumber: '',
|
||||||
environmentId: null,
|
environmentId: null,
|
||||||
description: ''
|
snapshotDesc: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
const createRules = {
|
const createRules = {
|
||||||
snapshotName: [
|
snapshotNumber: [
|
||||||
{ required: true, message: '请输入快照名称', trigger: 'blur' }
|
{ required: true, message: '请输入快照名称', trigger: 'blur' }
|
||||||
],
|
],
|
||||||
environmentId: [
|
environmentId: [
|
||||||
@ -234,9 +248,9 @@
|
|||||||
|
|
||||||
const resetCreateForm = () => {
|
const resetCreateForm = () => {
|
||||||
createForm.value = {
|
createForm.value = {
|
||||||
snapshotName: '',
|
snapshotNumber: '',
|
||||||
environmentId: null,
|
environmentId: null,
|
||||||
description: ''
|
snapshotDesc: ''
|
||||||
};
|
};
|
||||||
createFormRef.value?.clearValidate();
|
createFormRef.value?.clearValidate();
|
||||||
};
|
};
|
||||||
@ -266,23 +280,72 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleViewDetail = async (row) => {
|
const handleViewDetail = async (row) => {
|
||||||
|
console.log('点击查看详情,row 对象:', row);
|
||||||
|
console.log('row.id:', row.id);
|
||||||
|
console.log('row 的所有字段:', Object.keys(row));
|
||||||
|
|
||||||
|
const snapshotId = row.id || row.snapshotId || row.snapshotNumber;
|
||||||
|
|
||||||
|
if (!row || !snapshotId) {
|
||||||
|
ElMessage.error('快照ID不存在,无法查看详情');
|
||||||
|
console.error('快照数据异常:', row);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
detailLoading.value = true;
|
||||||
try {
|
try {
|
||||||
const response = await getSnapshotDetail(row.id);
|
console.log('获取快照详情,ID:', snapshotId);
|
||||||
|
const response = await getSnapshotDetail(snapshotId);
|
||||||
|
console.log('快照详情响应:', response);
|
||||||
|
|
||||||
if (response.code === 200) {
|
if (response.code === 200) {
|
||||||
currentSnapshot.value = response.data.snapshot;
|
const data = response.data;
|
||||||
snapshotConfigList.value = response.data.configs || [];
|
if (data) {
|
||||||
|
currentSnapshot.value = data.snapshot || data;
|
||||||
|
|
||||||
|
let configs = [];
|
||||||
|
if (data.snapshotContent) {
|
||||||
|
try {
|
||||||
|
configs = JSON.parse(data.snapshotContent);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('解析 snapshotContent 失败:', e);
|
||||||
|
configs = [];
|
||||||
|
}
|
||||||
|
} else if (data.configs) {
|
||||||
|
configs = data.configs;
|
||||||
|
} else if (data.snapshotConfigs) {
|
||||||
|
configs = data.snapshotConfigs;
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshotConfigList.value = Array.isArray(configs) ? configs : [];
|
||||||
|
console.log('当前快照:', currentSnapshot.value);
|
||||||
|
console.log('配置列表:', snapshotConfigList.value);
|
||||||
detailDialogVisible.value = true;
|
detailDialogVisible.value = true;
|
||||||
|
} else {
|
||||||
|
ElMessage.error('快照详情数据为空');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(response.msg || '获取快照详情失败');
|
ElMessage.error(response.msg || '获取快照详情失败');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
ElMessage.error(error.msg || '获取快照详情失败');
|
console.error('获取快照详情失败:', error);
|
||||||
|
ElMessage.error(error.msg || error.message || '获取快照详情失败');
|
||||||
|
} finally {
|
||||||
|
detailLoading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRestore = (row) => {
|
const handleRestore = (row) => {
|
||||||
|
const snapshotId = row.id || row.snapshotId || row.snapshotNumber;
|
||||||
|
|
||||||
|
if (!row || !snapshotId) {
|
||||||
|
ElMessage.error('快照ID不存在,无法恢复');
|
||||||
|
console.error('快照数据异常:', row);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ElMessageBox.confirm(
|
ElMessageBox.confirm(
|
||||||
`确定要恢复快照"${row.snapshotName}"吗?此操作将覆盖当前环境配置,请谨慎操作。`,
|
`确定要恢复快照"${row.snapshotNumber}"吗?此操作将覆盖当前环境配置,请谨慎操作。`,
|
||||||
'恢复确认',
|
'恢复确认',
|
||||||
{
|
{
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
@ -291,7 +354,7 @@
|
|||||||
}
|
}
|
||||||
).then(async () => {
|
).then(async () => {
|
||||||
try {
|
try {
|
||||||
const response = await restoreSnapshot(row.id, {});
|
const response = await restoreSnapshot(snapshotId, {});
|
||||||
if (response.code === 200) {
|
if (response.code === 200) {
|
||||||
ElMessage.success('快照恢复成功');
|
ElMessage.success('快照恢复成功');
|
||||||
getList();
|
getList();
|
||||||
@ -305,7 +368,15 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleCompare = (row) => {
|
const handleCompare = (row) => {
|
||||||
compareForm.value.snapshotId1 = row.id;
|
const snapshotId = row.id || row.snapshotId || row.snapshotNumber;
|
||||||
|
|
||||||
|
if (!row || !snapshotId) {
|
||||||
|
ElMessage.error('快照ID不存在,无法对比');
|
||||||
|
console.error('快照数据异常:', row);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
compareForm.value.snapshotId1 = snapshotId;
|
||||||
compareDialogVisible.value = true;
|
compareDialogVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -321,13 +392,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
compareLoading.value = true;
|
compareLoading.value = true;
|
||||||
|
compareResult.value = [];
|
||||||
|
compareReport.value = '';
|
||||||
try {
|
try {
|
||||||
const response = await compareSnapshots(
|
const response = await compareSnapshots(
|
||||||
compareForm.value.snapshotId1,
|
compareForm.value.snapshotId1,
|
||||||
compareForm.value.snapshotId2
|
compareForm.value.snapshotId2
|
||||||
);
|
);
|
||||||
if (response.code === 200) {
|
if (response.code === 200) {
|
||||||
compareResult.value = response.data || [];
|
if (response.data && Array.isArray(response.data)) {
|
||||||
|
compareResult.value = response.data;
|
||||||
|
} else if (response.msg) {
|
||||||
|
compareReport.value = response.msg;
|
||||||
|
} else {
|
||||||
|
ElMessage.warning('对比结果格式异常');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(response.msg || '对比快照失败');
|
ElMessage.error(response.msg || '对比快照失败');
|
||||||
}
|
}
|
||||||
@ -339,8 +418,16 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleDelete = (row) => {
|
const handleDelete = (row) => {
|
||||||
|
const snapshotId = row.id || row.snapshotId || row.snapshotNumber;
|
||||||
|
|
||||||
|
if (!row || !snapshotId) {
|
||||||
|
ElMessage.error('快照ID不存在,无法删除');
|
||||||
|
console.error('快照数据异常:', row);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ElMessageBox.confirm(
|
ElMessageBox.confirm(
|
||||||
`确定要删除快照"${row.snapshotName}"吗?删除后无法恢复。`,
|
`确定要删除快照"${row.snapshotNumber}"吗?删除后无法恢复。`,
|
||||||
'删除确认',
|
'删除确认',
|
||||||
{
|
{
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
@ -349,7 +436,7 @@
|
|||||||
}
|
}
|
||||||
).then(async () => {
|
).then(async () => {
|
||||||
try {
|
try {
|
||||||
const response = await delSnapshot(row.id);
|
const response = await delSnapshot(snapshotId);
|
||||||
if (response.code === 200) {
|
if (response.code === 200) {
|
||||||
ElMessage.success('删除成功');
|
ElMessage.success('删除成功');
|
||||||
getList();
|
getList();
|
||||||
@ -400,6 +487,25 @@
|
|||||||
color: #909399;
|
color: #909399;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.compare-report {
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
border-radius: 4px;
|
||||||
|
max-height: 500px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compare-report pre {
|
||||||
|
margin: 0;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
font-family: 'Courier New', Courier, monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
:deep(.el-table) {
|
:deep(.el-table) {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user