插件+修改源代码方式增加allure报告功能

📅 2026/6/17 19:13:02
插件+修改源代码方式增加allure报告功能
背景在文章《如何在allure报告中增加新的用例状态》与《js动态向allure报告用例详情页注入状态转换按钮》中分别介绍了如何往原生的allure报告里面增加自定义用例状态与用例状态扭转按钮但是两篇文章都都是在原始报告文件上进行修改如果继续增加新的功能会对原始文件侵入太多所以本文将介绍一种插件的方式往原生allure报告里面增加自定义功能减少对源文件的修改的同时方便扩展。新增功能新增自定义用例状态新增用例状态扭转按钮与备注输入框新增失败用例缓存生成按钮实现方案1. 增加插件在allure报告插件目录plugins/下创建插件文件夹tailor-made,文件夹下新增文件made.js与made.css文件内容如下allure-report/# 【展示】最终生成的可视化报告目录静态网站├── index.html# 报告的首页入口必须通过本地服务打开├── app.js# 前端核心渲染逻辑与框架资源├── styles.css# 报告的样式文件├── plugins/# 插件目录│ └── tailor-made# 自定义插件目录│ ├── made.js# 实现功能注入│ └── made.css# 注入控件样式made.js// 获取当前报告idfunctiongetReportId(){// /allure/10001_25_allure-report/ -- 10001_25_allure-reportvarmwindow.location.pathname.match(/\/([^\/])\/?$/)returnm?m[1]:null;}// 复制到剪贴板functioncopyToClipboard(text){// 动态创建临时输入框用完即删不占页面空间consttempInputdocument.createElement(input);tempInput.valuetext;document.body.appendChild(tempInput);// 选中复制兼容性拉满tempInput.select();constsuccessdocument.execCommand(copy);// 清理临时元素document.body.removeChild(tempInput);// 用原生alert提示结果alert(success?✅ 内容已复制至剪切板\n${text}:❌ 复制失败请手动复制);}// 封装一个通用的 POST 请求函数asyncfunctionsendPostRequest(url,data){try{constresponseawaitfetch(url,{method:POST,headers:{Content-Type:application/json// 指定提交的数据格式为 JSON},body:JSON.stringify(data)// 将传递进来的参数对象转换为 JSON 字符串});if(!response.ok){thrownewError(请求失败状态码${response.status});}// 如果服务器返回的是 JSON 数据可以解析后返回如果不需要返回数据这一步可省略constresultawaitresponse.json();returnresult;}catch(error){console.error(POST 请求出错:,error);throwerror;// 将错误继续抛出交给调用者处理}}// 用例增加状态转换按钮(function(){// 获取当前用例 uidfunctiongetCurrentUid(){// #categories/db923e8926a341803448fb09fd557b9e/47f029ca0aa9e5e2/ -- db923e8926a341803448fb09fd557b9e 47f029ca0aa9e5e2varmwindow.location.hash.match(/#.*\/([^\/])\/([^\/])/);returnm?[m[1],m[2]]:[null,null];}// 创建按钮functioncreateElement(){varreport_idgetReportId()if(!report_id)return;varuidsgetCurrentUid();if(!uids[0]||!uids[1])return;vartargetElementdocument.querySelector(.test-result-overview__tags);varnewElementdocument.querySelector(.custom-action-box);if(targetElement!newElement){// 2. 创建一个容器 div用来包裹输入框和两个按钮方便控制布局constcontainerdocument.createElement(div);// 给容器加个类名方便后续写 CSS 样式container.classNamecustom-action-box;// 3. 创建输入框constinputdocument.createElement(input);input.typetext;input.placeholder请输入内容...;// 设置输入框样式让它和按钮有点间距input.style.marginLeft16px;input.style.marginRight10px;// 4. 创建“标记通过”按钮constpassBtndocument.createElement(button);passBtn.innerText标记通过;passBtn.typebutton;// 加上这一行防止触发表单默认提交passBtn.style.marginRight3px;// 绑定点击事件passBtn.onclickasyncfunction(){text_strinput.value||passBtn.innerText// 1. 准备参数constrequestData{desc:text_str,status:passed,uid:uids[1],report_id:report_id};try{// 2. 调用封装好的函数传入接口地址和参数constresultawaitsendPostRequest(/allure/edit,requestData);// 3. 请求成功并等待执行完成后提示并刷新页面console.info(状态扭转成功);location.reload();}catch(error){// 4. 处理请求失败的情况console.error(操作失败请稍后重试。);}};// 5. 创建“标记失败”按钮constfailBtndocument.createElement(button);failBtn.innerText已排查;failBtn.typebutton;// 加上这一行防止触发表单默认提交// 绑定点击事件failBtn.onclickasyncfunction(){text_strinput.value||failBtn.innerText// 1. 准备参数constrequestData{desc:text_str,status:checked,uid:uids[1],report_id:report_id};try{// 2. 调用封装好的函数传入接口地址和参数constresultawaitsendPostRequest(/allure/edit,requestData);// 3. 请求成功并等待执行完成后提示并刷新页面console.info(状态扭转成功);location.reload();}catch(error){// 4. 处理请求失败的情况console.error(操作失败请稍后重试。);}};// 6. 将输入框和按钮依次添加到容器中container.appendChild(input);container.appendChild(passBtn);container.appendChild(failBtn);// 7. 将整个容器插入到目标标签的后面 (afterend 表示在元素自身的后面插入)targetElement.insertAdjacentElement(afterend,container);}return;}// 监听路由变化varlastHash;functioncheckRoute(){varhwindow.location.hash;if(h!lastHash/^#.*\//.test(h)){// #xxxx/ 这样的路由才能匹配成功lastHashh;setTimeout(function(){createElement();},300);}else{lastHash;}}// 多种方式监听window.addEventListener(hashchange,checkRoute);setInterval(checkRoute,500);})();// 增加生成缓存按钮(function(){// 等待 DOM 加载完成window.addEventListener(DOMContentLoaded,function(){varreport_idgetReportId()if(!report_id)return;varnewElementdocument.getElementById(custom-float-btn);if(newElement)return;// 1. 动态创建按钮元素constbtndocument.createElement(div);btn.idcustom-float-btn;// 修改按钮内容btn.innerHTMLspan stylefont-size: 21px;生成缓存/span;// 2. 样式made.css样式文件注入// 3. 绑定点击事件btn.onclickasyncfunction(){constrequestData{report_id:report_id};try{constresultawaitsendPostRequest(/allure/make_cache,requestData);copyToClipboard(缓存下载地址${result.downloadURL}\n用例数${result.caseNum})console.info(缓存下载地址${result.downloadURL}\n用例数${result.caseNum});}catch(error){// 4. 处理请求失败的情况alert(缓存生成失败请联系管理员);}};// 4. 将按钮添加到页面 body 中document.body.appendChild(btn);});})();made.css.alert_status_checked{background:#4ecfca}.bar__fill_status_checked{background:#4ecfca}.label_status_checked{background:#4ecfca}.text_status_checked{color:#4ecfca}.message_status_checked{border-color:#4ecfca}.status-details_status_checked{background:#4ecfca}.status-details_status_checked{border-color:#4ecfca}.status-details_status_checked{background:#4ecfca}.chart__legend-icon_status_checked{background:#4ecfca}.chart__fill_status_checked{fill:#4ecfca}.y-label_status_checked{background:#4ecfca}.n-label_status_checked{color:#4ecfca}#custom-float-btn{position:fixed;right:30px;bottom:30px;padding:12px 24px;/* 药丸按钮需要左右内边距 */background-color:#4CAF50;color:white;border-radius:50px;/* 药丸形状的关键设置足够大的圆角 */display:flex;align-items:center;justify-content:center;box-shadow:0 4px 8pxrgba(0,0,0,0.3);cursor:pointer;z-index:9999;transition:transform 0.2s ease,background-color 0.2s ease;font-size:16px;font-weight:bold;white-space:nowrap;/* 防止文字换行 */user-select:none;/* 防止双击时选中文字 */}2. 修改原报告文件app.js 增加用例状态由于用例状态需要在app.js中显示声明所以这一点修改无法动态注入所以只能修改原始文件可参考《如何在allure报告中增加新的用例状态》中介绍的app.js 文件改动index.html 导入插件效果