plus-ui/src/views/biz/apiTest/index.vue
15003752739 06bd77bc60 feat(biz): 添加接口测试页面支持视频搜索和评论功能
- 新增 fetchVideoSearchV2 和 fetchVideoComments API 接口
- 实现接口测试页面,支持 JSON 参数输入和响应结果显示
- 集成视频搜索和视频评论两种测试方法
- 添加参数验证、示例填充和结果清空功能
- 实现接口调用耗时统计和落库结果展示
- 集成权限控制和错误处理机制
2026-06-03 22:21:54 +08:00

193 lines
5.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="p-2">
<el-card shadow="never">
<template #header>
<span class="font-bold">接口测试</span>
<span class="ml-2 text-gray-400 text-sm">调用 IBizDouyinSearchServiceJSON 作为方法入参</span>
</template>
<el-form label-width="100px">
<el-form-item label="测试方法">
<el-radio-group v-model="method">
<el-radio label="fetchVideoSearchV2">fetchVideoSearchV2视频搜索</el-radio>
<el-radio label="fetchVideoComments">fetchVideoComments视频评论</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="JSON 参数">
<el-input
v-model="jsonParams"
type="textarea"
:rows="14"
placeholder="请输入 JSON 对象,例如:&#10;{&#10; &quot;keyword&quot;: &quot;CPU&quot;,&#10; &quot;cursor&quot;: 0&#10;}"
spellcheck="false"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" :loading="loading" icon="VideoPlay" v-hasPermi="['biz:apiTest:invoke']" @click="handleInvoke">
执行
</el-button>
<el-button icon="Document" @click="fillSample">填充示例</el-button>
<el-button icon="Refresh" @click="clearResult">清空结果</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card v-if="persistSummary" shadow="never" class="mt-[10px]">
<template #header>
<span class="font-bold">落库结果</span>
</template>
<el-alert
v-if="persistSummary.error"
type="warning"
:title="String(persistSummary.error)"
show-icon
:closable="false"
class="mb-2"
/>
<el-descriptions v-else :column="3" border size="small">
<el-descriptions-item v-for="(val, key) in persistSummary" :key="key" :label="String(key)">
{{ val }}
</el-descriptions-item>
</el-descriptions>
</el-card>
<el-card shadow="never" class="mt-[10px]">
<template #header>
<div class="flex items-center justify-between">
<span class="font-bold">响应结果</span>
<el-tag v-if="elapsedMs !== null" type="info" size="small">耗时 {{ elapsedMs }} ms</el-tag>
</div>
</template>
<div v-if="!responseText" class="text-gray-400 text-sm py-8 text-center">执行后将在此展示接口返回 JSON</div>
<pre v-else class="response-pre">{{ responseText }}</pre>
</el-card>
</div>
</template>
<script setup name="ApiTest" lang="ts">
import { fetchVideoComments, fetchVideoSearchV2 } from '@/api/biz/apiTest';
import { ElMessage } from 'element-plus';
type TestMethod = 'fetchVideoSearchV2' | 'fetchVideoComments';
const SAMPLE_PARAMS: Record<TestMethod, string> = {
fetchVideoSearchV2: JSON.stringify(
{
keyword: 'CPU',
cursor: 0
},
null,
2
),
fetchVideoComments: JSON.stringify(
{
aweme_id: '7448118827402972455',
count: 20
},
null,
2
)
};
const method = ref<TestMethod>('fetchVideoSearchV2');
const jsonParams = ref(SAMPLE_PARAMS.fetchVideoSearchV2);
const responseText = ref('');
const persistSummary = ref<Record<string, unknown> | null>(null);
const loading = ref(false);
const elapsedMs = ref<number | null>(null);
watch(method, (val) => {
jsonParams.value = SAMPLE_PARAMS[val];
responseText.value = '';
persistSummary.value = null;
elapsedMs.value = null;
});
const parseParams = (): Record<string, any> => {
const text = jsonParams.value?.trim();
if (!text) {
return {};
}
try {
const parsed = JSON.parse(text);
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
throw new Error('参数必须是 JSON 对象');
}
return parsed;
} catch (e: any) {
throw new Error('JSON 格式错误:' + (e?.message || '无法解析'));
}
};
const formatResponse = (data: unknown): string => {
try {
return JSON.stringify(data, null, 2);
} catch {
return String(data);
}
};
const handleInvoke = async () => {
let params: Record<string, any>;
try {
params = parseParams();
} catch (e: any) {
ElMessage.error(e.message);
return;
}
loading.value = true;
const start = Date.now();
try {
const res =
method.value === 'fetchVideoSearchV2'
? await fetchVideoSearchV2(params)
: await fetchVideoComments(params);
elapsedMs.value = Date.now() - start;
const payload = res.data as Record<string, unknown>;
persistSummary.value = (payload?.persist as Record<string, unknown>) ?? null;
responseText.value = formatResponse(payload);
if (persistSummary.value?.error) {
ElMessage.warning('接口调用成功,但落库未执行:' + persistSummary.value.error);
} else if (persistSummary.value) {
ElMessage.success('调用成功,落库已完成');
} else {
ElMessage.success('调用成功');
}
} catch (e: any) {
elapsedMs.value = Date.now() - start;
responseText.value = e?.message || '请求失败';
ElMessage.error('调用失败');
} finally {
loading.value = false;
}
};
const fillSample = () => {
jsonParams.value = SAMPLE_PARAMS[method.value];
};
const clearResult = () => {
responseText.value = '';
persistSummary.value = null;
elapsedMs.value = null;
};
</script>
<style scoped>
.response-pre {
margin: 0;
padding: 12px;
background: var(--el-fill-color-light);
border-radius: 4px;
font-size: 13px;
line-height: 1.5;
white-space: pre-wrap;
word-break: break-all;
max-height: 600px;
overflow: auto;
}
</style>