parent
217c30be67
commit
f0e6bed4d9
|
@ -440,6 +440,11 @@
|
|||
<artifactId>xmindjbehaveplugin</artifactId>
|
||||
<version>0.8</version>
|
||||
</dependency>
|
||||
<!-- selenium包 -->
|
||||
<dependency>
|
||||
<groupId>org.seleniumhq.selenium</groupId>
|
||||
<artifactId>selenium-java</artifactId>
|
||||
</dependency>
|
||||
<!-- 基础包 -->
|
||||
<dependency>
|
||||
<groupId>io.metersphere</groupId>
|
||||
|
|
|
@ -7,8 +7,11 @@ import io.metersphere.api.dto.share.ShareInfoDTO;
|
|||
import io.metersphere.api.service.ApiDefinitionService;
|
||||
import io.metersphere.api.service.ShareInfoService;
|
||||
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
|
||||
import io.metersphere.base.domain.ReportStatisticsWithBLOBs;
|
||||
import io.metersphere.base.domain.ShareInfo;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.reportstatistics.dto.ReportStatisticsSaveRequest;
|
||||
import io.metersphere.reportstatistics.service.ReportStatisticsService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
@ -29,6 +32,8 @@ public class ShareInfoController {
|
|||
ShareInfoService shareInfoService;
|
||||
@Resource
|
||||
ApiDefinitionService apiDefinitionService;
|
||||
@Resource
|
||||
ReportStatisticsService reportStatisticsService;
|
||||
|
||||
@PostMapping("/selectApiSimpleInfo")
|
||||
public List<ApiDocumentInfoDTO> list(@RequestBody ApiDocumentRequest request) {
|
||||
|
@ -44,13 +49,13 @@ public class ShareInfoController {
|
|||
@PostMapping("/selectApiInfoByParam")
|
||||
public List<ApiDocumentInfoDTO> selectApiInfoByParam(@RequestBody ApiDocumentRequest request) {
|
||||
List<ApiDocumentInfoDTO> returnList = new ArrayList<>();
|
||||
if(request.getApiIdList() != null){
|
||||
if (request.getApiIdList() != null) {
|
||||
//要根据ids的顺序进行返回排序
|
||||
List<ApiDefinitionWithBLOBs> apiModels = apiDefinitionService.getBLOBs(request.getApiIdList());
|
||||
Map<String,ApiDefinitionWithBLOBs> apiModelMaps = apiModels.stream().collect(Collectors.toMap(ApiDefinitionWithBLOBs :: getId,a->a,(k1,k2)->k1));
|
||||
for(String id : request.getApiIdList()){
|
||||
Map<String, ApiDefinitionWithBLOBs> apiModelMaps = apiModels.stream().collect(Collectors.toMap(ApiDefinitionWithBLOBs::getId, a -> a, (k1, k2) -> k1));
|
||||
for (String id : request.getApiIdList()) {
|
||||
ApiDefinitionWithBLOBs model = apiModelMaps.get(id);
|
||||
if(model == null){
|
||||
if (model == null) {
|
||||
model = new ApiDefinitionWithBLOBs();
|
||||
model.setId(id);
|
||||
model.setName(id);
|
||||
|
@ -66,9 +71,9 @@ public class ShareInfoController {
|
|||
public ApiDocumentInfoDTO selectApiInfoById(@PathVariable String id) {
|
||||
ApiDefinitionWithBLOBs apiModel = apiDefinitionService.getBLOBs(id);
|
||||
ApiDocumentInfoDTO returnDTO = new ApiDocumentInfoDTO();
|
||||
try{
|
||||
try {
|
||||
returnDTO = shareInfoService.conversionModelToDTO(apiModel);
|
||||
}catch (Exception e){
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e);
|
||||
}
|
||||
returnDTO.setSelectedFlag(true);
|
||||
|
@ -88,4 +93,9 @@ public class ShareInfoController {
|
|||
ShareInfoDTO returnDTO = shareInfoService.conversionShareInfoToDTO(apiShare);
|
||||
return returnDTO;
|
||||
}
|
||||
|
||||
@PostMapping("/selectHistoryReportById")
|
||||
public ReportStatisticsWithBLOBs selectById(@RequestBody ReportStatisticsSaveRequest request) {
|
||||
return reportStatisticsService.selectById(request.getId());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -176,4 +176,5 @@ public class PermissionConstants {
|
|||
public static final String PROJECT_ENTERPRISE_REPORT_EDIT = "PROJECT_ENTERPRISE_REPORT:READ+EDIT";
|
||||
public static final String PROJECT_ENTERPRISE_REPORT_DELETE = "PROJECT_ENTERPRISE_REPORT:READ+DELETE";
|
||||
public static final String PROJECT_ENTERPRISE_REPORT_COPY = "PROJECT_ENTERPRISE_REPORT:READ+COPY";
|
||||
public static final String PROJECT_ENTERPRISE_REPORT_SCHEDULE = "PROJECT_ENTERPRISE_REPORT:READ+SCHEDULE";
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package io.metersphere.commons.constants;
|
||||
|
||||
public enum ScheduleGroup {
|
||||
API_TEST, PERFORMANCE_TEST, API_SCENARIO_TEST, TEST_PLAN_TEST, SWAGGER_IMPORT, ISSUE_SYNC
|
||||
API_TEST, PERFORMANCE_TEST, API_SCENARIO_TEST, TEST_PLAN_TEST, SWAGGER_IMPORT, ISSUE_SYNC,
|
||||
SCHEDULE_SEND_REPORT
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import java.util.Map;
|
|||
|
||||
public class ShiroUtils {
|
||||
|
||||
public static void loadBaseFilterChain(Map<String, String> filterChainDefinitionMap){
|
||||
public static void loadBaseFilterChain(Map<String, String> filterChainDefinitionMap) {
|
||||
|
||||
filterChainDefinitionMap.put("/resource/**", "anon");
|
||||
filterChainDefinitionMap.put("/*.worker.js", "anon");
|
||||
|
@ -53,9 +53,11 @@ public class ShiroUtils {
|
|||
//分享相关接口
|
||||
filterChainDefinitionMap.put("/share/info/generateShareInfoWithExpired", "anon");
|
||||
filterChainDefinitionMap.put("/share/info/selectApiInfoByParam", "anon");
|
||||
filterChainDefinitionMap.put("/share/info/selectHistoryReportById", "anon");
|
||||
filterChainDefinitionMap.put("/share/get/**", "anon");
|
||||
filterChainDefinitionMap.put("/share/info", "apikey, csrf, authc"); // 需要认证
|
||||
filterChainDefinitionMap.put("/document/**", "anon");
|
||||
filterChainDefinitionMap.put("/echartPic/**", "anon");
|
||||
filterChainDefinitionMap.put("/share/**", "anon");
|
||||
filterChainDefinitionMap.put("/sharePlanReport", "anon");
|
||||
|
||||
|
@ -82,14 +84,14 @@ public class ShiroUtils {
|
|||
filterChainDefinitionMap.put("/resource/md/get/**", "apikey, authc");
|
||||
}
|
||||
|
||||
public static Cookie getSessionIdCookie(){
|
||||
public static Cookie getSessionIdCookie() {
|
||||
SimpleCookie sessionIdCookie = new SimpleCookie();
|
||||
sessionIdCookie.setPath("/");
|
||||
sessionIdCookie.setName("MS_SESSION_ID");
|
||||
return sessionIdCookie;
|
||||
}
|
||||
|
||||
public static SessionManager getSessionManager(Long sessionTimeout, CacheManager cacheManager){
|
||||
public static SessionManager getSessionManager(Long sessionTimeout, CacheManager cacheManager) {
|
||||
DefaultWebSessionManager sessionManager = new CustomSessionManager();
|
||||
sessionManager.setSessionIdUrlRewritingEnabled(false);
|
||||
sessionManager.setDeleteInvalidSessions(true);
|
||||
|
|
|
@ -32,8 +32,13 @@ public class IndexController {
|
|||
return "document.html";
|
||||
}
|
||||
|
||||
@GetMapping(value = "/echartPic")
|
||||
public String echartPic() {
|
||||
return "share-enterprise-report.html";
|
||||
}
|
||||
|
||||
@GetMapping(value = "/sharePlanReport")
|
||||
public String shareRedirect() {
|
||||
return "share-plan-report.html";
|
||||
return "share-plan-report.html";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package io.metersphere.reportstatistics.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class HeadlessRequest {
|
||||
public String url;
|
||||
public String driverPath;
|
||||
}
|
|
@ -6,16 +6,20 @@ import io.metersphere.base.domain.ReportStatistics;
|
|||
import io.metersphere.base.domain.ReportStatisticsExample;
|
||||
import io.metersphere.base.domain.ReportStatisticsWithBLOBs;
|
||||
import io.metersphere.base.mapper.ReportStatisticsMapper;
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
import io.metersphere.reportstatistics.dto.ReportStatisticsSaveRequest;
|
||||
import io.metersphere.reportstatistics.dto.ReportStatisticsType;
|
||||
import io.metersphere.reportstatistics.dto.TestCaseCountTableDTO;
|
||||
import io.metersphere.dto.BaseSystemConfigDTO;
|
||||
import io.metersphere.reportstatistics.dto.*;
|
||||
import io.metersphere.reportstatistics.dto.charts.Series;
|
||||
import io.metersphere.reportstatistics.dto.table.TestCaseCountTableDataDTO;
|
||||
import io.metersphere.reportstatistics.dto.table.TestCaseCountTableItemDataDTO;
|
||||
import io.metersphere.reportstatistics.dto.table.TestCaseCountTableRowDTO;
|
||||
import io.metersphere.reportstatistics.utils.ChromeUtils;
|
||||
import io.metersphere.service.SystemParameterService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
|
@ -31,19 +35,21 @@ import java.util.UUID;
|
|||
public class ReportStatisticsService {
|
||||
@Resource
|
||||
private ReportStatisticsMapper reportStatisticsMapper;
|
||||
@Resource
|
||||
private TestCaseCountService testCaseCountService;
|
||||
|
||||
public ReportStatisticsWithBLOBs saveByRequest(ReportStatisticsSaveRequest request) {
|
||||
ReportStatisticsWithBLOBs model = new ReportStatisticsWithBLOBs();
|
||||
model.setId(UUID.randomUUID().toString());
|
||||
|
||||
String name = "用例分析报表";
|
||||
if(StringUtils.equalsIgnoreCase(ReportStatisticsType.TEST_CASE_COUNT.name(),request.getReportType())){
|
||||
if (StringUtils.equalsIgnoreCase(ReportStatisticsType.TEST_CASE_COUNT.name(), request.getReportType())) {
|
||||
name = "用例统计报表";
|
||||
model.setReportType(ReportStatisticsType.TEST_CASE_COUNT.name());
|
||||
}else {
|
||||
} else {
|
||||
model.setReportType(ReportStatisticsType.TEST_CASE_ANALYSIS.name());
|
||||
}
|
||||
if(StringUtils.isEmpty(request.getName())){
|
||||
if (StringUtils.isEmpty(request.getName())) {
|
||||
request.setName(name);
|
||||
}
|
||||
model.setName(request.getName());
|
||||
|
@ -66,23 +72,81 @@ public class ReportStatisticsService {
|
|||
}
|
||||
|
||||
public ReportStatisticsWithBLOBs selectById(String id) {
|
||||
ReportStatisticsWithBLOBs blob = reportStatisticsMapper.selectByPrimaryKey(id);
|
||||
JSONObject dataOption = JSONObject.parseObject(blob.getDataOption());
|
||||
ReportStatisticsWithBLOBs blob = reportStatisticsMapper.selectByPrimaryKey(id);
|
||||
JSONObject selectOption = JSONObject.parseObject(blob.getSelectOption());
|
||||
if(!dataOption.containsKey("showTable")){
|
||||
List<TestCaseCountTableDTO> dtos = JSONArray.parseArray(dataOption.getString("tableData"),TestCaseCountTableDTO.class);
|
||||
TestCaseCountTableDataDTO showTable = this.countShowTable(selectOption.getString("xaxis"), JSONArray.parseArray(selectOption.getString("yaxis"),String.class),dtos);
|
||||
dataOption.put("showTable",showTable);
|
||||
JSONObject dataOption = JSONObject.parseObject(blob.getDataOption());
|
||||
boolean isReportNeedUpdate = this.isReportNeedUpdate(blob);
|
||||
if (isReportNeedUpdate) {
|
||||
TestCaseCountRequest countRequest = JSONObject.parseObject(blob.getSelectOption(), TestCaseCountRequest.class);
|
||||
JSONObject returnDataOption = this.reloadDatas(countRequest, dataOption.getString("chartType"));
|
||||
if (returnDataOption != null) {
|
||||
dataOption = returnDataOption;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dataOption.containsKey("showTable")) {
|
||||
List<TestCaseCountTableDTO> dtos = JSONArray.parseArray(dataOption.getString("tableData"), TestCaseCountTableDTO.class);
|
||||
TestCaseCountTableDataDTO showTable = this.countShowTable(selectOption.getString("xaxis"), JSONArray.parseArray(selectOption.getString("yaxis"), String.class), dtos);
|
||||
dataOption.put("showTable", showTable);
|
||||
blob.setDataOption(dataOption.toString());
|
||||
}
|
||||
return blob;
|
||||
}
|
||||
|
||||
private JSONObject reloadDatas(TestCaseCountRequest request, String chartType) {
|
||||
if (StringUtils.isEmpty(chartType)) {
|
||||
chartType = "bar";
|
||||
}
|
||||
JSONObject returnObject = new JSONObject();
|
||||
TestCaseCountResponse testCaseCountResponse = testCaseCountService.getReport(request);
|
||||
if (testCaseCountResponse.getBarChartDTO() != null) {
|
||||
JSONObject loadOptionObject = new JSONObject();
|
||||
loadOptionObject.put("legend", JSONObject.toJSON(testCaseCountResponse.getBarChartDTO().getLegend()));
|
||||
loadOptionObject.put("xAxis", JSONObject.toJSON(testCaseCountResponse.getBarChartDTO().getXAxis()));
|
||||
loadOptionObject.put("xaxis", JSONObject.toJSON(testCaseCountResponse.getBarChartDTO().getXAxis()));
|
||||
loadOptionObject.put("yAxis", JSONObject.toJSON(testCaseCountResponse.getBarChartDTO().getYAxis()));
|
||||
loadOptionObject.put("tooltip", new JSONObject());
|
||||
loadOptionObject.put("lable", new JSONObject());
|
||||
if (!CollectionUtils.isEmpty(testCaseCountResponse.getBarChartDTO().getSeries())) {
|
||||
List<Series> list = testCaseCountResponse.getBarChartDTO().getSeries();
|
||||
for (Series model : list) {
|
||||
model.setType(chartType);
|
||||
}
|
||||
loadOptionObject.put("series", JSONArray.toJSON(list));
|
||||
}
|
||||
loadOptionObject.put("grid", new JSONObject().put("bottom", "75px"));
|
||||
returnObject.put("loadOption", loadOptionObject);
|
||||
}
|
||||
if (testCaseCountResponse.getPieChartDTO() != null) {
|
||||
JSONObject pieOptionObject = new JSONObject();
|
||||
pieOptionObject.put("title", JSONObject.toJSON(testCaseCountResponse.getPieChartDTO().getTitle()));
|
||||
pieOptionObject.put("xAxis", JSONObject.toJSON(testCaseCountResponse.getPieChartDTO().getXAxis()));
|
||||
if (!CollectionUtils.isEmpty(testCaseCountResponse.getPieChartDTO().getSeries())) {
|
||||
List<Series> list = testCaseCountResponse.getPieChartDTO().getSeries();
|
||||
for (Series model : list) {
|
||||
model.setType(chartType);
|
||||
}
|
||||
pieOptionObject.put("series", JSONArray.toJSON(list));
|
||||
}
|
||||
pieOptionObject.put("grid", new JSONObject().put("bottom", "75px"));
|
||||
if (testCaseCountResponse.getPieChartDTO().getWidth() > 0) {
|
||||
pieOptionObject.put("width", testCaseCountResponse.getPieChartDTO().getWidth());
|
||||
}
|
||||
returnObject.put("pieOption", pieOptionObject);
|
||||
}
|
||||
if (testCaseCountResponse.getTableDTOs() != null) {
|
||||
returnObject.put("tableData", JSONArray.toJSON(testCaseCountResponse.getTableDTOs()));
|
||||
}
|
||||
returnObject.put("chartType", chartType);
|
||||
return returnObject;
|
||||
}
|
||||
|
||||
private TestCaseCountTableDataDTO countShowTable(String groupName, List<String> yaxis, List<TestCaseCountTableDTO> dtos) {
|
||||
if(yaxis == null){
|
||||
if (yaxis == null) {
|
||||
yaxis = new ArrayList<>();
|
||||
}
|
||||
TestCaseCountTableDataDTO returnDTO = new TestCaseCountTableDataDTO();
|
||||
String [] headers = new String[]{groupName,"总计","testCase","apiCase","scenarioCase","loadCaseCount"};
|
||||
String[] headers = new String[]{groupName, "总计", "testCase", "apiCase", "scenarioCase", "loadCaseCount"};
|
||||
|
||||
List<TestCaseCountTableItemDataDTO> heads = new ArrayList<>();
|
||||
boolean showTestCase = true;
|
||||
|
@ -91,19 +155,19 @@ public class ReportStatisticsService {
|
|||
boolean showLoad = true;
|
||||
|
||||
for (String head : headers) {
|
||||
if(StringUtils.equalsAnyIgnoreCase(head,groupName,"总计") || yaxis.contains(head)){
|
||||
if (StringUtils.equalsAnyIgnoreCase(head, groupName, "总计") || yaxis.contains(head)) {
|
||||
TestCaseCountTableItemDataDTO headData = new TestCaseCountTableItemDataDTO();
|
||||
headData.setId(UUID.randomUUID().toString());
|
||||
headData.setValue(head);
|
||||
heads.add(headData);
|
||||
}else {
|
||||
if(StringUtils.equalsIgnoreCase(head,"testCase")){
|
||||
} else {
|
||||
if (StringUtils.equalsIgnoreCase(head, "testCase")) {
|
||||
showTestCase = false;
|
||||
}else if(StringUtils.equalsIgnoreCase(head,"apiCase")){
|
||||
} else if (StringUtils.equalsIgnoreCase(head, "apiCase")) {
|
||||
showApi = false;
|
||||
}else if(StringUtils.equalsIgnoreCase(head,"scenarioCase")){
|
||||
} else if (StringUtils.equalsIgnoreCase(head, "scenarioCase")) {
|
||||
showScenario = false;
|
||||
}else if(StringUtils.equalsIgnoreCase(head,"loadCaseCount")){
|
||||
} else if (StringUtils.equalsIgnoreCase(head, "loadCaseCount")) {
|
||||
showLoad = false;
|
||||
}
|
||||
}
|
||||
|
@ -123,28 +187,28 @@ public class ReportStatisticsService {
|
|||
countData.setValue(data.getAllCount());
|
||||
rowDataList.add(countData);
|
||||
|
||||
if(showTestCase){
|
||||
if (showTestCase) {
|
||||
TestCaseCountTableItemDataDTO itemData = new TestCaseCountTableItemDataDTO();
|
||||
itemData.setId(UUID.randomUUID().toString());
|
||||
itemData.setValue(data.getTestCaseCount());
|
||||
rowDataList.add(itemData);
|
||||
}
|
||||
|
||||
if(showApi){
|
||||
if (showApi) {
|
||||
TestCaseCountTableItemDataDTO itemData = new TestCaseCountTableItemDataDTO();
|
||||
itemData.setId(UUID.randomUUID().toString());
|
||||
itemData.setValue(data.getApiCaseCount());
|
||||
rowDataList.add(itemData);
|
||||
}
|
||||
|
||||
if(showScenario){
|
||||
if (showScenario) {
|
||||
TestCaseCountTableItemDataDTO itemData = new TestCaseCountTableItemDataDTO();
|
||||
itemData.setId(UUID.randomUUID().toString());
|
||||
itemData.setValue(data.getScenarioCaseCount());
|
||||
rowDataList.add(itemData);
|
||||
}
|
||||
|
||||
if(showLoad){
|
||||
if (showLoad) {
|
||||
TestCaseCountTableItemDataDTO itemData = new TestCaseCountTableItemDataDTO();
|
||||
itemData.setId(UUID.randomUUID().toString());
|
||||
itemData.setValue(data.getLoadCaseCount());
|
||||
|
@ -173,16 +237,38 @@ public class ReportStatisticsService {
|
|||
public List<ReportStatistics> selectByRequest(ReportStatisticsSaveRequest request) {
|
||||
ReportStatisticsExample example = new ReportStatisticsExample();
|
||||
ReportStatisticsExample.Criteria criteria = example.createCriteria();
|
||||
if(StringUtils.isNotEmpty(request.getProjectId())){
|
||||
if (StringUtils.isNotEmpty(request.getProjectId())) {
|
||||
criteria.andProjectIdEqualTo(request.getProjectId());
|
||||
}
|
||||
if(StringUtils.isNotEmpty(request.getReportType())){
|
||||
if (StringUtils.isNotEmpty(request.getReportType())) {
|
||||
criteria.andReportTypeEqualTo(request.getReportType());
|
||||
}
|
||||
if(StringUtils.isNotEmpty(request.getName())){
|
||||
if (StringUtils.isNotEmpty(request.getName())) {
|
||||
criteria.andNameLike(request.getName());
|
||||
}
|
||||
example.setOrderByClause("create_time DESC");
|
||||
return reportStatisticsMapper.selectByExample(example);
|
||||
return reportStatisticsMapper.selectByExample(example);
|
||||
}
|
||||
|
||||
public String getImageContentById(ReportStatisticsWithBLOBs reportRecordId) {
|
||||
ChromeUtils chromeUtils = new ChromeUtils();
|
||||
HeadlessRequest headlessRequest = new HeadlessRequest();
|
||||
|
||||
BaseSystemConfigDTO baseInfo = CommonBeanFactory.getBean(SystemParameterService.class).getBaseInfo();
|
||||
// 占位符
|
||||
String platformUrl = "http://localhost:8081";
|
||||
if (baseInfo != null) {
|
||||
platformUrl = baseInfo.getUrl();
|
||||
}
|
||||
platformUrl += "/echartPic?shareId=" + reportRecordId.getId();
|
||||
|
||||
headlessRequest.setUrl(platformUrl);
|
||||
String imageData = chromeUtils.getImageInfo(headlessRequest);
|
||||
return imageData;
|
||||
}
|
||||
|
||||
public boolean isReportNeedUpdate(ReportStatisticsWithBLOBs model) {
|
||||
JSONObject selectOption = JSONObject.parseObject(model.getSelectOption());
|
||||
return selectOption.containsKey("timeType") && StringUtils.equalsIgnoreCase("dynamicTime", selectOption.getString("timeType"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -496,6 +496,13 @@ public class TestCaseCountService {
|
|||
this.add("50%");
|
||||
}});
|
||||
|
||||
Map<String,Object> labelMap = new HashMap<>();
|
||||
Map<String,Object> normalMap = new HashMap<>();
|
||||
normalMap.put("show",true);
|
||||
normalMap.put("formatter","{b}: {c}({d}%)");
|
||||
labelMap.put("normal",normalMap);
|
||||
series.setLabel(labelMap);
|
||||
|
||||
Title title = new Title();
|
||||
title.setSubtext(summary.groupName);
|
||||
title.setLeft(leftPxStr);
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
package io.metersphere.reportstatistics.utils;
|
||||
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.reportstatistics.dto.HeadlessRequest;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openqa.selenium.JavascriptExecutor;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.chrome.ChromeDriver;
|
||||
import org.openqa.selenium.chrome.ChromeDriverService;
|
||||
import org.openqa.selenium.chrome.ChromeOptions;
|
||||
|
||||
public class ChromeUtils {
|
||||
private static final String DEFAULT_DRIVERPATH = "/Users/handsomesong/chromeDriver/chromedriver_mac64_m1/chromedriver";
|
||||
|
||||
private WebDriver genWebDriver(HeadlessRequest headlessRequest) {
|
||||
String driverPath = headlessRequest.driverPath;
|
||||
if (StringUtils.isEmpty(driverPath)) {
|
||||
driverPath = DEFAULT_DRIVERPATH;
|
||||
}
|
||||
//初始化一个chrome浏览器实例driver
|
||||
ChromeOptions options = new ChromeOptions();
|
||||
options.addArguments("headless");
|
||||
options.addArguments("no-sandbox");
|
||||
options.addArguments("disable-gpu");
|
||||
options.addArguments("disable-features=NetworkService");
|
||||
options.addArguments("ignore-certificate-errors");
|
||||
options.addArguments("silent-launch");
|
||||
options.addArguments("disable-application-cache");
|
||||
options.addArguments("disable-web-security");
|
||||
options.addArguments("no-proxy-server");
|
||||
options.addArguments("disable-dev-shm-usage");
|
||||
options.addArguments("lang=zh_CN.UTF-8");
|
||||
WebDriver driver = null;
|
||||
try {
|
||||
System.setProperty(ChromeDriverService.CHROME_DRIVER_EXE_PROPERTY, driverPath);
|
||||
driver = new ChromeDriver(options);
|
||||
driver.get(headlessRequest.url);
|
||||
driver.manage().window().fullscreen();
|
||||
}catch (Exception e){
|
||||
if(driver != null){
|
||||
driver.quit();
|
||||
driver = null;
|
||||
}
|
||||
LogUtil.error(e);
|
||||
}
|
||||
return driver;
|
||||
}
|
||||
|
||||
public String getImageInfo(HeadlessRequest request){
|
||||
WebDriver driver = this.genWebDriver(request);
|
||||
String files = null;
|
||||
if(driver != null){
|
||||
try {
|
||||
//预留echart动画的加载时间
|
||||
Thread.sleep(3 * 1000);
|
||||
String js = "var chartsCanvas = document.getElementById('picChart').getElementsByTagName('canvas')[0];" +
|
||||
"var imageUrl = null;" +
|
||||
"if (chartsCanvas!= null) {" +
|
||||
" imageUrl = chartsCanvas && chartsCanvas.toDataURL('image/png');"+
|
||||
"return imageUrl;" +
|
||||
"}";
|
||||
files = ((JavascriptExecutor)driver).executeScript(js).toString();
|
||||
}catch (Exception e){
|
||||
LogUtil.error(e);
|
||||
}finally {
|
||||
driver.quit();
|
||||
}
|
||||
}
|
||||
if(StringUtils.isNotEmpty(files)){
|
||||
return files;
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1 +1 @@
|
|||
Subproject commit a41ba52f5495bc68f84a07643442d2b0e9524786
|
||||
Subproject commit 9dd0111ebafcdab7153a97ab3a3af39f5c69dac5
|
|
@ -873,6 +873,12 @@
|
|||
"resourceId": "PROJECT_ENTERPRISE_REPORT",
|
||||
"license": true
|
||||
},
|
||||
{
|
||||
"id": "PROJECT_ENTERPRISE_REPORT:READ+SCHEDULE",
|
||||
"name": "定时发送",
|
||||
"resourceId": "PROJECT_ENTERPRISE_REPORT",
|
||||
"license": true
|
||||
},
|
||||
{
|
||||
"id": "PROJECT_ENTERPRISE_REPORT:READ+EDIT",
|
||||
"name": "修改报告",
|
||||
|
|
|
@ -165,6 +165,9 @@ export default {
|
|||
if (this.paramRow.redirectFrom == 'testPlan') {
|
||||
paramTestId = this.paramRow.id;
|
||||
this.scheduleTaskType = "TEST_PLAN_TEST";
|
||||
} else if (this.paramRow.redirectFrom == 'enterpriseReport') {
|
||||
paramTestId = this.paramRow.id;
|
||||
this.scheduleTaskType = "ENTERPRISE_REPORT";
|
||||
} else {
|
||||
paramTestId = this.paramRow.id;
|
||||
this.scheduleTaskType = "API_SCENARIO_TEST";
|
||||
|
@ -192,6 +195,9 @@ export default {
|
|||
if (row.redirectFrom == 'testPlan') {
|
||||
paramTestId = row.id;
|
||||
this.scheduleTaskType = "TEST_PLAN_TEST";
|
||||
} else if (row.redirectFrom == 'enterpriseReport') {
|
||||
paramTestId = row.id;
|
||||
this.scheduleTaskType = "ENTERPRISE_REPORT";
|
||||
} else {
|
||||
paramTestId = row.id;
|
||||
this.scheduleTaskType = "API_SCENARIO_TEST";
|
||||
|
@ -263,6 +269,13 @@ export default {
|
|||
if (param.id) {
|
||||
url = '/schedule/update';
|
||||
}
|
||||
} else if (this.scheduleTaskType == 'ENTERPRISE_REPORT') {
|
||||
param.scheduleFrom = "enterpriseReport";
|
||||
//测试计划页面跳转的创建
|
||||
url = '/schedule/create';
|
||||
if (param.id) {
|
||||
url = '/schedule/update';
|
||||
}
|
||||
} else {
|
||||
param.scheduleFrom = "scenario";
|
||||
if (param.id) {
|
||||
|
|
|
@ -94,6 +94,7 @@ export default {
|
|||
let data = response.data.barChartDTO;
|
||||
let pieData = response.data.pieChartDTO;
|
||||
let selectTableData = response.data.tableDTOs;
|
||||
console.info(response.data);
|
||||
this.initPic(data, pieData, selectTableData);
|
||||
}, error => {
|
||||
this.loading = false;
|
||||
|
@ -101,6 +102,7 @@ export default {
|
|||
},
|
||||
initPic(barData, pieData, selectTableData) {
|
||||
this.loading = true;
|
||||
this.resetOptions();
|
||||
if (barData) {
|
||||
this.loadOption.legend = barData.legend;
|
||||
this.loadOption.xAxis = barData.xaxis;
|
||||
|
@ -172,7 +174,7 @@ export default {
|
|||
let dataOptionObj = JSON.parse(reportData.dataOption);
|
||||
if (dataOptionObj.chartType) {
|
||||
this.chartType = dataOptionObj.chartType;
|
||||
}else {
|
||||
} else {
|
||||
this.chartType = "bar";
|
||||
}
|
||||
this.initPic(dataOptionObj.loadOption, dataOptionObj.pieOption, dataOptionObj.tableData);
|
||||
|
@ -207,6 +209,24 @@ export default {
|
|||
return "";
|
||||
}
|
||||
},
|
||||
resetOptions() {
|
||||
this.loadOption = {
|
||||
legend: {},
|
||||
xAxis: {},
|
||||
yAxis: {},
|
||||
label: {},
|
||||
tooltip: {},
|
||||
series: []
|
||||
};
|
||||
this.pieOption = {
|
||||
legend: {},
|
||||
label: {},
|
||||
tooltip: {},
|
||||
series: [],
|
||||
title: [],
|
||||
};
|
||||
this.tableData = [];
|
||||
},
|
||||
selectAndSaveReport(reportName) {
|
||||
let opt = this.$refs.countFilter.getOption();
|
||||
this.options = opt;
|
||||
|
|
|
@ -269,9 +269,6 @@ export default {
|
|||
this.loading = true;
|
||||
this.option = opt;
|
||||
this.$nextTick(() => {
|
||||
if(this.option.timeType === "dynamicTime"){
|
||||
this.init();
|
||||
}
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit dd73a29ed22916b8d7ff70d1062604a17177d3a5
|
||||
Subproject commit 249ac53686faf82906dcfabf76d66bdc8fda39db
|
|
@ -0,0 +1,109 @@
|
|||
<template>
|
||||
<report-chart v-if="!needReloading" :read-only="true" :need-full-screen="false" :chart-type="dataOption.chartType"
|
||||
ref="analysisChart" :load-option="dataOption.loadOption" :pie-option="dataOption.pieOption"/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ReportChart from "@/business/components/xpack/reportstatistics/projectreport/components/chart/ReportChart";
|
||||
import {getShareId} from "@/common/js/utils";
|
||||
|
||||
export default {
|
||||
name: "ShareEnterpriseReportTemplate",
|
||||
components: {ReportChart},
|
||||
data() {
|
||||
return {
|
||||
needReloading: false,
|
||||
shareId: '',
|
||||
dataOption: {
|
||||
chartType: '',
|
||||
loadOption: {
|
||||
legend: {},
|
||||
xAxis: {},
|
||||
yAxis: {},
|
||||
label: {},
|
||||
tooltip: {},
|
||||
series: []
|
||||
},
|
||||
pieOption: {
|
||||
legend: {},
|
||||
label: {},
|
||||
tooltip: {},
|
||||
series: [],
|
||||
title: [],
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.initEchartData();
|
||||
},
|
||||
methods: {
|
||||
initEchartData() {
|
||||
this.shareId = getShareId();
|
||||
let paramObj = {
|
||||
id: this.shareId
|
||||
};
|
||||
this.resetOptions();
|
||||
this.$post('/share/info/selectHistoryReportById', paramObj, response => {
|
||||
let reportData = response.data;
|
||||
if (reportData) {
|
||||
let selectOption = JSON.parse(reportData.selectOption);
|
||||
let data = JSON.parse(reportData.dataOption);
|
||||
data.selectOption = selectOption;
|
||||
this.dataOption = data;
|
||||
console.info(this.dataOption);
|
||||
this.reloadChart();
|
||||
}
|
||||
}, (error) => {
|
||||
this.$error(this.$t('查找报告失败!'));
|
||||
return false;
|
||||
});
|
||||
},
|
||||
initPic(loadOptionParam, tableData) {
|
||||
this.loading = true;
|
||||
if (loadOptionParam) {
|
||||
this.loadOption.legend = loadOptionParam.legend;
|
||||
this.loadOption.xAxis = loadOptionParam.xaxis;
|
||||
this.loadOption.series = loadOptionParam.series;
|
||||
this.loadOption.grid = {
|
||||
bottom: '75px',//距离下边距
|
||||
}
|
||||
this.loadOption.series.forEach(item => {
|
||||
item.type = this.$refs.analysisChart.chartType;
|
||||
})
|
||||
}
|
||||
if (tableData) {
|
||||
this.tableData = tableData;
|
||||
}
|
||||
this.loading = false;
|
||||
},
|
||||
reloadChart() {
|
||||
console.info("load data over, reload compnents.");
|
||||
this.$refs.analysisChart.reload();
|
||||
},
|
||||
resetOptions() {
|
||||
this.dataOption = {
|
||||
chartType: '',
|
||||
loadOption: {
|
||||
legend: {},
|
||||
xAxis: {},
|
||||
yAxis: {},
|
||||
label: {},
|
||||
tooltip: {},
|
||||
series: []
|
||||
},
|
||||
pieOption: {
|
||||
legend: {},
|
||||
label: {},
|
||||
tooltip: {},
|
||||
series: [],
|
||||
title: [],
|
||||
},
|
||||
};
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="shortcut icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title>Enterprise Report</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="shareEnterpriseReport"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,40 @@
|
|||
import ShareEnterpriseReportTemplate from "./ShareEnterpriseReportTemplate";
|
||||
|
||||
import Vue from 'vue';
|
||||
import ElementUI, {Button, Col, Form, FormItem, Input, Row, Main, Card, Table, TableColumn} from 'element-ui';
|
||||
import '@/assets/theme/index.css';
|
||||
import '@/common/css/menu-header.css';
|
||||
import '@/common/css/main.css';
|
||||
import i18n from "@/i18n/i18n";
|
||||
import chart from "@/common/js/chart";
|
||||
import filters from "@/common/js/filter";
|
||||
import icon from "@/common/js/icon";
|
||||
import message from "@/common/js/message";
|
||||
import Ajax from "@/common/js/ajax";
|
||||
|
||||
Vue.use(ElementUI, {
|
||||
i18n: (key, value) => i18n.t(key, value)
|
||||
});
|
||||
|
||||
Vue.use(Row);
|
||||
Vue.use(Col);
|
||||
Vue.use(Form);
|
||||
Vue.use(FormItem);
|
||||
Vue.use(Input);
|
||||
Vue.use(Button);
|
||||
Vue.use(chart);
|
||||
Vue.use(Main);
|
||||
Vue.use(Card);
|
||||
Vue.use(Ajax)
|
||||
Vue.use(TableColumn);
|
||||
Vue.use(Table);
|
||||
Vue.use(filters);
|
||||
Vue.use(icon);
|
||||
Vue.use(message);
|
||||
|
||||
new Vue({
|
||||
el: '#shareEnterpriseReport',
|
||||
i18n,
|
||||
render: h => h(ShareEnterpriseReportTemplate)
|
||||
});
|
||||
|
|
@ -44,6 +44,11 @@ module.exports = {
|
|||
template: "src/template/report/plan/plan-report.html",
|
||||
filename: "plan-report.html",
|
||||
},
|
||||
enterpriseReport: {
|
||||
entry: "src/template/enterprise/share/share-enterprise-report.js",
|
||||
template: "src/template/enterprise/share/share-enterprise-report.html",
|
||||
filename: "share-enterprise-report.html",
|
||||
},
|
||||
},
|
||||
configureWebpack: {
|
||||
devtool: 'source-map',
|
||||
|
@ -61,9 +66,9 @@ module.exports = {
|
|||
return args;
|
||||
});
|
||||
config.plugin('inline-source-html-planReport')
|
||||
.after('html-planReport')
|
||||
.use(HtmlWebpackInlineSourcePlugin);
|
||||
|
||||
.after('html-planReport')
|
||||
.use(HtmlWebpackInlineSourcePlugin);
|
||||
config.plugins.delete('prefetch');
|
||||
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue