ui自动化报表截图查看
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
package com.test.test.controller;
|
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 java.util.List;
|
||||||
|
|
||||||
import com.test.test.domain.UiReport;
|
import com.test.test.domain.UiReport;
|
||||||
@@ -7,14 +11,7 @@ import com.test.test.service.IUiReportService;
|
|||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
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 com.test.common.annotation.Log;
|
import com.test.common.annotation.Log;
|
||||||
import com.test.common.core.controller.BaseController;
|
import com.test.common.core.controller.BaseController;
|
||||||
import com.test.common.core.domain.AjaxResult;
|
import com.test.common.core.domain.AjaxResult;
|
||||||
@@ -70,4 +67,28 @@ public class UiReportController extends BaseController
|
|||||||
{
|
{
|
||||||
return toAjax(uiReportService.deleteUiReportByIds(ids));
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -424,13 +424,14 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
|||||||
Thread.sleep(beforeAwaitTime);
|
Thread.sleep(beforeAwaitTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 3. 执行具体步骤
|
||||||
|
stepExecution.execute(step, seleniumUtils);
|
||||||
|
|
||||||
if (screenshotConfiguration == 1) {
|
if (screenshotConfiguration == 1) {
|
||||||
report.setScreenshot(seleniumUtils.takeScreenshotAsFile(TestConfig.getProfile()));
|
report.setScreenshot(seleniumUtils.takeScreenshotAsFile(TestConfig.getProfile()));
|
||||||
log.info("截图成功,路径:{}", seleniumUtils.takeScreenshotAsFile(TestConfig.getProfile()));
|
log.info("截图成功,路径:{}", seleniumUtils.takeScreenshotAsFile(TestConfig.getProfile()));
|
||||||
}
|
}
|
||||||
// 3. 执行具体步骤
|
|
||||||
stepExecution.execute(step, seleniumUtils);
|
|
||||||
|
|
||||||
// 执行后置等待
|
// 执行后置等待
|
||||||
if (afterAwaitTime > 0) {
|
if (afterAwaitTime > 0) {
|
||||||
log.info("执行后置等待: {}ms", afterAwaitTime);
|
log.info("执行后置等待: {}ms", afterAwaitTime);
|
||||||
|
|||||||
@@ -24,3 +24,13 @@ export function getTestReportDetail(query) {
|
|||||||
method: 'get',
|
method: 'get',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 测试报告 - 获取截图
|
||||||
|
export function getScreenshot(path) {
|
||||||
|
return request({
|
||||||
|
url: '/test/report/screenshot',
|
||||||
|
method: 'get',
|
||||||
|
params: { path },
|
||||||
|
responseType: 'blob'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -105,7 +105,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="right-collapse">
|
<div class="right-collapse">
|
||||||
<div>{{ item.take }}</div>
|
<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 class="collapse-status">
|
||||||
<div v-if="item.executionFlag === '1'">成功</div>
|
<div v-if="item.executionFlag === '1'">成功</div>
|
||||||
<div v-if="item.executionFlag === '0'">未执行</div>
|
<div v-if="item.executionFlag === '0'">未执行</div>
|
||||||
@@ -148,7 +148,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="right-collapse">
|
<div class="right-collapse">
|
||||||
<div>{{ item.take }}</div>
|
<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 class="collapse-status">
|
||||||
<div v-if="item.executionFlag === '1'">成功</div>
|
<div v-if="item.executionFlag === '1'">成功</div>
|
||||||
<div v-if="item.executionFlag === '0'">未执行</div>
|
<div v-if="item.executionFlag === '0'">未执行</div>
|
||||||
@@ -191,7 +191,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="right-collapse">
|
<div class="right-collapse">
|
||||||
<div>{{ item.take }}</div>
|
<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 class="collapse-status">
|
||||||
<div v-if="item.executionFlag === '1'">成功</div>
|
<div v-if="item.executionFlag === '1'">成功</div>
|
||||||
<div v-if="item.executionFlag === '0'">未执行</div>
|
<div v-if="item.executionFlag === '0'">未执行</div>
|
||||||
@@ -219,12 +219,25 @@
|
|||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import * as echarts from 'echarts';
|
import * as echarts from 'echarts';
|
||||||
import { getTestReportDetail } from '../../../api/uiTest/testReport';
|
import { getTestReportDetail, getScreenshot } from '../../../api/uiTest/testReport';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "TestReportDetail",
|
name: "TestReportDetail",
|
||||||
@@ -233,10 +246,13 @@ export default {
|
|||||||
return {
|
return {
|
||||||
activeName: 'first',
|
activeName: 'first',
|
||||||
uiSceneStepsAllReportVOList: [], // 全部
|
uiSceneStepsAllReportVOList: [], // 全部
|
||||||
uiSceneStepsErrorReportVOList: [{ title: 'aaa', contentList: [{}, {}] }, { title: 'bbb', contentList: [{}, {}] }], // 失败
|
uiSceneStepsErrorReportVOList: [], // 失败
|
||||||
uiSceneStepsNotReportVOList: [{ title: 'aaa', contentList: [{}, {}] }, { title: 'bbb', contentList: [{}, {}] }], // 未执行
|
uiSceneStepsNotReportVOList: [], // 未执行
|
||||||
active: 'first',
|
active: 'first',
|
||||||
detailData: {}, // 详情内容
|
detailData: {}, // 详情内容
|
||||||
|
dialogVisible: false, // 图片预览对话框是否显示
|
||||||
|
previewUrl: '', // 预览图片的URL
|
||||||
|
imageLoading: false, // 图片加载状态
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@@ -255,18 +271,40 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 截图
|
// 截图预览
|
||||||
clickHandleScreenshot() {
|
async clickHandleScreenshot(screenshot) {
|
||||||
console.log('截图')
|
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>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.report-detail {
|
.report-detail {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
|||||||
Reference in New Issue
Block a user