From 8dc013927ce370a1cee8c8fe68f68b1aab99afb9 Mon Sep 17 00:00:00 2001 From: chenfanghang <20001117@qq.com> Date: Sat, 28 Nov 2020 23:58:30 +0800 Subject: [PATCH 01/11] =?UTF-8?q?feat(=E6=8E=A5=E5=8F=A3=E7=9B=91=E6=8E=A7?= =?UTF-8?q?):=E5=A2=9E=E5=8A=A0=E5=93=8D=E5=BA=94=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E4=B8=8E=E7=8A=B6=E6=80=81=E7=9B=91=E6=8E=A7=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/controller/ApiMonitorController.java | 55 ++++++ .../metersphere/api/dto/ApiMonitorSearch.java | 10 ++ .../api/dto/ApiResponseCodeMonitor.java | 20 +++ .../api/dto/ApiResponseTimeMonitor.java | 20 +++ .../api/service/APIMonitorService.java | 35 ++++ .../api/service/APIReportService.java | 51 ++++++ .../metersphere/base/domain/ApiDataView.java | 24 +++ .../base/mapper/ApiDataViewMapper.java | 23 +++ .../base/mapper/ApiDataViewMapper.xml | 77 ++++++++ .../db/migration/V47__api_data_view.sql | 12 ++ .../components/api/head/ApiHeaderMenus.vue | 5 + .../components/api/monitor/ApiMonitor.vue | 168 ++++++++++++++++++ .../api/monitor/ApiMonitorChart.vue | 46 +++++ .../api/monitor/ApiMonitorSearch.vue | 100 +++++++++++ .../components/ApiErrorMonitorChart.vue | 93 ++++++++++ .../ApiResponseTimeMonitorChart.vue | 64 +++++++ .../monitor/components/CommonMonitorChart.vue | 33 ++++ .../src/business/components/api/router.js | 12 +- frontend/src/common/js/ajax.js | 6 +- frontend/src/common/js/chart.js | 2 + frontend/src/common/js/format-utils.js | 36 ++++ frontend/src/i18n/en-US.js | 13 +- frontend/src/i18n/zh-CN.js | 13 +- frontend/src/i18n/zh-TW.js | 13 +- 24 files changed, 924 insertions(+), 7 deletions(-) create mode 100644 backend/src/main/java/io/metersphere/api/controller/ApiMonitorController.java create mode 100644 backend/src/main/java/io/metersphere/api/dto/ApiMonitorSearch.java create mode 100644 backend/src/main/java/io/metersphere/api/dto/ApiResponseCodeMonitor.java create mode 100644 backend/src/main/java/io/metersphere/api/dto/ApiResponseTimeMonitor.java create mode 100644 backend/src/main/java/io/metersphere/api/service/APIMonitorService.java create mode 100644 backend/src/main/java/io/metersphere/base/domain/ApiDataView.java create mode 100644 backend/src/main/java/io/metersphere/base/mapper/ApiDataViewMapper.java create mode 100644 backend/src/main/java/io/metersphere/base/mapper/ApiDataViewMapper.xml create mode 100644 backend/src/main/resources/db/migration/V47__api_data_view.sql create mode 100644 frontend/src/business/components/api/monitor/ApiMonitor.vue create mode 100644 frontend/src/business/components/api/monitor/ApiMonitorChart.vue create mode 100644 frontend/src/business/components/api/monitor/ApiMonitorSearch.vue create mode 100644 frontend/src/business/components/api/monitor/components/ApiErrorMonitorChart.vue create mode 100644 frontend/src/business/components/api/monitor/components/ApiResponseTimeMonitorChart.vue create mode 100644 frontend/src/business/components/api/monitor/components/CommonMonitorChart.vue diff --git a/backend/src/main/java/io/metersphere/api/controller/ApiMonitorController.java b/backend/src/main/java/io/metersphere/api/controller/ApiMonitorController.java new file mode 100644 index 0000000000..2384d0b7f2 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/controller/ApiMonitorController.java @@ -0,0 +1,55 @@ +package io.metersphere.api.controller; + +import io.metersphere.api.dto.ApiMonitorSearch; +import io.metersphere.api.dto.ApiResponseCodeMonitor; +import io.metersphere.api.dto.ApiResponseTimeMonitor; +import io.metersphere.api.service.APIMonitorService; +import io.metersphere.commons.constants.RoleConstants; +import org.apache.shiro.authz.annotation.Logical; +import org.apache.shiro.authz.annotation.RequiresRoles; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; + +@RestController +@RequestMapping(value = "/api/monitor") +@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER, RoleConstants.TEST_VIEWER}, logical = Logical.OR) +public class ApiMonitorController { + + @Resource + private APIMonitorService apiMonitorService; + + /** + * 查询所有接口 + */ + @GetMapping("/list") + public List apiList() { + return apiMonitorService.list(); + } + + + /** + * 查询响应时间 + */ + @GetMapping("/getResponseTime") + public List responseTimeData(@RequestHeader("apiUrl") String url, String startTime, String endTime) { + return apiMonitorService.getApiResponseTimeData(url, startTime, endTime); + } + + /** + * 查询状态码 + */ + @GetMapping("/getResponseCode") + public List responseCodeData(@RequestHeader("apiUrl") String url, String startTime, String endTime) { + return apiMonitorService.getApiResponseCodeData(url, startTime, endTime); + } + + /** + * 查询reportId + */ + @GetMapping("/getReportId") + public String searchReportId(@RequestHeader("apiUrl") String url, @RequestParam("startTime") String startTime) { + return apiMonitorService.getReportId(url, startTime); + } +} diff --git a/backend/src/main/java/io/metersphere/api/dto/ApiMonitorSearch.java b/backend/src/main/java/io/metersphere/api/dto/ApiMonitorSearch.java new file mode 100644 index 0000000000..9ed3e0fc31 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/ApiMonitorSearch.java @@ -0,0 +1,10 @@ +package io.metersphere.api.dto; + +import lombok.Data; + +@Data +public class ApiMonitorSearch { + + private String url; + +} \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/api/dto/ApiResponseCodeMonitor.java b/backend/src/main/java/io/metersphere/api/dto/ApiResponseCodeMonitor.java new file mode 100644 index 0000000000..8fc6c1bd10 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/ApiResponseCodeMonitor.java @@ -0,0 +1,20 @@ +package io.metersphere.api.dto; + +import lombok.Data; + +@Data +public class ApiResponseCodeMonitor { + + private String id; + + private String reportId; + + private String url; + + private String apiName; + + private String startTime; + + private String responseCode; + +} diff --git a/backend/src/main/java/io/metersphere/api/dto/ApiResponseTimeMonitor.java b/backend/src/main/java/io/metersphere/api/dto/ApiResponseTimeMonitor.java new file mode 100644 index 0000000000..80ba42b930 --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/ApiResponseTimeMonitor.java @@ -0,0 +1,20 @@ +package io.metersphere.api.dto; + +import lombok.Data; + +@Data +public class ApiResponseTimeMonitor { + + private String id; + + private String reportId; + + private String url; + + private String apiName; + + private String startTime; + + private String responseTime; + +} diff --git a/backend/src/main/java/io/metersphere/api/service/APIMonitorService.java b/backend/src/main/java/io/metersphere/api/service/APIMonitorService.java new file mode 100644 index 0000000000..d8e942a01a --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/service/APIMonitorService.java @@ -0,0 +1,35 @@ +package io.metersphere.api.service; + +import io.metersphere.api.dto.ApiMonitorSearch; +import io.metersphere.api.dto.ApiResponseCodeMonitor; +import io.metersphere.api.dto.ApiResponseTimeMonitor; +import io.metersphere.base.mapper.ApiDataViewMapper; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.List; + +@Service +@Transactional(rollbackFor = Exception.class) +public class APIMonitorService { + + @Resource + private ApiDataViewMapper apiDataViewMapper; + + public List list() { + return apiDataViewMapper.selectAll(); + } + + public List getApiResponseTimeData(String apiUrl, String startTime, String endTime) { + return apiDataViewMapper.selectResponseTimeByUrl(apiUrl, startTime, endTime); + } + + public List getApiResponseCodeData(String apiUrl, String startTime, String endTime) { + return apiDataViewMapper.selectResponseCodeByUrl(apiUrl, startTime, endTime); + } + + public String getReportId(String apiUrl, String startTime) { + return apiDataViewMapper.selectReportIdByUrlAndStartTime(apiUrl, startTime); + } +} diff --git a/backend/src/main/java/io/metersphere/api/service/APIReportService.java b/backend/src/main/java/io/metersphere/api/service/APIReportService.java index cc4367eb8b..a8ce783493 100644 --- a/backend/src/main/java/io/metersphere/api/service/APIReportService.java +++ b/backend/src/main/java/io/metersphere/api/service/APIReportService.java @@ -1,17 +1,21 @@ package io.metersphere.api.service; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import io.metersphere.api.dto.APIReportResult; import io.metersphere.api.dto.DeleteAPIReportRequest; import io.metersphere.api.dto.QueryAPIReportRequest; import io.metersphere.api.jmeter.TestResult; import io.metersphere.base.domain.*; +import io.metersphere.base.mapper.ApiDataViewMapper; import io.metersphere.base.mapper.ApiTestReportDetailMapper; import io.metersphere.base.mapper.ApiTestReportMapper; import io.metersphere.base.mapper.ext.ExtApiTestReportMapper; import io.metersphere.commons.constants.APITestStatus; import io.metersphere.commons.constants.ReportTriggerMode; import io.metersphere.commons.exception.MSException; +import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.ServiceUtils; import io.metersphere.dto.DashboardTestDTO; import io.metersphere.i18n.Translator; @@ -21,8 +25,11 @@ import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.nio.charset.StandardCharsets; +import java.text.SimpleDateFormat; import java.time.Instant; import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.UUID; @@ -36,6 +43,8 @@ public class APIReportService { private ApiTestReportDetailMapper apiTestReportDetailMapper; @Resource private ExtApiTestReportMapper extApiTestReportMapper; + @Resource + private ApiDataViewMapper apiDataViewMapper; public List list(QueryAPIReportRequest request) { request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders())); @@ -63,6 +72,8 @@ public class APIReportService { public void delete(DeleteAPIReportRequest request) { apiTestReportDetailMapper.deleteByPrimaryKey(request.getId()); apiTestReportMapper.deleteByPrimaryKey(request.getId()); + apiDataViewMapper.deleteByReportId(request.getId()); + } public void deleteByTestId(String testId) { @@ -89,6 +100,8 @@ public class APIReportService { // report report.setUpdateTime(System.currentTimeMillis()); if (!StringUtils.equals(report.getStatus(), APITestStatus.Debug.name())) { + //新增每一条接口记录到api_data_view表中 + creatApiDataView(new String(detail.getContent(), StandardCharsets.UTF_8), report.getId()); if (result.getError() > 0) { report.setStatus(APITestStatus.Error.name()); } else { @@ -99,6 +112,44 @@ public class APIReportService { apiTestReportMapper.updateByPrimaryKeySelective(report); } + private void creatApiDataView(String jsonString, String reportId) { + List listApiDataView = new ArrayList<>(); + JSONObject jsonObject = JSON.parseObject(jsonString, JSONObject.class); + JSONArray jsonArray = jsonObject.getJSONArray("scenarios"); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + try { + for (int i = 0; i < jsonArray.size(); i++) { + JSONObject jsonInArray = jsonArray.getJSONObject(i); + JSONArray jsonRequestResults = jsonInArray.getJSONArray("requestResults"); + for (int j = 0; j < jsonRequestResults.size(); j++) { + JSONObject jsonInResponseResult = jsonRequestResults.getJSONObject(j).getJSONObject("responseResult"); + String responseTime = jsonInResponseResult.getString("responseTime"); + String responseCode = jsonInResponseResult.getString("responseCode"); + String startTime = jsonRequestResults.getJSONObject(j).getString("startTime"); + String name = jsonRequestResults.getJSONObject(j).getString("name"); + String url = jsonRequestResults.getJSONObject(j).getString("url"); + if (StringUtils.isBlank(url)){ + //如果非http请求不入库 + continue; + } + ApiDataView apiDataView = new ApiDataView(); + apiDataView.setId(UUID.randomUUID().toString()); + apiDataView.setReportId(reportId); + apiDataView.setApiName(name); + apiDataView.setUrl(StringUtils.substringBefore(url,"?")); + apiDataView.setResponseTime(responseTime); + apiDataView.setStartTime(sdf.format(new Date(Long.parseLong(startTime)))); + apiDataView.setResponseCode(responseCode); + listApiDataView.add(apiDataView); + } + } + } catch (Exception e) { + LogUtil.error(e); + } + apiDataViewMapper.insertListApiData(listApiDataView); + + } + public String create(ApiTest test, String triggerMode) { ApiTestReport running = getRunningReport(test.getId()); if (running != null) { diff --git a/backend/src/main/java/io/metersphere/base/domain/ApiDataView.java b/backend/src/main/java/io/metersphere/base/domain/ApiDataView.java new file mode 100644 index 0000000000..8399077381 --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/domain/ApiDataView.java @@ -0,0 +1,24 @@ +package io.metersphere.base.domain; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class ApiDataView implements Serializable { + private String id; + + private String reportId; + + private String url; + + private String apiName; + + private String startTime; + + private String responseCode; + + private String responseTime; + + private static final long serialVersionUID = 1L; +} diff --git a/backend/src/main/java/io/metersphere/base/mapper/ApiDataViewMapper.java b/backend/src/main/java/io/metersphere/base/mapper/ApiDataViewMapper.java new file mode 100644 index 0000000000..48cf86c598 --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/mapper/ApiDataViewMapper.java @@ -0,0 +1,23 @@ +package io.metersphere.base.mapper; + +import io.metersphere.api.dto.ApiMonitorSearch; +import io.metersphere.api.dto.ApiResponseCodeMonitor; +import io.metersphere.api.dto.ApiResponseTimeMonitor; +import io.metersphere.base.domain.ApiDataView; + +import java.util.List; + +public interface ApiDataViewMapper { + + List selectAll(); + + List selectResponseTimeByUrl(String url,String startTime,String endTime); + + List selectResponseCodeByUrl(String url,String startTime,String endTime); + + Integer insertListApiData(List list); + + Integer deleteByReportId(String reportId); + + String selectReportIdByUrlAndStartTime(String apiUrl,String startTime); +} \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/ApiDataViewMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ApiDataViewMapper.xml new file mode 100644 index 0000000000..671a97fdb5 --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/mapper/ApiDataViewMapper.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + delete from api_data_view where report_id = #{reportId,jdbcType=VARCHAR} + + + + + + + + + + + insert into api_data_view(id, report_id, api_name,url, response_code, start_time,response_time) + values + + ( + #{item.id,jdbcType=VARCHAR}, + #{item.reportId,jdbcType=VARCHAR}, + #{item.apiName,jdbcType=VARCHAR}, + #{item.url,jdbcType=VARCHAR}, + #{item.responseCode,jdbcType=VARCHAR}, + #{item.startTime,jdbcType=VARCHAR}, + #{item.responseTime,jdbcType=VARCHAR} + ) + + + \ No newline at end of file diff --git a/backend/src/main/resources/db/migration/V47__api_data_view.sql b/backend/src/main/resources/db/migration/V47__api_data_view.sql new file mode 100644 index 0000000000..74ff59be4f --- /dev/null +++ b/backend/src/main/resources/db/migration/V47__api_data_view.sql @@ -0,0 +1,12 @@ +CREATE TABLE IF NOT EXISTS `api_data_view` +( + id varchar(50) NOT NULL primary key, + report_id varchar(255) NOT NULL, + api_name varchar(200) NULL, + url varchar(255) NULL, + response_code varchar(100) NULL, + start_time varchar(20) NULL, + response_time varchar(20) default '0' NULL, + create_time timestamp default CURRENT_TIMESTAMP NOT NULL, + update_time timestamp default CURRENT_TIMESTAMP NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file diff --git a/frontend/src/business/components/api/head/ApiHeaderMenus.vue b/frontend/src/business/components/api/head/ApiHeaderMenus.vue index 5e1e6f1d1f..f398905d6f 100644 --- a/frontend/src/business/components/api/head/ApiHeaderMenus.vue +++ b/frontend/src/business/components/api/head/ApiHeaderMenus.vue @@ -32,6 +32,11 @@ + + + + {{ $t('commons.monitor') }} + diff --git a/frontend/src/business/components/api/monitor/ApiMonitor.vue b/frontend/src/business/components/api/monitor/ApiMonitor.vue new file mode 100644 index 0000000000..466b1e5eea --- /dev/null +++ b/frontend/src/business/components/api/monitor/ApiMonitor.vue @@ -0,0 +1,168 @@ + + + + + diff --git a/frontend/src/business/components/api/monitor/ApiMonitorChart.vue b/frontend/src/business/components/api/monitor/ApiMonitorChart.vue new file mode 100644 index 0000000000..c7e2b1a3e8 --- /dev/null +++ b/frontend/src/business/components/api/monitor/ApiMonitorChart.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/frontend/src/business/components/api/monitor/ApiMonitorSearch.vue b/frontend/src/business/components/api/monitor/ApiMonitorSearch.vue new file mode 100644 index 0000000000..d97a9a2d33 --- /dev/null +++ b/frontend/src/business/components/api/monitor/ApiMonitorSearch.vue @@ -0,0 +1,100 @@ + + + + + diff --git a/frontend/src/business/components/api/monitor/components/ApiErrorMonitorChart.vue b/frontend/src/business/components/api/monitor/components/ApiErrorMonitorChart.vue new file mode 100644 index 0000000000..ca7903e471 --- /dev/null +++ b/frontend/src/business/components/api/monitor/components/ApiErrorMonitorChart.vue @@ -0,0 +1,93 @@ + + + + + diff --git a/frontend/src/business/components/api/monitor/components/ApiResponseTimeMonitorChart.vue b/frontend/src/business/components/api/monitor/components/ApiResponseTimeMonitorChart.vue new file mode 100644 index 0000000000..dccd45060e --- /dev/null +++ b/frontend/src/business/components/api/monitor/components/ApiResponseTimeMonitorChart.vue @@ -0,0 +1,64 @@ + + + + + diff --git a/frontend/src/business/components/api/monitor/components/CommonMonitorChart.vue b/frontend/src/business/components/api/monitor/components/CommonMonitorChart.vue new file mode 100644 index 0000000000..868373a31e --- /dev/null +++ b/frontend/src/business/components/api/monitor/components/CommonMonitorChart.vue @@ -0,0 +1,33 @@ + + + + + + + diff --git a/frontend/src/business/components/api/router.js b/frontend/src/business/components/api/router.js index 672d9faf7e..3528722f23 100644 --- a/frontend/src/business/components/api/router.js +++ b/frontend/src/business/components/api/router.js @@ -38,6 +38,16 @@ export default { path: "report/view/:reportId", name: "ApiReportView", component: () => import('@/business/components/api/report/ApiReportView'), - } + }, + { + path: "definition", + name: "ApiDefinition", + component: () => import('@/business/components/api/definition/ApiDefinition'), + }, + { + path: 'monitor/view', + name: 'ApiMonitor', + component: () => import('@/business/components/api/monitor/ApiMonitor'), + }, ] } diff --git a/frontend/src/common/js/ajax.js b/frontend/src/common/js/ajax.js index 3482f67ebd..9acc2d2c6c 100644 --- a/frontend/src/common/js/ajax.js +++ b/frontend/src/common/js/ajax.js @@ -70,12 +70,12 @@ export default { } } - Vue.prototype.$$get = function (url, data, success) { + Vue.prototype.$$get = function (url, data, header, success) { let result = {loading: true}; if (!success) { - return axios.get(url, {params: data}); + return axios.get(url, {params: data, headers: header}); } else { - axios.get(url, {params: data}).then(response => { + axios.get(url, {params: data, headers: header}).then(response => { then(success, response, result); }).catch(error => { exception(error, result); diff --git a/frontend/src/common/js/chart.js b/frontend/src/common/js/chart.js index f2ec0b5317..5e26e1bcc6 100644 --- a/frontend/src/common/js/chart.js +++ b/frontend/src/common/js/chart.js @@ -4,6 +4,8 @@ import 'echarts/lib/chart/bar' import 'echarts/lib/chart/pie' import 'echarts/lib/component/tooltip' import 'echarts/lib/component/title' +import 'echarts/lib/component/toolbox'; +import 'echarts/lib/component/dataZoom'; import 'zrender/lib/svg/svg' export default { diff --git a/frontend/src/common/js/format-utils.js b/frontend/src/common/js/format-utils.js index 1c1206b6fd..e207b6df90 100644 --- a/frontend/src/common/js/format-utils.js +++ b/frontend/src/common/js/format-utils.js @@ -120,6 +120,42 @@ export function formatXml(text) { return outputText.replace(/\s+$/g, '').replace(/\r/g, '\r\n'); } +/** + * @param time 时间 + * @param cFormat 格式 + * @returns {string|null} 字符串 + * @example formatTime('2018-1-29', '{y}/{m}/{d} {h}:{i}:{s}') // -> 2018/01/29 00:00:00 + */ +export function formatTime(time, cFormat) { + if (arguments.length === 0) return null; + if ((time + '').length === 10) { + time = +time * 1000; + } + let format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}', date; + if (typeof time === 'object') { + date = time; + } else { + date = new Date(time); + } + let formatObj = { + y: date.getFullYear(), + m: date.getMonth() + 1, + d: date.getDate(), + h: date.getHours(), + i: date.getMinutes(), + s: date.getSeconds(), + a: date.getDay() + }; + return format.replace(/{([ymdhisa])+}/g, (result, key) => { + let value = formatObj[key]; + if (key === 'a') return ['一', '二', '三', '四', '五', '六', '日'][value - 1]; + if (result.length > 0 && value < 10) { + value = '0' + value; + } + return value || 0; + }); +} + function getPrefix(prefixIndex) { var span = ' '; var output = []; diff --git a/frontend/src/i18n/en-US.js b/frontend/src/i18n/en-US.js index bfc2f4a616..7e69aaaffc 100644 --- a/frontend/src/i18n/en-US.js +++ b/frontend/src/i18n/en-US.js @@ -162,7 +162,8 @@ export default { between: "Between", current_user: "Current user" } - } + }, + monitor:"monitor" }, license: { title: 'Authorization management', @@ -707,6 +708,16 @@ export default { running: "The test is reporting", not_exist: "Test report does not exist", }, + api_monitor: { + to:"to", + start_time:"Start Time", + end_time:"End Time", + today:"Today", + this_week:"This Week", + this_mouth:"This Mouth", + please_search:"Please Search", + date:"Date" + }, test_track: { test_track: "Track", confirm: "Confirm", diff --git a/frontend/src/i18n/zh-CN.js b/frontend/src/i18n/zh-CN.js index 6974ad127a..45403e5574 100644 --- a/frontend/src/i18n/zh-CN.js +++ b/frontend/src/i18n/zh-CN.js @@ -162,7 +162,8 @@ export default { between: "之间", current_user: "是当前用户" } - } + }, + monitor: "监控" }, license: { title: '授权管理', @@ -709,6 +710,16 @@ export default { running: "测试报告导出中", not_exist: "测试报告不存在", }, + api_monitor: { + to:"至", + start_time:"开始日期", + end_time:"结束日期", + today:"今日", + this_week:"本周", + this_mouth:"本月", + please_search:"请搜索", + date:"日期" + }, test_track: { test_track: "测试跟踪", confirm: "确 定", diff --git a/frontend/src/i18n/zh-TW.js b/frontend/src/i18n/zh-TW.js index 62a1a3e3c7..9af605db4a 100644 --- a/frontend/src/i18n/zh-TW.js +++ b/frontend/src/i18n/zh-TW.js @@ -162,7 +162,8 @@ export default { between: "之間", current_user: "是當前用戶" } - } + }, + monitor:"監控" }, license: { title: '授權管理', @@ -710,6 +711,16 @@ export default { running: "測試報告導出中", not_exist: "測試報告不存在", }, + api_monitor: { + to:"到", + start_time:"開始時間", + end_time:"結束時間", + today:"今天", + this_week:"本週", + this_mouth:"本月", + please_search:"請搜索", + date:"日期" + }, test_track: { test_track: "測試跟蹤", confirm: "確 定", From 0acc2a915db2ac1ef3c5c080c38e17ae9186f95d Mon Sep 17 00:00:00 2001 From: BugKing Date: Mon, 30 Nov 2020 19:07:44 +0800 Subject: [PATCH 02/11] =?UTF-8?q?refactor:=20=E8=A7=A3=E5=86=B3=E5=90=88?= =?UTF-8?q?=E5=B9=B6=E5=90=8E=E7=9A=84=E5=86=B2=E7=AA=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/business/components/api/router.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/frontend/src/business/components/api/router.js b/frontend/src/business/components/api/router.js index 3528722f23..dbb73ae0c0 100644 --- a/frontend/src/business/components/api/router.js +++ b/frontend/src/business/components/api/router.js @@ -39,11 +39,6 @@ export default { name: "ApiReportView", component: () => import('@/business/components/api/report/ApiReportView'), }, - { - path: "definition", - name: "ApiDefinition", - component: () => import('@/business/components/api/definition/ApiDefinition'), - }, { path: 'monitor/view', name: 'ApiMonitor', From 6a4f78d2feea85162f35640c832bae72c678b0ae Mon Sep 17 00:00:00 2001 From: BugKing Date: Mon, 30 Nov 2020 20:44:58 +0800 Subject: [PATCH 03/11] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E6=B5=8B=E8=AF=95=E7=9B=91=E6=8E=A7=E5=93=8D=E5=BA=94?= =?UTF-8?q?=E7=A0=81=E5=9B=BE=E8=A1=A8=E4=B8=8D=E6=98=BE=E7=A4=BA=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/business/components/api/monitor/ApiMonitor.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/business/components/api/monitor/ApiMonitor.vue b/frontend/src/business/components/api/monitor/ApiMonitor.vue index 466b1e5eea..e5dab060db 100644 --- a/frontend/src/business/components/api/monitor/ApiMonitor.vue +++ b/frontend/src/business/components/api/monitor/ApiMonitor.vue @@ -95,7 +95,7 @@ export default { {'apiUrl': this.apiUrl}, response => { Object.values(response.data).forEach(value => { this.rspCodexAxis.push(value.startTime); - this.rspCodeData.push(value.responseTime); + this.rspCodeData.push(value.responseCode); }); }); }, From 97448b39d5571df7aa36cdeb66889aaf2427fedf Mon Sep 17 00:00:00 2001 From: BugKing Date: Fri, 4 Dec 2020 10:01:14 +0800 Subject: [PATCH 04/11] =?UTF-8?q?build:=20=E5=A2=9E=E5=8A=A0=20action?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build-push.yml | 64 ++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 .github/workflows/build-push.yml diff --git a/.github/workflows/build-push.yml b/.github/workflows/build-push.yml new file mode 100644 index 0000000000..a87efc78c3 --- /dev/null +++ b/.github/workflows/build-push.yml @@ -0,0 +1,64 @@ +name: Build Docker Image and Push + +on: + push: + branches: + - master + - v1* + pull_request: + branches: + - master + - v1* + + workflow_dispatch: + +jobs: + build_push: + runs-on: ubuntu-latest + name: Build Docker Image and Push + steps: + - uses: actions/checkout@v2 + with: + submodules: true + token: ${{ secrets.ACCESS_TOKEN }} + + - name: Inject slug/short variables + uses: rlespinasse/github-slug-action@v3.x + - name: Cache node modules + uses: actions/cache@v2 + env: + cache-name: cache-node-modules + with: + path: ~/.npm + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + + - name: Cache local Maven repository + uses: actions/cache@v2 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + server-id: github # Value of the distributionManagement/repository/id field of the pom.xml + settings-path: ${{ github.workspace }} # location for the settings.xml file + + - name: Build with Maven + run: mvn -B package --file pom.xml + + - name: Push to Docker Hub + uses: docker/build-push-action@v1 + with: + username: metersphere + password: ${{ secrets.DOCKER_HUB_TOKEN }} + repository: metersphere/metersphere + tag_with_ref: true + build_args: MS_VERSION=${{ env.GITHUB_REF_SLUG }}-${{ env.GITHUB_SHA_SHORT }} From 2c316439bc2cf481ec07c6515083113918d48fd0 Mon Sep 17 00:00:00 2001 From: BugKing Date: Thu, 3 Dec 2020 18:25:25 +0800 Subject: [PATCH 05/11] =?UTF-8?q?build:=20=E4=BF=AE=E6=94=B9=20Dockerfile?= =?UTF-8?q?=20=E5=9F=BA=E7=A1=80=E9=95=9C=E5=83=8F=E5=9C=B0=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 8e0a6e24fa..5dc3c7e4d7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM registry.fit2cloud.com/metersphere/fabric8-java-alpine-openjdk8-jre +FROM metersphere/fabric8-java-alpine-openjdk8-jre MAINTAINER FIT2CLOUD From 44418244046d1c9b000063d18c311b53ded407d8 Mon Sep 17 00:00:00 2001 From: chenjianxing Date: Fri, 4 Dec 2020 10:42:53 +0800 Subject: [PATCH 06/11] =?UTF-8?q?refactor(=E6=8E=A5=E5=8F=A3=E6=B5=8B?= =?UTF-8?q?=E8=AF=95):=20=E6=95=B0=E6=8D=AE=E5=BA=93=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E8=A1=A8=E5=A4=B4=E5=8F=AF=E5=A4=8D=E5=88=B6=20fixes=20#679?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/api/report/components/SqlResultTable.vue | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/frontend/src/business/components/api/report/components/SqlResultTable.vue b/frontend/src/business/components/api/report/components/SqlResultTable.vue index 5406710eef..20c499c0f8 100644 --- a/frontend/src/business/components/api/report/components/SqlResultTable.vue +++ b/frontend/src/business/components/api/report/components/SqlResultTable.vue @@ -118,4 +118,12 @@ max-height: 500px; } + .el-table >>> th { + -webkit-user-select: text; + -khtml-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; + } + From 897017be774652374901019268c9c77af0a20db6 Mon Sep 17 00:00:00 2001 From: chenjianxing Date: Fri, 4 Dec 2020 10:44:40 +0800 Subject: [PATCH 07/11] =?UTF-8?q?fix(=E6=8E=A5=E5=8F=A3=E6=B5=8B=E8=AF=95)?= =?UTF-8?q?:=20json=E7=BB=93=E6=9E=9C=E8=87=AA=E5=8A=A8=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business/components/api/report/components/ResponseText.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/business/components/api/report/components/ResponseText.vue b/frontend/src/business/components/api/report/components/ResponseText.vue index f1f64f40fb..bb2f479d83 100644 --- a/frontend/src/business/components/api/report/components/ResponseText.vue +++ b/frontend/src/business/components/api/report/components/ResponseText.vue @@ -81,7 +81,7 @@ export default { if (!this.response.headers) { return; } - if (this.response.headers.indexOf("Content-Type: application/json") > 0) { + if (this.response.headers.indexOf("application/json") > 0) { this.mode = BODY_FORMAT.JSON; } }, From 5b41a769354fa8fe23796cb77bbc1b83a468d445 Mon Sep 17 00:00:00 2001 From: chenjianxing Date: Fri, 4 Dec 2020 10:55:51 +0800 Subject: [PATCH 08/11] =?UTF-8?q?fix(=E6=B5=8B=E8=AF=95=E8=B7=9F=E8=B8=AA)?= =?UTF-8?q?:=20=E7=BC=96=E8=BE=91=E7=94=A8=E4=BE=8B=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plan/view/comonents/TestPlanTestCaseEdit.vue | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/frontend/src/business/components/track/plan/view/comonents/TestPlanTestCaseEdit.vue b/frontend/src/business/components/track/plan/view/comonents/TestPlanTestCaseEdit.vue index c2fe737e3d..dbf0b890b0 100644 --- a/frontend/src/business/components/track/plan/view/comonents/TestPlanTestCaseEdit.vue +++ b/frontend/src/business/components/track/plan/view/comonents/TestPlanTestCaseEdit.vue @@ -484,12 +484,14 @@ export default { item.issues.hasIssues = false; } item.steptResults = []; - for (let i = 0; i < item.steps.length; i++) { - if (item.results[i]) { - item.steps[i].actualResult = item.results[i].actualResult; - item.steps[i].executeResult = item.results[i].executeResult; + if (item.steps) { + for (let i = 0; i < item.steps.length; i++) { + if (item.results[i]) { + item.steps[i].actualResult = item.results[i].actualResult; + item.steps[i].executeResult = item.results[i].executeResult; + } + item.steptResults.push(item.steps[i]); } - item.steptResults.push(item.steps[i]); } this.testCase = item; this.initTest(); From 25631ce05fa32b0a3da66cedefad49833a550c4b Mon Sep 17 00:00:00 2001 From: BugKing Date: Fri, 4 Dec 2020 15:53:21 +0800 Subject: [PATCH 09/11] =?UTF-8?q?Revert=20"chore:=20=E5=90=8C=E6=AD=A5=20s?= =?UTF-8?q?ubmodule"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 9e62022a --- backend/src/main/java/io/metersphere/xpack | 2 +- frontend/src/business/components/xpack | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/io/metersphere/xpack b/backend/src/main/java/io/metersphere/xpack index bb494fc68a..57d6f78efa 160000 --- a/backend/src/main/java/io/metersphere/xpack +++ b/backend/src/main/java/io/metersphere/xpack @@ -1 +1 @@ -Subproject commit bb494fc68a2367359c9048fa7250c7618de4afb6 +Subproject commit 57d6f78efa4b0300be188e8b024511ceef0873ed diff --git a/frontend/src/business/components/xpack b/frontend/src/business/components/xpack index 8a972a1987..71d57ae5d7 160000 --- a/frontend/src/business/components/xpack +++ b/frontend/src/business/components/xpack @@ -1 +1 @@ -Subproject commit 8a972a198775b3783ed6e4cef27197e53d1ebdc8 +Subproject commit 71d57ae5d7f8bb5c93a29504ac6f2300dc189ce9 From 7ee9522298cbedb6f7ecdc864cf400eeb8fdc2b6 Mon Sep 17 00:00:00 2001 From: "Captain.B" Date: Thu, 26 Nov 2020 11:52:43 +0800 Subject: [PATCH 10/11] =?UTF-8?q?chore:=20=E5=90=8C=E6=AD=A5=20submodule?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 9e62022ae909037edb2161eceb190dccb3b494e4) --- backend/src/main/java/io/metersphere/xpack | 2 +- frontend/src/business/components/xpack | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/io/metersphere/xpack b/backend/src/main/java/io/metersphere/xpack index 57d6f78efa..bb494fc68a 160000 --- a/backend/src/main/java/io/metersphere/xpack +++ b/backend/src/main/java/io/metersphere/xpack @@ -1 +1 @@ -Subproject commit 57d6f78efa4b0300be188e8b024511ceef0873ed +Subproject commit bb494fc68a2367359c9048fa7250c7618de4afb6 diff --git a/frontend/src/business/components/xpack b/frontend/src/business/components/xpack index 71d57ae5d7..8a972a1987 160000 --- a/frontend/src/business/components/xpack +++ b/frontend/src/business/components/xpack @@ -1 +1 @@ -Subproject commit 71d57ae5d7f8bb5c93a29504ac6f2300dc189ce9 +Subproject commit 8a972a198775b3783ed6e4cef27197e53d1ebdc8 From 0abd7209e03fe6bc3717015dcba8c4b2c3cb7454 Mon Sep 17 00:00:00 2001 From: "Captain.B" Date: Fri, 4 Dec 2020 17:56:06 +0800 Subject: [PATCH 11/11] =?UTF-8?q?fix(=E6=80=A7=E8=83=BD=E6=B5=8B=E8=AF=95)?= =?UTF-8?q?:=20=E4=BF=AE=E5=A4=8D=E5=A4=9A=E4=B8=AA=E7=BA=BF=E7=A8=8B?= =?UTF-8?q?=E7=BB=84=E4=B8=8D=E8=83=BD=E8=AE=BE=E7=BD=AE=E7=BA=BF=E7=A8=8B?= =?UTF-8?q?=E6=95=B0=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../report/components/PerformancePressureConfig.vue | 9 +++++---- .../test/components/PerformancePressureConfig.vue | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/frontend/src/business/components/performance/report/components/PerformancePressureConfig.vue b/frontend/src/business/components/performance/report/components/PerformancePressureConfig.vue index 096146e3d3..18c67b8af8 100644 --- a/frontend/src/business/components/performance/report/components/PerformancePressureConfig.vue +++ b/frontend/src/business/components/performance/report/components/PerformancePressureConfig.vue @@ -226,8 +226,9 @@ export default { if (handler.rampUpTime < handler.step) { handler.step = handler.rampUpTime; } + let color = ['#60acfc', '#32d3eb', '#5bc49f', '#feb64d', '#ff7c7c', '#9287e7', '#ca8622', '#bda29a', '#6e7074', '#546570', '#c4ccd3']; handler.options = { - color: ['#60acfc', '#32d3eb', '#5bc49f', '#feb64d', '#ff7c7c', '#9287e7', '#ca8622', '#bda29a', '#6e7074', '#546570', '#c4ccd3'], + color: color, xAxis: { type: 'category', boundaryGap: false, @@ -261,10 +262,10 @@ export default { normal: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, - color: hexToRgba(handler.options.color[i], 0.3), + color: hexToRgba(color[i % color.length], 0.3), }, { offset: 0.8, - color: hexToRgba(handler.options.color[i], 0), + color: hexToRgba(color[i % color.length], 0), }], false), shadowColor: 'rgba(0, 0, 0, 0.1)', shadowBlur: 10 @@ -272,7 +273,7 @@ export default { }, itemStyle: { normal: { - color: hexToRgb(handler.options.color[i]), + color: hexToRgb(color[i % color.length]), borderColor: 'rgba(137,189,2,0.27)', borderWidth: 12 } diff --git a/frontend/src/business/components/performance/test/components/PerformancePressureConfig.vue b/frontend/src/business/components/performance/test/components/PerformancePressureConfig.vue index 5d98032542..c531212baa 100644 --- a/frontend/src/business/components/performance/test/components/PerformancePressureConfig.vue +++ b/frontend/src/business/components/performance/test/components/PerformancePressureConfig.vue @@ -268,8 +268,9 @@ export default { if (handler.rampUpTime < handler.step) { handler.step = handler.rampUpTime; } + let color = ['#60acfc', '#32d3eb', '#5bc49f', '#feb64d', '#ff7c7c', '#9287e7', '#ca8622', '#bda29a', '#6e7074', '#546570', '#c4ccd3']; handler.options = { - color: ['#60acfc', '#32d3eb', '#5bc49f', '#feb64d', '#ff7c7c', '#9287e7', '#ca8622', '#bda29a', '#6e7074', '#546570', '#c4ccd3'], + color: color, xAxis: { type: 'category', boundaryGap: false, @@ -302,10 +303,10 @@ export default { normal: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, - color: hexToRgba(handler.options.color[i], 0.3), + color: hexToRgba(color[i % color.length], 0.3), }, { offset: 0.8, - color: hexToRgba(handler.options.color[i], 0), + color: hexToRgba(color[i % color.length], 0), }], false), shadowColor: 'rgba(0, 0, 0, 0.1)', shadowBlur: 10 @@ -313,7 +314,7 @@ export default { }, itemStyle: { normal: { - color: hexToRgb(handler.options.color[i]), + color: hexToRgb(color[i % color.length]), borderColor: 'rgba(137,189,2,0.27)', borderWidth: 12 }