feat(biz): 添加接口测试页面支持视频搜索和评论功能

- 新增 fetchVideoSearchV2 和 fetchVideoComments API 接口
- 实现接口测试页面,支持 JSON 参数输入和响应结果显示
- 集成视频搜索和视频评论两种测试方法
- 添加参数验证、示例填充和结果清空功能
- 实现接口调用耗时统计和落库结果展示
- 集成权限控制和错误处理机制
This commit is contained in:
15003752739 2026-06-03 22:21:54 +08:00
parent 96c80447fb
commit 06bd77bc60
2 changed files with 215 additions and 0 deletions

View File

@ -0,0 +1,23 @@
import request from '@/utils/request';
/**
* fetchVideoSearchV2
*/
export const fetchVideoSearchV2 = (data: Record<string, any>) => {
return request({
url: '/biz/apiTest/fetchVideoSearchV2',
method: 'post',
data
});
};
/**
* fetchVideoComments
*/
export const fetchVideoComments = (data: Record<string, any>) => {
return request({
url: '/biz/apiTest/fetchVideoComments',
method: 'post',
data
});
};

View File

@ -0,0 +1,192 @@
<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>