diff --git a/backend/src/main/java/io/metersphere/commons/utils/ShiroUtils.java b/backend/src/main/java/io/metersphere/commons/utils/ShiroUtils.java index 8722d2a757..08173be997 100644 --- a/backend/src/main/java/io/metersphere/commons/utils/ShiroUtils.java +++ b/backend/src/main/java/io/metersphere/commons/utils/ShiroUtils.java @@ -63,6 +63,7 @@ public class ShiroUtils { filterChainDefinitionMap.put("/sharePlanReport", "anon"); filterChainDefinitionMap.put("/sharePerformanceReport", "anon"); filterChainDefinitionMap.put("/shareApiReport", "anon"); + filterChainDefinitionMap.put("/shareUiReport", "anon"); filterChainDefinitionMap.put("/system/theme", "anon"); filterChainDefinitionMap.put("/system/save/baseurl/**", "anon"); diff --git a/backend/src/main/java/io/metersphere/controller/IndexController.java b/backend/src/main/java/io/metersphere/controller/IndexController.java index d0f91da819..7f8519438e 100644 --- a/backend/src/main/java/io/metersphere/controller/IndexController.java +++ b/backend/src/main/java/io/metersphere/controller/IndexController.java @@ -51,4 +51,9 @@ public class IndexController { public String shareApiRedirect() { return "share-api-report.html"; } + + @GetMapping(value = "/shareUiReport") + public String shareUiRedirect() { + return "share-ui-report.html"; + } } diff --git a/backend/src/main/java/io/metersphere/dto/ProjectConfig.java b/backend/src/main/java/io/metersphere/dto/ProjectConfig.java index 9c8377f422..0257930ea5 100644 --- a/backend/src/main/java/io/metersphere/dto/ProjectConfig.java +++ b/backend/src/main/java/io/metersphere/dto/ProjectConfig.java @@ -12,6 +12,7 @@ public class ProjectConfig { private String trackShareReportTime; private String performanceShareReportTime; private String apiShareReportTime; + private String uiShareReportTime; private Boolean caseCustomNum = false; private Boolean scenarioCustomNum = false; private String apiQuickMenu; @@ -25,5 +26,7 @@ public class ProjectConfig { private String cleanApiReportExpr; private Boolean cleanLoadReport = false; private String cleanLoadReportExpr; + private Boolean cleanUiReport = false; + private String cleanUiReportExpr; private Boolean urlRepeatable = false; } diff --git a/backend/src/main/java/io/metersphere/job/sechedule/CleanUpReportJob.java b/backend/src/main/java/io/metersphere/job/sechedule/CleanUpReportJob.java index 2832c34553..a32542be1a 100644 --- a/backend/src/main/java/io/metersphere/job/sechedule/CleanUpReportJob.java +++ b/backend/src/main/java/io/metersphere/job/sechedule/CleanUpReportJob.java @@ -53,8 +53,10 @@ public class CleanUpReportJob extends MsScheduleJob { if (BooleanUtils.isTrue(config.getCleanLoadReport())) { this.doCleanUp(projectService::cleanUpLoadReport, config.getCleanLoadReportExpr()); } - // 定时删除 UI 调试模式生成的截图 - projectService.cleanUpUiReportImg(); + if (BooleanUtils.isTrue(config.getCleanUiReport())) { + // 定时删除 UI 调试模式生成的截图 + this.doCleanUp(projectService::cleanUpUiReportImg, config.getCleanUiReportExpr()); + } } catch (Exception e) { LogUtil.error("clean up report error."); LogUtil.error(e.getMessage(), e); diff --git a/backend/src/main/java/io/metersphere/service/ProjectService.java b/backend/src/main/java/io/metersphere/service/ProjectService.java index b8eb2f1b10..7213f71627 100644 --- a/backend/src/main/java/io/metersphere/service/ProjectService.java +++ b/backend/src/main/java/io/metersphere/service/ProjectService.java @@ -1035,14 +1035,16 @@ public class ProjectService { } // 删除 UI 报告产生的截图 - public void cleanUpUiReportImg() { + public void cleanUpUiReportImg(long backupTime, String projectId) { try { // 属于定时任务删除调试报告情况 // 获取昨天的当前时间 - Date backupTime = org.apache.commons.lang3.time.DateUtils.addDays(new Date(), -1); +// Date backupTime = org.apache.commons.lang3.time.DateUtils.addDays(new Date(), -1); // 清理类型为 UI 报告类型,且时间为昨天之前的 UI 调试类型报告截图 ApiScenarioReportExample example = new ApiScenarioReportExample(); - example.createCriteria().andCreateTimeLessThan(backupTime.getTime()).andReportTypeEqualTo(ReportTypeConstants.UI_INDEPENDENT.name()) + example.createCriteria() + .andProjectIdEqualTo(projectId) + .andCreateTimeLessThan(backupTime).andReportTypeEqualTo(ReportTypeConstants.UI_INDEPENDENT.name()) .andExecuteTypeEqualTo(ExecuteType.Debug.name()); List apiScenarioReports = apiScenarioReportMapper.selectByExample(example); // 删除调试报告的截图 diff --git a/backend/src/main/java/io/metersphere/xpack b/backend/src/main/java/io/metersphere/xpack index 2ca4ff0b6d..a9db2120f5 160000 --- a/backend/src/main/java/io/metersphere/xpack +++ b/backend/src/main/java/io/metersphere/xpack @@ -1 +1 @@ -Subproject commit 2ca4ff0b6d771d280eba6958345426e56d1d15a4 +Subproject commit a9db2120f547fd4cd88d6fb9ba115b182a9b80eb diff --git a/frontend/src/business/components/api/automation/report/ApiReportViewHeader.vue b/frontend/src/business/components/api/automation/report/ApiReportViewHeader.vue index 0b4e032955..aac5646b10 100644 --- a/frontend/src/business/components/api/automation/report/ApiReportViewHeader.vue +++ b/frontend/src/business/components/api/automation/report/ApiReportViewHeader.vue @@ -3,52 +3,59 @@ - + - + {{ report.name }} {{ report.name }} - + - {{$t('report.test_start_time')}}: + {{ $t('report.test_start_time') }}: {{ report.createTime | timestampFormatDate }} - {{$t('report.test_end_time')}}: + {{ $t('report.test_end_time') }}: {{ report.endTime | timestampFormatDate }} - - {{ $t('test_track.plan_view.export_report') }} - - - -

{{ shareUrl }}

- {{ - $t('commons.validity_period')+application.typeValue - }} -
- {{ $t("commons.copy") }} - -
- - {{ $t('test_track.plan_view.share_report') }} +
+ + {{ $t('test_track.plan_view.export_report') }} - - - {{$t('commons.cancel')}} - + +

{{ shareUrl }}

+ {{ + $t('commons.validity_period') + application.typeValue + }} +
+ {{ $t("commons.copy") }} + +
+ + {{ $t('test_track.plan_view.share_report') }} + +
+ + {{ $t('commons.cancel') }} + + +
@@ -58,9 +65,13 @@ import {generateShareInfoWithExpired} from "@/network/share"; import {getCurrentProjectID} from "@/common/js/utils"; +import MsTag from "@/business/components/common/components/MsTag"; +const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/); +const UiDownloadScreenshot = requireComponent.keys().length > 0 ? requireComponent("./ui/automation/report/UiDownloadScreenshot.vue") : {}; export default { name: "MsApiReportViewHeader", + components: {MsTag, 'UiDownloadScreenshot': UiDownloadScreenshot.default}, props: { report: {}, debug: Boolean, @@ -103,7 +114,7 @@ export default { isReadOnly: false, nameIsEdit: false, shareUrl: "", - application:{} + application: {} } }, created() { @@ -132,27 +143,33 @@ export default { let pram = {}; pram.customData = report.id; pram.shareType = 'API_REPORT'; + let thisHost = window.location.host; + let shareUrl = thisHost + "/shareApiReport"; + if(this.isUi){ + pram.shareType = 'UI_REPORT'; + shareUrl = thisHost + "/shareUiReport"; + } generateShareInfoWithExpired(pram, (data) => { - let thisHost = window.location.host; - this.shareUrl = thisHost + "/shareApiReport" + data.shareUrl; + this.shareUrl = shareUrl + data.shareUrl; }); }, - getProjectApplication(){ - this.$get('/project_application/get/' + getCurrentProjectID()+"/API_SHARE_REPORT_TIME", res => { - if(res.data){ + getProjectApplication() { + let path = "/API_SHARE_REPORT_TIME"; + if(this.isUi){ + path = "/UI_SHARE_REPORT_TIME"; + } + this.$get('/project_application/get/' + getCurrentProjectID() + path, res => { + if (res.data && res.data.typeValue) { let quantity = res.data.typeValue.substring(0, res.data.typeValue.length - 1); let unit = res.data.typeValue.substring(res.data.typeValue.length - 1); - if(unit==='H'){ - res.data.typeValue = quantity+this.$t('commons.date_unit.hour'); - }else - if(unit==='D'){ - res.data.typeValue = quantity+this.$t('commons.date_unit.day'); - }else - if(unit==='M'){ - res.data.typeValue = quantity+this.$t('commons.workspace_unit')+this.$t('commons.date_unit.month'); - }else - if(unit==='Y'){ - res.data.typeValue = quantity+this.$t('commons.date_unit.year'); + if (unit === 'H') { + res.data.typeValue = quantity + this.$t('commons.date_unit.hour'); + } else if (unit === 'D') { + res.data.typeValue = quantity + this.$t('commons.date_unit.day'); + } else if (unit === 'M') { + res.data.typeValue = quantity + this.$t('commons.workspace_unit') + this.$t('commons.date_unit.month'); + } else if (unit === 'Y') { + res.data.typeValue = quantity + this.$t('commons.date_unit.year'); } this.application = res.data; } diff --git a/frontend/src/business/components/api/definition/components/environment/ApiEnvironmentConfig.vue b/frontend/src/business/components/api/definition/components/environment/ApiEnvironmentConfig.vue index f9549376cc..c59eb19ee7 100644 --- a/frontend/src/business/components/api/definition/components/environment/ApiEnvironmentConfig.vue +++ b/frontend/src/business/components/api/definition/components/environment/ApiEnvironmentConfig.vue @@ -22,7 +22,7 @@ import MsAsideContainer from "../../../../common/components/MsAsideContainer"; import MsMainContainer from "../../../../common/components/MsMainContainer"; import MsAsideItem from "../../../../common/components/MsAsideItem"; import EnvironmentEdit from "./EnvironmentEdit"; -import {hasPermission, listenGoBack, removeGoBackListener} from "@/common/js/utils"; +import {getUUID, hasPermission, listenGoBack, removeGoBackListener} from "@/common/js/utils"; import {Environment, parseEnvironment} from "../../model/EnvironmentModel"; export default { diff --git a/frontend/src/business/components/api/test/components/ApiEnvironmentConfig.vue b/frontend/src/business/components/api/test/components/ApiEnvironmentConfig.vue index cbb1c6e173..0e5b9898b3 100644 --- a/frontend/src/business/components/api/test/components/ApiEnvironmentConfig.vue +++ b/frontend/src/business/components/api/test/components/ApiEnvironmentConfig.vue @@ -24,7 +24,7 @@ import MsAsideContainer from "../../../common/components/MsAsideContainer"; import MsMainContainer from "../../../common/components/MsMainContainer"; import MsAsideItem from "../../../common/components/MsAsideItem"; import EnvironmentEdit from "./environment/EnvironmentEdit"; -import {hasPermission, listenGoBack, removeGoBackListener} from "../../../../../common/js/utils"; +import {getUUID, hasPermission, listenGoBack, removeGoBackListener} from "../../../../../common/js/utils"; import {Environment, parseEnvironment} from "../model/EnvironmentModel"; import MsDialogHeader from "@/business/components/common/components/MsDialogHeader"; diff --git a/frontend/src/business/components/project/menu/EnvironmentList.vue b/frontend/src/business/components/project/menu/EnvironmentList.vue index 89aedeee18..114180c18f 100644 --- a/frontend/src/business/components/project/menu/EnvironmentList.vue +++ b/frontend/src/business/components/project/menu/EnvironmentList.vue @@ -132,7 +132,7 @@ import EnvironmentEdit from "@/business/components/api/test/components/environme import MsAsideItem from "@/business/components/common/components/MsAsideItem"; import MsAsideContainer from "@/business/components/common/components/MsAsideContainer"; import ProjectSwitch from "@/business/components/common/head/ProjectSwitch"; -import {downloadFile, getCurrentProjectID} from "@/common/js/utils"; +import {downloadFile, getCurrentProjectID, getUUID} from "@/common/js/utils"; import EnvironmentImport from "@/business/components/project/menu/EnvironmentImport"; import MsMainContainer from "@/business/components/common/components/MsMainContainer"; import MsContainer from "@/business/components/common/components/MsContainer"; diff --git a/frontend/src/business/components/project/menu/appmanage/AppManage.vue b/frontend/src/business/components/project/menu/appmanage/AppManage.vue index 55afb3530b..20f4d7a76c 100644 --- a/frontend/src/business/components/project/menu/appmanage/AppManage.vue +++ b/frontend/src/business/components/project/menu/appmanage/AppManage.vue @@ -105,24 +105,45 @@ - - {{ $t('commons.view_settings') }} - - - - - - + + + + {{ this.$t('commons.enable_settings') }} + + + + + + + + + + + {{ $t('commons.view_settings') }} + + + + + + + @@ -176,7 +197,9 @@ export default { cleanApiReport: false, cleanApiReportExpr: "", cleanLoadReport: false, - cleanLoadReportExpr: "" + cleanLoadReportExpr: "", + cleanUiReport: false, + cleanUiReportExpr: "" }, count: 0, isXpack: false, @@ -193,6 +216,7 @@ export default { config: { trackShareReportTime: "", performanceShareReportTime: "", + uiShareReportTime: "", apiShareReportTime: "", caseCustomNum: false, scenarioCustomNum: false, @@ -207,6 +231,8 @@ export default { cleanApiReportExpr: "", cleanLoadReport: false, cleanLoadReportExpr: "", + cleanUiReport: false, + cleanUiReportExpr: "", urlRepeatable: false, shareReport: true } diff --git a/frontend/src/business/components/settings/workspace/environment/EnvironmentList.vue b/frontend/src/business/components/settings/workspace/environment/EnvironmentList.vue index 029027a74f..ed26c092af 100644 --- a/frontend/src/business/components/settings/workspace/environment/EnvironmentList.vue +++ b/frontend/src/business/components/settings/workspace/environment/EnvironmentList.vue @@ -145,7 +145,7 @@ import EnvironmentEdit from "@/business/components/api/test/components/environme import MsAsideItem from "@/business/components/common/components/MsAsideItem"; import MsAsideContainer from "@/business/components/common/components/MsAsideContainer"; import ProjectSwitch from "@/business/components/common/head/ProjectSwitch"; -import {downloadFile, strMapToObj} from "@/common/js/utils"; +import {downloadFile, getUUID, strMapToObj} from "@/common/js/utils"; import EnvironmentImport from "@/business/components/project/menu/EnvironmentImport"; import ShowMoreBtn from "@/business/components/track/case/components/ShowMoreBtn"; import {_handleSelect, _handleSelectAll, getSelectDataCounts, setUnSelectIds} from "@/common/js/tableUtils"; diff --git a/frontend/src/business/components/xpack b/frontend/src/business/components/xpack index be7591f7f5..c698d5eac1 160000 --- a/frontend/src/business/components/xpack +++ b/frontend/src/business/components/xpack @@ -1 +1 @@ -Subproject commit be7591f7f5077a77ee5abce16461af30f3ac8666 +Subproject commit c698d5eac1182ad0c51f4ababdcc16c4b713416b diff --git a/frontend/src/i18n/en-US.js b/frontend/src/i18n/en-US.js index 34a3d2beac..2978a083ee 100644 --- a/frontend/src/i18n/en-US.js +++ b/frontend/src/i18n/en-US.js @@ -827,6 +827,7 @@ export default { timing_clean_plan_report: "Regularly clean up test report", timing_clean_api_report: "Regularly clean up api report", timing_clean_load_report: "Regularly clean up performance report", + timing_clean_ui_report: "Regularly clean up ui report", keep_recent: "Keep recent", please_select_cleaning_time: "please select cleaning time!" }, diff --git a/frontend/src/i18n/zh-CN.js b/frontend/src/i18n/zh-CN.js index a7d35fcc70..e4bcb2413e 100644 --- a/frontend/src/i18n/zh-CN.js +++ b/frontend/src/i18n/zh-CN.js @@ -830,7 +830,8 @@ export default { }, timing_clean_plan_report: "定时清理测试计划报告", timing_clean_api_report: "定时清理接口测试报告", - timing_clean_load_report: "定时清理性能测试报告", + timing_clean_load_report: "定时清理性能测试报告", + timing_clean_ui_report: "定时清理UI测试报告", keep_recent: "保留最近", please_select_cleaning_time: "请选择清理时间!" }, diff --git a/frontend/src/i18n/zh-TW.js b/frontend/src/i18n/zh-TW.js index 699db43145..77dd9c1fa9 100644 --- a/frontend/src/i18n/zh-TW.js +++ b/frontend/src/i18n/zh-TW.js @@ -831,6 +831,7 @@ export default { timing_clean_plan_report: "定時清理測試計劃報告", timing_clean_api_report: "定時清理接口測試報告", timing_clean_load_report: "定時清理性能測試報告", + timing_clean_ui_report: "定時清理UI測試報告", keep_recent: "保留最近", please_select_cleaning_time: "請選擇清理時間!" }, diff --git a/frontend/src/template/report/ui/share/ShareUiReportTemplate.vue b/frontend/src/template/report/ui/share/ShareUiReportTemplate.vue new file mode 100644 index 0000000000..8b68d48dcf --- /dev/null +++ b/frontend/src/template/report/ui/share/ShareUiReportTemplate.vue @@ -0,0 +1,36 @@ + + + + + diff --git a/frontend/src/template/report/ui/share/share-ui-report.html b/frontend/src/template/report/ui/share/share-ui-report.html new file mode 100644 index 0000000000..c3f76daf2b --- /dev/null +++ b/frontend/src/template/report/ui/share/share-ui-report.html @@ -0,0 +1,13 @@ + + + + + + + + Ui Report + + +
+ + diff --git a/frontend/src/template/report/ui/share/share-ui-report.js b/frontend/src/template/report/ui/share/share-ui-report.js new file mode 100644 index 0000000000..2e57da9f3c --- /dev/null +++ b/frontend/src/template/report/ui/share/share-ui-report.js @@ -0,0 +1,4 @@ +import ShareUiReportTemplate from "@/template/report/ui/share/ShareUiReportTemplate"; +import uiReportUse from "@/template/report/ui/uiReportUse"; + +uiReportUse('#shareUiReport', ShareUiReportTemplate); diff --git a/frontend/src/template/report/ui/uiReportUse.js b/frontend/src/template/report/ui/uiReportUse.js new file mode 100644 index 0000000000..663e38ebf9 --- /dev/null +++ b/frontend/src/template/report/ui/uiReportUse.js @@ -0,0 +1,43 @@ +import Vue from 'vue'; +import ElementUI, {Button, Card, Col, Form, FormItem, Input, Main, Popover, Row, 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"; + + +function uiReportUse(id, template) { + 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(TableColumn); + Vue.use(Table); + Vue.use(filters); + Vue.use(icon); + Vue.use(message); + Vue.use(ajax); + Vue.use(Popover); + + new Vue({ + el: id, + i18n, + render: h => h(template) + }); +} + +export default uiReportUse; diff --git a/frontend/vue.config.js b/frontend/vue.config.js index ece235134e..84d7b0320d 100644 --- a/frontend/vue.config.js +++ b/frontend/vue.config.js @@ -49,6 +49,11 @@ module.exports = { template: "src/template/report/api/share/share-api-report.html", filename: "share-api-report.html", }, + shareUiReport: { + entry: "src/template/report/ui/share/share-ui-report.js", + template: "src/template/report/ui/share/share-ui-report.html", + filename: "share-ui-report.html", + }, enterpriseReport: { entry: "src/template/enterprise/share/share-enterprise-report.js", template: "src/template/enterprise/share/share-enterprise-report.html",