ui自动化报表截图查看

This commit is contained in:
2025-05-28 18:20:06 +08:00
parent e5dc3bab05
commit a9d0f68f52
4 changed files with 94 additions and 24 deletions

View File

@@ -1,5 +1,9 @@
package com.test.test.controller;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import com.test.test.domain.UiReport;
@@ -7,14 +11,7 @@ import com.test.test.service.IUiReportService;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import com.test.common.annotation.Log;
import com.test.common.core.controller.BaseController;
import com.test.common.core.domain.AjaxResult;
@@ -70,4 +67,28 @@ public class UiReportController extends BaseController
{
return toAjax(uiReportService.deleteUiReportByIds(ids));
}
@GetMapping("/screenshot")
public void getScreenshot(@RequestParam String path, HttpServletResponse response) throws IOException {
File file = new File(path);
if (!file.exists()) {
try {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
} catch (IOException e) {
throw new RuntimeException(e);
}
return;
}
response.setContentType("image/png");
try (FileInputStream in = new FileInputStream(file);
OutputStream out = response.getOutputStream()) {
byte[] buffer = new byte[4096];
int length;
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
}
}
}

View File

@@ -424,13 +424,14 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
Thread.sleep(beforeAwaitTime);
}
// 3. 执行具体步骤
stepExecution.execute(step, seleniumUtils);
if (screenshotConfiguration == 1) {
report.setScreenshot(seleniumUtils.takeScreenshotAsFile(TestConfig.getProfile()));
log.info("截图成功,路径:{}", seleniumUtils.takeScreenshotAsFile(TestConfig.getProfile()));
}
// 3. 执行具体步骤
stepExecution.execute(step, seleniumUtils);
// 执行后置等待
if (afterAwaitTime > 0) {
log.info("执行后置等待: {}ms", afterAwaitTime);

View File

@@ -24,3 +24,13 @@ export function getTestReportDetail(query) {
method: 'get',
})
}
// 测试报告 - 获取截图
export function getScreenshot(path) {
return request({
url: '/test/report/screenshot',
method: 'get',
params: { path },
responseType: 'blob'
})
}

View File

@@ -105,7 +105,7 @@
</div>
<div class="right-collapse">
<div>{{ item.take }}</div>
<el-button size="mini" type="text" @click.native.stop="clickHandleScreenshot">截图</el-button>
<el-button v-if="item.screenshot" size="mini" type="text" @click.native.stop="clickHandleScreenshot(item.screenshot)">截图</el-button>
<div class="collapse-status">
<div v-if="item.executionFlag === '1'">成功</div>
<div v-if="item.executionFlag === '0'">未执行</div>
@@ -148,7 +148,7 @@
</div>
<div class="right-collapse">
<div>{{ item.take }}</div>
<el-button size="mini" type="text" @click.native.stop="clickHandleScreenshot">截图</el-button>
<el-button v-if="item.screenshot" size="mini" type="text" @click.native.stop="clickHandleScreenshot(item.screenshot)">截图</el-button>
<div class="collapse-status">
<div v-if="item.executionFlag === '1'">成功</div>
<div v-if="item.executionFlag === '0'">未执行</div>
@@ -191,7 +191,7 @@
</div>
<div class="right-collapse">
<div>{{ item.take }}</div>
<el-button size="mini" type="text" @click.native.stop="clickHandleScreenshot">截图</el-button>
<el-button v-if="item.screenshot" size="mini" type="text" @click.native.stop="clickHandleScreenshot(item.screenshot)">截图</el-button>
<div class="collapse-status">
<div v-if="item.executionFlag === '1'">成功</div>
<div v-if="item.executionFlag === '0'">未执行</div>
@@ -219,12 +219,25 @@
</el-tab-pane>
</el-tabs>
</div>
<!-- 图片预览对话框 -->
<el-dialog :visible.sync="dialogVisible" append-to-body width="80%" :close-on-click-modal="false">
<div v-loading="imageLoading" style="min-height: 200px;">
<el-image
v-if="previewUrl"
style="width: 100%"
:src="previewUrl"
:preview-src-list="[previewUrl]"
fit="contain"
/>
</div>
</el-dialog>
</div>
</template>
<script>
import * as echarts from 'echarts';
import { getTestReportDetail } from '../../../api/uiTest/testReport';
import { getTestReportDetail, getScreenshot } from '../../../api/uiTest/testReport';
export default {
name: "TestReportDetail",
@@ -233,10 +246,13 @@ export default {
return {
activeName: 'first',
uiSceneStepsAllReportVOList: [], // 全部
uiSceneStepsErrorReportVOList: [{ title: 'aaa', contentList: [{}, {}] }, { title: 'bbb', contentList: [{}, {}] }], // 失败
uiSceneStepsNotReportVOList: [{ title: 'aaa', contentList: [{}, {}] }, { title: 'bbb', contentList: [{}, {}] }], // 未执行
uiSceneStepsErrorReportVOList: [], // 失败
uiSceneStepsNotReportVOList: [], // 未执行
active: 'first',
detailData: {}, // 详情内容
dialogVisible: false, // 图片预览对话框是否显示
previewUrl: '', // 预览图片的URL
imageLoading: false, // 图片加载状态
}
},
mounted() {
@@ -255,18 +271,40 @@ export default {
}
})
},
// 截图
clickHandleScreenshot() {
console.log('截图')
// 截图预览
async clickHandleScreenshot(screenshot) {
if (screenshot) {
try {
this.imageLoading = true;
this.dialogVisible = true;
// 获取图片数据
const response = await getScreenshot(screenshot);
// 创建 Blob URL
const blob = new Blob([response], { type: 'image/png' });
if (this.previewUrl) {
URL.revokeObjectURL(this.previewUrl); // 释放之前的 URL
}
this.previewUrl = URL.createObjectURL(blob);
} catch (error) {
this.$message.error('图片加载失败');
this.dialogVisible = false;
} finally {
this.imageLoading = false;
}
}
},
},
beforeDestroy() {
// 清理 Blob URL
if (this.previewUrl) {
URL.revokeObjectURL(this.previewUrl);
}
}
}
</script>
<style scoped lang="scss">
.report-detail {
padding: 20px;