Vue接口平台学习十——接口用例页面2
效果图及简单说明

左边选择用例,右侧就显示该用例的详细信息。
使用el-collapse折叠组件,将请求到的用例详情数据展示到页面中。
所有数据内容,绑定到caseData中
// 页面绑定的用例编辑数据
const caseData = reactive({title: "",interface: {method: "get",url: ""},headers: '',request: {json: '{}',data: '{}',params: '{}'},file: [],setup_script: '',teardown_script: ''
})
页面内容实现
1. 请求API信息
<el-collapse-item name="1"><template #title><img src="@/assets/icons/icon-api-a.png" width="20"><b>API信息</b></template><el-input v-model="caseData.interface.url" readonly><template #prepend><el-select v-model="caseData.interface.method" placeholder="选择请求方法" style="width: 115px"><el-option label="GET" value="get"/><el-option label="POST" value="post"/><el-option label="PUT" value="put"/><el-option label="PATCH" value="patch"/><el-option label="DELETE" value="delete"/></el-select></template></el-input></el-collapse-item>
一个下拉选择(请求方法) + 一个只读的input框

2.用例title
<el-collapse-item name="2"><template #title><img src="@/assets/icons/case.png" width="20"><b>用例名称</b></template><el-input v-model="caseData.title"><template #prepend><span>用例名称</span></template></el-input></el-collapse-item>
一个带前缀的input输入框

3. 前置脚本
前置脚本是一个python代码编辑器
<div class="code"><Editor v-model="caseData.setup_script" lang="python" height='300px' class="scriptEdit"></Editor>
</div>
但是,可以准备一些预制脚本,方便使用。
可以创建编辑一些脚本保存在数据库,然后读取。这里没有选择那么复杂的内容,直接写死在了前端页面点击添加。
<div class='script_code'><div class="code"><Editor v-model="caseData.setup_script" lang="python" height='300px' class="scriptEdit"></Editor></div><div class='mod'><div class="add_code"><el-button @click='addSetupScript("func")' plain size="small">调用全局工具函数</el-button></div><div class="add_code"><el-button @click='addSetupScript("global")' plain size="small">设置全局变量</el-button></div><div class="add_code"><el-button @click='addSetupScript("env")' plain size="small">设置局部变量</el-button></div><div class="add_code"><el-button @click='addSetupScript("sql")' plain size="small">执行sql查询</el-button></div></div>
</div>
// 生成前置脚本
function addSetupScript(item) {if (item === "func") {caseData.setup_script += '# 调用全局工具函数random_mobile随机生成一个手机号码\nmobile = global_func.random_mobile()\n'} else if (item === "global") {caseData.setup_script += '# 设置局部变量\ntest.save_global_variable("变量名","变量值")\n'} else if (item === "env") {caseData.setup_script += '# 设置局部变量\ntest.save_env_variable("变量名","变量值")\n'} else if (item === "sql") {caseData.setup_script +='# ----执行sql语句(需要在环境中配置数据库连接信息)----\n # db.连接名.execute_all(sql语句) \nsql = "SELECT count(*) as count FROM futureloan.member"\nres = db.hwyun.execute_all(sql)\n'}
}

4. 请求头
同样代码编辑器
<el-collapse-item name="4"><template #title><img src="@/assets/icons/keyhole.png" width="20"><b>请求头</b></template><Editor lang="json" v-model="caseData.headers"></Editor>
</el-collapse-item>

5.查询参数
<el-collapse-item name="5"><template #title><img src="@/assets/icons/API_api.png" width="20"><b>查询参数</b></template><Editor lang="json" v-model="caseData.request.params"></Editor></el-collapse-item>

6. 请求体(Get请求不可点击)
get请求禁用了,然后如果是文件类型数据,复用之前的FormData组件
<el-collapse-item name="6" :disabled="caseData.interface.method=='get'"><template #title><img src="@/assets/icons/body.png" width="20"><b>请求体</b></template><el-radio-group v-model="bodyType"><el-radio-button label="json">Json</el-radio-button><el-radio-button label="data">X-www-form-urlencoded</el-radio-button><el-radio-button label="form-data">Form-data</el-radio-button></el-radio-group><!-- json参数 --><div v-if='bodyType==="json"'><Editor lang="json" v-model="caseData.request.json"></Editor></div><div v-else-if='bodyType==="data"'><Editor lang="json" v-model="caseData.request.data"></Editor></div><div v-else><FromData v-model="file"></FromData></div>
</el-collapse-item>

7.后置脚本(同前置脚本)
<el-collapse-item name="7"><template #title><img src="@/assets/icons/instruction.png" width="20"><b>后置断言脚本</b></template><div class='script_code'><div class="code"><Editor v-model="caseData.teardown_script" lang="python" height='300px' ></Editor></div><div class='mod'><el-scrollbar height="300px"><div class="add_code"><el-button @click="addTearDownCodeMod('getBody')" plain size="small">获取响应体</el-button></div><div class="add_code"><el-button @click="addTearDownCodeMod('http')" plain size="small">HTTP状态码断言</el-button></div> <div class="add_code"><el-button @click="addTearDownCodeMod('contain')" plain size="small">断言包含</el-button><!-- 省略 .... --></div></el-scrollbar></div></div>
</el-collapse-item>

8.悬浮操作按钮
与测试环境页面一样,使用 Affix 固钉 组件
https://element-plus.org/zh-CN/component/affix.html#affix-%E5%9B%BA%E9%92%89
<el-affix :offset="40" position="bottom"><div class="btns"><el-button @click='runCase' type="primary" plain size="small" icon='Promotion'>运行</el-button><el-button @click='copyCase' type="primary" plain size="small" icon='DocumentCopy'>复制</el-button><el-button @click='saveCase' type="primary" plain size="small" icon='FolderChecked'>保存</el-button><el-button @click='clickDelete' type="danger" plain size="small" icon='Delete'>删除</el-button></div>
</el-affix>
页面功能实现
1. 点击获取接口用例详情
在之前一节,左侧显示了用例列表。并且点击某个用例,实现了点击方法@click='selectCase(_case.id)',也就是function selectCase(id) { activeCase.value = id }将activeCase 赋值了。
而在右侧,显示用例详情页,把activeCase值传给了CaseEditor这个组件
<div class="card right_box"><CaseEditor :case_id='activeCase'></CaseEditor>
</div>
然后在CaseEditor组件定义props接收传递的值,然后监听这个值变化,就请求获取用例详情。
const props = defineProps({case_id: ""
})// 侦听case_id的变化
watch(() => props.case_id, (val) => {if (val !== '') {getCaseInfo(val)}
})if (props.case_id != undefined) {getCaseInfo(props.case_id)
}// 调用获取详情的接口
async function getCaseInfo(id) {// console.log("获取详情:"+id)const response = await http.pro.getCaseInfoAPi(id)if (response.status === 200) {// 保存用例对象caseObj = response.data// 把用例数据绑定到编辑页面caseData.title = caseObj.titlecaseData.interface = caseObj.interfacecaseData.setup_script = caseObj.setup_scriptcaseData.file = caseObj.filecaseData.teardown_script = caseObj.teardown_scriptcaseData.headers = JSON.stringify(caseObj.headers, 0, 4)caseData.request.json = JSON.stringify(caseObj.request.json || {}, 0, 4)caseData.request.data = JSON.stringify(caseObj.request.data || {}, 0, 4)caseData.request.params = JSON.stringify(caseObj.request.params || {}, 0, 4)file.value = caseObj.file}// get请求默认不展示请求体,其他默认自动展开if (caseData.interface.method == 'get') {activeNames.value = ['1', '2']} else {activeNames.value = ['1', '2', '6']}// console.log(activeNames)// 根据请求体信息,默认选中对应的拦if (caseData.request.json != '{}') {bodyType.value = 'json'} else if (caseData.request.data != '{}') {bodyType.value = 'data'} else if (caseData.file.length != 0) {bodyType.value = 'form-data'}
}
2.保存用例
编辑好数据后,都是双向绑定的,直接组成参数调用api就行了。
// 保存用例
async function saveCase() {if (caseData.headers == '') {caseData.headers = '{}'} else if (caseData.request.params == '') {caseData.request.params = '{}'} else if (caseData.request.json == '') {caseData.request.json = '{}'} else if (caseData.request.data == '') {caseData.request.data = '{}'}// 准备参数const params = {title: caseData.title,headers: JSON.parse(caseData.headers),request: {params: JSON.parse(caseData.request.params),},setup_script: caseData.setup_script,teardown_script: caseData.teardown_script,}if (caseData.interface.method != 'get') {// console.log('!get')if (bodyType.value === 'json') {params.request.json = JSON.parse(caseData.request.json)} else if (bodyType.value === 'data') {params.request.data = JSON.parse(caseData.request.data)} else {params.file = file.value}}// 调用修改用例的接口const response = await api.updateCaseApi(props.case_id, params)if (response.status === 200) {ElNotification({title: '保存成功',type: 'success',})// 刷新页面数据pstore.getInterFaceList()}
}
3. 删除用例
和之前的删除方法没有什么区别,有个二次确认弹窗。然后删除过后,把页面数据清空。
// 删除测试用例的方法
function clickDelete() {ElMessageBox.confirm('删除操作不可恢复,请确认是否要删除该测试用例?','提示', {confirmButtonText: '确认',cancelButtonText: '取消',type: 'warning',}).then(async () => {// 调用后端接口进行删除const response = await http.pro.deleteCaseApi(props.case_id)if (response.status === 204) {ElNotification({title: '删除成功',type: 'success',})// 刷新页面数据pstore.getInterFaceList()resetData()}}).catch(() => {ElNotification({type: 'info',title: '已取消删除操作',})})
}function resetData() {// 清空页面编辑的数据caseData.title = ''caseData.interface = {method: "get",url: ""}caseData.setup_script = ''caseData.file = []caseData.teardown_script = ''caseData.headers = ''caseData.request.json = "{}"caseData.request.data = "{}"caseData.request.params = "{}"caseObj = {}
}
4. 复制用例
与新增测试环境一样,在名字后面+copy,其他内容都保持不变
// 复制用例
async function copyCase() {const response = await http.pro.createCaseApi({title: caseObj.title + '-COPY',interface: caseObj.interface.id})if (response.status === 201) {ElNotification({title: '复制成功',type: 'success',})// 刷新页面数据pstore.getInterFaceList()}
}
5. 运行用例
运行结果用抽屉组件展示,展示内容就是之前调试运行时的Result组件
<!-- 测试用例运行的结果 --><el-drawer v-model="isShowDrawer" size="50%"><template #header><b>运行结果</b></template><template #default><Result :result='responseData'></Result></template></el-drawer>
// 保存用例运行的结果
let responseData = ref({})
// 是否显示结果的窗口
let isShowDrawer = ref(false)async function runCase() {// 准备参数const params = {env: pstore.env,cases: {title: caseData.title,interface: caseData.interface,headers: JSON.parse(caseData.headers),request: {params: JSON.parse(caseData.request.params),},setup_script: caseData.setup_script,teardown_script: caseData.teardown_script,}}// console.log(params.cases.interface.method)if (params.cases.interface.method != 'get') {if (bodyType.value === 'json') {params.cases.request.json = JSON.parse(caseData.request.json)} else if (bodyType.value === 'data') {params.cases.request.data = JSON.parse(caseData.request.data)} else {params.cases.file = caseData.file}}// console.log(params.cases.request)// 调用运行用例的接口const response = await http.run.runInterFaceCaseApi(params)if (response.status === 200) {// console.log('运行成功')responseData.value = response.data// 展示执行结果isShowDrawer.value = true}
}

到此页面功能实现完成。
小优化,增加loading
刚才运行时,受网络问题,一直没结果。所以,就增加一个loading效果
同样使用了element的loading组件
https://element-plus.org/zh-CN/component/loading.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%8A%A0%E8%BD%BD%E4%B8%AD%E7%BB%84%E4%BB%B6%E5%86%85%E5%AE%B9
给页面绑定loading相关数据
<el-collapse v-model="activeNames" v-loading="scrennLoading" element-loading-text="运行中..." element-loading-background="rgba(122, 122, 122, 0.8)">
然后运行时,显示loading,运行结束再隐藏loading
const scrennLoading = ref(false)async function runCase() {// 显示loadingscrennLoading.value = true。。。// 隐藏loadingscrennLoading.value = false
}

总结
复用之前的组件以减少开发量。所以一个经常会用到的组件,最好单独抽出来。以便后续使用。
然后用了cursor,没次数了。又尝试了一下Trae,也是挺不错的。遇到问题向Ai求助真是泰裤辣!

相关文章:
Vue接口平台学习十——接口用例页面2
效果图及简单说明 左边选择用例,右侧就显示该用例的详细信息。 使用el-collapse折叠组件,将请求到的用例详情数据展示到页面中。 所有数据内容,绑定到caseData中 // 页面绑定的用例编辑数据 const caseData reactive({title: "",…...
目标检测中的损失函数(二) | BIoU RIoU α-IoU
BIoU来自发表在2018年CVPR上的文章:《Improving Object Localization With Fitness NMS and Bounded IoU Loss》 论文针对现有目标检测方法只关注“足够好”的定位,而非“最优”的框,提出了一种考虑定位质量的NMS策略和BIoU loss。 这里不赘…...
SpringAI系列 - MCP篇(一) - 什么是MCP
目录 一、引言二、MCP核心架构三、MCP传输层(stdio / sse)四、MCP能力协商机制(Capability Negotiation)五、MCP Client相关能力(Roots / Sampling)六、MCP Server相关能力(Prompts / Resources / Tools)一、引言 之前我们在接入大模型时,不同的大模型通常都有自己的…...
Linux 入门十一:Linux 网络编程
一、概述 1. 网络编程基础 网络编程是通过网络应用编程接口(API)编写程序,实现不同主机上进程间的信息交互。它解决的核心问题是:如何让不同主机上的程序进行通信。 2. 网络模型:从 OSI 到 TCP/IP OSI 七层模型&…...
沐渥氮气柜控制板温湿度氧含量氮气流量四显智控系统
氮气柜控制板通常用于实时监控和调节柜内环境参数,确保存储物品如电子元件、精密仪器、化学品等,处于低氧、干燥的稳定状态。以下是沐渥氮气柜控制板核心参数的详细介绍及控制逻辑: 一、控制板核心参数显示模块 1)温度显示&am…...
vue3 主题模式 结合 element-plus的主题
vue3 主题模式 结合 element-plus的主题 npm i element-plus --save-dev在 Vue 3 中,实现主题模式主要有以下几种方式 1.使用 CSS 变量(自定义属性) CSS 变量是一种在 CSS 中定义可重用值的方式。在主题模式中,可以将颜色、字体…...
Redis 有序集合(Sorted Set)
Redis 有序集合(Sorted Set) 以下从基础命令、内部编码和使用场景三个维度对 Redis 有序集合进行详细解析: 一、基础命令 命令时间复杂度命令含义zadd key score member [score member …] O ( k l o g ( n ) ) O(klog(n)) O(klog(n))&…...
[c语言日寄]免费文档生成器——Doxygen在c语言程序中的使用
【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋:这是一个专注于C语言刷题的专栏,精选题目,搭配详细题解、拓展算法。从基础语法到复杂算法,题目涉及的知识点全面覆盖,助力你系统提升。无论你是初学者,还是…...
QtCreator的设计器、预览功能能看到程序图标,编译运行后图标消失
重新更换虚拟机(Vmware Kylin),重新编译和配置了很多第三方库后,将代码跑到新的这个虚拟机环境中,但是出现程序图标不可见,占位也消失,后来继续检查ui文件,ui文件图标也异常&#x…...
QT文件和文件夹拷贝操作
1.拷贝文件夹 //(源文件目录路劲,目的文件目录,文件存在是否覆盖) bool copyDirectory(const QString& srcPath, const QString& dstPath, bool coverFileIfExist) { QDir srcDir(srcPath); QDir dstDir(dstPath); if (!dstDir.exi…...
面试常用基础算法
目录 快速排序归并排序堆排序 n n n皇后问题最大和子数组爬楼梯中心扩展法求最长回文子序列分割回文串动态规划求最长回文子序列最长回文子串单调栈双指针算法修改 分割回文串滑动窗口栈 快速排序 #include <iostream> #include <algorithm>using namespace std;…...
Python-24:小R的随机播放顺序
问题描述 小R有一个特殊的随机播放规则。他首先播放歌单中的第一首歌,播放后将其从歌单中移除。如果歌单中还有歌曲,则会将当前第一首歌移到最后一首。这个过程会一直重复,直到歌单中没有任何歌曲。 例如,给定歌单 [5, 3, 2, 1,…...
悬空引用和之道、之禅-《分析模式》漫谈57
DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 “Analysis Patterns”的第5章“对象引用”原文: Unless you can catch all such references, there is the risk of a dangling reference, which often has painful con…...
Python accumulate 函数详解
https://docs.python.org/zh-cn/3/library/itertools.html#itertools.accumulate 在 Python 中,accumulate 是一个生成器(generator), 是来自 itertools 模块的一个函数。 它的作用是返回一个迭代器,该迭代器生成输入数据的累积结…...
Cursor可视化大屏搭建__0420
主题:用Cursor怎么进行数据洞察,做AI预测化内容。 Python基础语法与AI python生态强大,代码简洁,相对其他语言Python更好上手,浙江高考将Python列为可选科目 科学计算:Sklearn,Numpy,Pandas 人工智能:Tensorflow,Pytorch 网络爬虫:Scrapy…...
【初阶数据结构】树——二叉树(上)
文章目录 目录 前言 一、树 1.树的概念与结构 2.树相关术语 3.树的表示 二、二叉树 1.概念与结构 2.特殊的二叉树 3.二叉树存储结构 总结 前言 本篇带大家学习一种非线性数据结构——树,简单认识树和二叉数以及了解二叉树的存储结构。 一、树 1.树的概念与结构 树…...
ECharts散点图-散点图14,附视频讲解与代码下载
引言: ECharts散点图是一种常见的数据可视化图表类型,它通过在二维坐标系或其它坐标系中绘制散乱的点来展示数据之间的关系。本文将详细介绍如何使用ECharts库实现一个散点图,包括图表效果预览、视频讲解及代码下载,让你轻松掌握…...
C++中的算术转换、其他隐式类型转换和显示转换详解
C中的类型转换(Type Conversion)是指将一个数据类型的值转换为另一个数据类型的过程,主要包括: 一、算术类型转换(Arithmetic Conversions) 算术类型转换通常发生在算术运算或比较中,称为**“标…...
GAIA-2:用于自动驾驶的可控多视图生成世界模型
25年3月来自英国创业公司 Wayze 的论文“GAIA-2: A Controllable Multi-View Generative World Model for Autonomous Driving”。(注:23年9月其发布GAIA-1) 生成模型为模拟复杂环境提供一种可扩展且灵活的范例,但目前的方法不足…...
(一)CMake / MsBuild Ninja Make/ MSVC g++ clang++ 等c++编译概念解释
c 几个编译概念 一 概念二 层级关系总结2.1层级表格2.2 关键点说明2.3 示例流程(以 Ninja 为例)2.4 示例流程(Windows 平台) 三 总结 一 概念 CMake 通过 CMakeLists.txt 生成不同平台的构建文件(如 .sln、build.n…...
创建 Node.js Playwright 项目:从零开始搭建自动化测试环境
一、环境准备 在开始创建 Playwright 项目之前,确保你的电脑上已经安装了以下工具: Node.js:Playwright 依赖于 Node.js 环境,确保你已经安装了最新版本的 Node.js。可以通过以下命令检查是否安装成功: node -v npm -…...
浅谈AI致幻
文章目录 当前形势下存在的AI幻觉(AI致幻)什么是AI幻觉AI幻觉的类型为什么AI会产生幻觉AI幻觉的危害与影响当前应对AI幻觉的技术与方法行业与学术界的最新进展未来挑战与展望结论 当前形势下存在的AI幻觉(AI致幻) 什么是AI幻觉 …...
postman乘法计算,变量赋值
postman脚本怎么计算乘法 在Postman中,你可以通过多种方式计算乘法,这取决于你的具体需求。例如,如果你想在发送请求前计算乘法结果,或者在测试标签中计算响应数据的乘法,下面是一些常见的方法。 1. 使用JavaScript代…...
自定义错误码的必要性
为什么要使用错误码,直接返回一个错误信息不好么? 下面介绍一下,在程序开发中使用错误码的必要性~ 便于排查问题 想象你开了一家奶茶店,顾客下单后可能出现各种问题: 没珍珠了(错误码:50…...
车载软件架构 --- 二级boot设计说明需求规范
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 周末洗了一个澡,换了一身衣服,出了门却不知道去哪儿,不知道去找谁,漫无目的走着,大概这就是成年人最深的孤独吧! 旧人不知我近况,新人不知我过…...
管理杂谈——采石矶大捷的传奇与启示
南宋抗金史上,岳飞与岳家军的铁血传奇家喻户晓,但另一位力挽狂澜的“文官战神”却常被忽视——他从未掌兵,却在南宋存亡之际整合溃军,以少胜多,缔造采石矶大捷。此人正是虞允文。一介书生何以扭转乾坤?他的…...
Java高效合并Excel报表实战:GcExcel让数据处理更简单
前言:为什么需要自动化合并Excel? 在日常办公场景中,Excel报表合并是数据分析的基础操作。根据2023年企业办公效率报告显示: 财务人员平均每周花费6.2小时在Excel合并操作上人工合并的错误率高达15%90%的中大型企业已采用自动化…...
第十四届蓝桥杯 2023 C/C++组 平方差
目录 题目: 题目描述: 题目链接: 思路: 核心思路: 第一种思路: 第二种思路: 坑点: 代码: 数学找规律 O(n) 50分代码详解: O(1)满分代码详解&#x…...
前端路由缓存实现
vue3缓存实现完整版,查看这篇设计和实现方式吧,更完整...
I/O复用函数的使用——select
I/O复用函数的使用——select 目录 一、概念 二、select接口 2.1 基础概念 2.2 使用 select 函数的标准输入读取代码 2.3 基于 select 模型的多客户端 TCP 服务器实现 一、概念 i/o复用使得程序能同时监听多个文件描述符,可以提高程序性能。 之前为了让服务器能…...
