This commit is contained in:
2025-12-04 12:44:54 +08:00
parent d687bf67b1
commit 3f33e5c2f1
8 changed files with 447 additions and 99 deletions

View File

@@ -414,13 +414,25 @@
<div v-if="decryptedData" class="mt-3 pt-3 border-t border-gray-200">
<h5 class="text-xs font-semibold text-gray-700 mb-1">解密后的内容</h5>
<pre
class="bg-green-50 p-2 rounded text-xs overflow-x-auto m-0 mb-1.5 max-h-45 border border-green-200 font-mono text-green-800">
class="bg-green-50 p-2 rounded text-xs overflow-x-auto m-0 mb-1.5 max-h-45 border border-green-200 font-mono text-green-800"
:key="`decrypted-${Date.now()}`">
{{ JSON.stringify(decryptedData, null, 2) }}</pre>
<el-button type="success" size="default"
@click="copyToClipboard(JSON.stringify(decryptedData, null, 2))" class="w-full">
复制解密内容
</el-button>
</div>
<!-- 解密加载状态 -->
<div v-else-if="debugging && debugResult && debugResult.success && debugResult.response?.data?.data"
class="mt-3 pt-3 border-t border-gray-200">
<div class="flex items-center gap-2 text-sm text-gray-500">
<svg class="animate-spin h-4 w-4 text-gray-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
<span>正在解密响应数据...</span>
</div>
</div>
</div>
</div>
</div>
@@ -545,6 +557,8 @@ const productsLoading = ref(false)
const debugging = ref(false)
const encrypting = ref(false)
const autoSelecting = ref(false) // 新增:自动选择状态
const isSelectingProduct = ref(false) // 防止重复选择产品的标志
const lastSelectedProductId = ref(null) // 记录最后选择的产品ID
const userProducts = ref([])
const apiConfig = ref(null)
const selectedProduct = ref(null)
@@ -650,12 +664,22 @@ onMounted(async () => {
// 监听路由参数变化,自动选择产品
watch(
() => route.params.productId,
async (newProductId) => {
() => route.query.productId || route.params.productId,
async (newProductId, oldProductId) => {
// 防止重复触发如果产品ID没有变化不执行
if (newProductId === oldProductId) {
return
}
// 如果正在选择产品,不重复执行
if (isSelectingProduct.value) {
return
}
if (newProductId && userProducts.value.length > 0) {
await autoSelectProduct(newProductId)
} else if (!newProductId && userProducts.value.length > 0) {
// 如果没有指定产品,选择第一个
} else if (!newProductId && userProducts.value.length > 0 && !selectedProduct.value) {
// 如果没有指定产品且当前没有选中产品,选择第一个
await selectProduct(userProducts.value[0])
}
}
@@ -663,6 +687,18 @@ watch(
// 自动选择产品
const autoSelectProduct = async (productId) => {
// 防止重复执行
if (isSelectingProduct.value) {
console.log('正在选择产品,跳过重复请求')
return
}
// 如果已经选择了相同的产品,不重复选择
if (lastSelectedProductId.value === productId && selectedProduct.value) {
console.log('产品已选择,跳过重复选择:', productId)
return
}
// 如果用户产品列表为空,等待加载完成
if (!userProducts.value.length) {
console.log('等待用户产品列表加载完成...')
@@ -686,7 +722,13 @@ const autoSelectProduct = async (productId) => {
if (targetProduct) {
console.log('自动选择产品:', targetProduct)
await selectProduct(targetProduct)
isSelectingProduct.value = true
try {
await selectProduct(targetProduct)
lastSelectedProductId.value = productId
} finally {
isSelectingProduct.value = false
}
} else {
console.warn('未找到指定的产品:', productId)
ElMessage.warning(`未找到产品ID为 ${productId} 的产品,请手动选择`)
@@ -699,7 +741,7 @@ const loadUserProducts = async () => {
try {
const response = await subscriptionApi.getMySubscriptions({
page: 1,
page_size: 100
page_size: 1000
})
if (response.success && response.data?.items) {
@@ -712,16 +754,23 @@ const loadUserProducts = async () => {
}))
console.log("route.params", route)
// 检查是否有params参数指定产品
if (route.params.productId && userProducts.value.length > 0) {
// 检查是否有query或params参数指定产品
const productId = route.query.productId || route.params.productId
if (productId && userProducts.value.length > 0) {
await nextTick()
await autoSelectProduct(route.params.productId)
} else if (userProducts.value.length > 0) {
// 没有指定产品时,默认选择第一个
// 使用 autoSelectProduct 会自动处理防重复逻辑
await autoSelectProduct(productId)
} else if (userProducts.value.length > 0 && !selectedProduct.value) {
// 没有指定产品时,默认选择第一个(仅在未选择产品时)
autoSelecting.value = true
await selectProduct(userProducts.value[0])
autoSelecting.value = false
isSelectingProduct.value = true
try {
await selectProduct(userProducts.value[0])
lastSelectedProductId.value = userProducts.value[0].id || userProducts.value[0].product_id
} finally {
isSelectingProduct.value = false
autoSelecting.value = false
}
}
} else {
// 如果没有订阅产品,显示提示信息
@@ -753,6 +802,15 @@ const loadApiKeys = async () => {
// 选择产品
const selectProduct = async (product) => {
// 防止重复选择相同产品
const productId = product.product_id || product.id
if (selectedProduct.value &&
(selectedProduct.value.id === productId || selectedProduct.value.product_id === productId) &&
!isSelectingProduct.value) {
console.log('产品已选择,跳过重复加载:', productId)
return
}
// 确保API密钥已经加载
if (!debugForm.accessId || !debugForm.secretKey) {
ElMessage.warning('正在加载API密钥请稍候...')
@@ -764,6 +822,7 @@ const selectProduct = async (product) => {
debugForm.params = {}
debugResult.value = null
encryptedData.value = null
decryptedData.value = null
activeTab.value = 'basic_info' // 重置Tab
productDocumentation.value = null // 重置文档
@@ -1106,6 +1165,11 @@ const handleDebug = async () => {
}
debugging.value = true
// 清空之前的调试结果确保UI实时更新
debugResult.value = null
decryptedData.value = null
await nextTick() // 确保DOM更新
const startTime = new Date()
try {
@@ -1118,22 +1182,6 @@ const handleDebug = async () => {
return
}
// 1.5. 类型转换:将 page_size 和 page_num 从字符串转换为数字
if (parsedParams && typeof parsedParams === 'object') {
if (parsedParams.page_size !== undefined && typeof parsedParams.page_size === 'string') {
const pageSize = parseInt(parsedParams.page_size, 10)
if (!isNaN(pageSize)) {
parsedParams.page_size = pageSize
}
}
if (parsedParams.page_num !== undefined && typeof parsedParams.page_num === 'string') {
const pageNum = parseInt(parsedParams.page_num, 10)
if (!isNaN(pageNum)) {
parsedParams.page_num = pageNum
}
}
}
// 2. 加密参数
const encryptedParams = await encryptWithAES(parsedParams, debugForm.secretKey)
if (!encryptedParams) {
@@ -1159,7 +1207,7 @@ const handleDebug = async () => {
console.log('产品API调用成功:', responseData)
const endTime = new Date()
// 5. 保存调试结果
// 5. 保存调试结果 - 立即更新确保UI实时显示
debugResult.value = createDebugResult(
selectedProduct.value,
requestBody,
@@ -1170,6 +1218,9 @@ const handleDebug = async () => {
responseData.success && responseData.data?.code === 0
)
// 确保DOM更新后再进行解密操作
await nextTick()
// 6. 如果响应成功且包含加密数据,自动解密
console.log('responseData', responseData)
if (responseData.success && responseData.data?.code === 0 && responseData.data?.data && typeof responseData.data.data === 'string') {
@@ -1180,7 +1231,9 @@ const handleDebug = async () => {
)
if (decryptResult.success) {
// 使用 nextTick 确保响应式更新
decryptedData.value = decryptResult.data
await nextTick()
ElMessage.success('调试完成,数据已自动解密')
} else {
ElMessage.warning('调试完成,但数据解密失败:' + (decryptResult.message || '未知错误'))
@@ -1223,6 +1276,9 @@ const handleDebug = async () => {
false
)
// 确保DOM更新
await nextTick()
ElMessage.error('API调用失败' + apiError.message)
}
} catch (error) {
@@ -1239,6 +1295,9 @@ const handleDebug = async () => {
endTime,
false
)
// 确保DOM更新
await nextTick()
} finally {
debugging.value = false
}