fix: 修复启用禁用模块页面上的入口没有隐藏的问题

This commit is contained in:
Captain.B 2021-04-23 18:06:33 +08:00 committed by 刘瑞斌
parent 7d51f5ddef
commit 699fcde198
11 changed files with 520 additions and 433 deletions

View File

@ -7,7 +7,9 @@
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="ref">{{ $t('api_test.automation.view_ref') }}</el-dropdown-item>
<el-dropdown-item command="schedule" v-tester>{{ $t('api_test.automation.schedule') }}</el-dropdown-item>
<el-dropdown-item command="create_performance" v-tester>{{ $t('api_test.create_performance_test') }}</el-dropdown-item>
<el-dropdown-item command="create_performance" v-tester v-modules="['performance']">
{{ $t('api_test.create_performance_test') }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<ms-reference-view @openScenario="openScenario" ref="viewRef"/>

View File

@ -5,7 +5,9 @@
</el-link>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="ref">{{ $t('api_test.automation.view_ref') }}</el-dropdown-item>
<el-dropdown-item command="create_performance">{{ $t('api_test.create_performance_test') }}</el-dropdown-item>
<el-dropdown-item command="create_performance" v-modules="['performance']">
{{ $t('api_test.create_performance_test') }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>

View File

@ -4,23 +4,43 @@ export const PRIORITY = [
{name: 'P1', id: 'P1'},
{name: 'P2', id: 'P2'},
{name: 'P3', id: 'P3'}
]
];
export const CASE_ORDER = [
{label: 'api_test.definition.request.grade_order_asc', name: 'priority', type: 'desc', id: 'grade_order_asc'},
{label: 'api_test.definition.request.grade_order_desc', name: 'priority', type: 'asc', id: 'grade_order_desc'},
{label: 'api_test.definition.request.create_time_order_asc', name: 'create_time', type: 'asc', id: 'create_time_order_asc'},
{label: 'api_test.definition.request.create_time_order_desc', name: 'create_time', type: 'desc', id: 'create_time_order_desc'},
{label: 'api_test.definition.request.update_time_order_asc', name: 'update_time', type: 'asc', id: 'update_time_order_asc'},
{label: 'api_test.definition.request.update_time_order_desc', name: 'update_time', type: 'desc', id: 'update_time_order_desc'}
]
{
label: 'api_test.definition.request.create_time_order_asc',
name: 'create_time',
type: 'asc',
id: 'create_time_order_asc'
},
{
label: 'api_test.definition.request.create_time_order_desc',
name: 'create_time',
type: 'desc',
id: 'create_time_order_desc'
},
{
label: 'api_test.definition.request.update_time_order_asc',
name: 'update_time',
type: 'asc',
id: 'update_time_order_asc'
},
{
label: 'api_test.definition.request.update_time_order_desc',
name: 'update_time',
type: 'desc',
id: 'update_time_order_desc'
}
];
export const OPTIONS = [
{value: 'HTTP', name: 'HTTP'},
{value: 'TCP', name: 'TCP'},
{value: 'SQL', name: 'SQL'},
{value: 'DUBBO', name: 'DUBBO'}
]
];
export const DEFAULT_DATA = [{
"id": "gc",
@ -32,7 +52,7 @@ export const DEFAULT_DATA = [{
"name": "全部模块",
"level": 0,
"children": [],
}]
}];
export const REQ_METHOD = [
{id: 'GET', label: 'GET'},
@ -43,51 +63,51 @@ export const REQ_METHOD = [
{id: 'OPTIONS', label: 'OPTIONS'},
{id: 'HEAD', label: 'HEAD'},
{id: 'CONNECT', label: 'CONNECT'}
]
];
export const TCP_METHOD = [
{id: 'TCP', label: 'TCP'}
]
];
export const SQL_METHOD = [
{id: 'SQL', label: 'SQL'}
]
];
export const DUBBO_METHOD = [
{id: 'dubbo://', label: 'dubbo://'},
]
];
export const CASE_PRIORITY = [
{id: 'P0', label: 'P0'},
{id: 'P1', label: 'P1'},
{id: 'P2', label: 'P2'},
{id: 'P3', label: 'P3'}
]
];
export const REVIEW_STATUS = [
{id: 'Prepare', label: '未评审'},
{id: 'Pass', label: '通过'},
{id: 'UnPass', label: '未通过'}
]
];
export const API_STATUS = [
{id: 'Prepare', label: '未开始'},
{id: 'Underway', label: '进行中'},
{id: 'Completed', label: '已完成'}
]
];
export const TEST = [
{id: 'performance', name: '性能测试'},
{id: 'testcase', name: '接口用例'},
{id: 'automation', name: '场景测试'}
]
{id: 'performance', name: '性能测试', module: 'performance'},
{id: 'testcase', name: '接口用例', module: 'api'},
{id: 'automation', name: '场景测试', module: 'api'}
];
export const API_METHOD_COLOUR = [
['GET', "#61AFFE"], ['POST', '#49CC90'], ['PUT', '#fca130'],
['PATCH', '#E2EE11'], ['DELETE', '#f93e3d'], ['OPTIONS', '#0EF5DA'],
['HEAD', '#8E58E7'], ['CONNECT', '#90AFAE'],
['DUBBO', '#C36EEF'], ['dubbo://', '#C36EEF'], ['SQL', '#0AEAD4'], ['TCP', '#0A52DF'],
]
];
export const REQUIRED = [
{name: '必填', id: true},
{name: '非必填', id: false}
]
];
export const RESULT_MAP = new Map([
['success', '执行结果:通过'],

View File

@ -6,6 +6,7 @@
active-text-color="#fff"
:default-active="activeIndex"
@select="handleSelect"
:key="menuKey"
router>
<el-menu-item index="/track" v-if="check('testTrack')" v-permission="['test_manager','test_user','test_viewer']">
@ -35,6 +36,7 @@
import {LicenseKey} from '@/common/js/constants';
import {mapGetters} from "vuex";
import {hasLicense} from "@/common/js/utils";
import {MODULE_CHANGE, ModuleEvent} from "@/business/components/common/head/ListEvent";
const requireContext = require.context('@/business/components/xpack/', true, /router\.js$/);
const report = requireContext.keys().map(key => requireContext(key).report);
@ -49,7 +51,8 @@ export default {
return {
activeIndex: '/',
isReport: isReport,
modules: {}
modules: {},
menuKey: 0,
};
},
props: {
@ -75,6 +78,8 @@ export default {
module.default.listModules(this);
}
}
this.registerEvents();
},
computed: {
...mapGetters([
@ -100,6 +105,15 @@ export default {
return this.modules[key] === 'ENABLE';
}
return true;
},
registerEvents() {
ModuleEvent.$on(MODULE_CHANGE, () => {
if (module.default) {
module.default.listModules(this).then(() => {
this.menuKey++;
});
}
});
}
}
};

View File

@ -1,7 +1,10 @@
import Vue from 'vue'
import Vue from 'vue';
export const LIST_CHANGE = 'LIST_CHANGE';
export let ApiEvent = new Vue();
export let TrackEvent = new Vue();
export let PerformanceEvent = new Vue();
export const MODULE_CHANGE = 'MODULE_CHANGE';
export let ModuleEvent = new Vue();

View File

@ -1,17 +1,19 @@
<template>
<el-tabs class="other-info-tabs" v-loading="result.loading" v-model="tabActiveName">
<el-tab-pane :label="$t('commons.remark')" name="remark">
<el-row >
<el-row>
<ms-rich-text :disabled="readOnly" :content="form.remark" @updateRichText="updateRemark"/>
</el-row>
</el-tab-pane>
<el-tab-pane :label="$t('test_track.case.relate_test')" name="relateTest">
<el-col v-if="form.list" :span="7" :offset="1">
<span class="cast_label">关联测试</span>
<span v-for="(item,index) in form.list" :key="index">
<el-button @click="openTest(item)" type="text" style="margin-left: 7px;">{{ item.testName }}</el-button>
<el-col v-if="form.list" :span="7" :offset="1">
<span class="cast_label">关联测试</span>
<span v-for="(item,index) in form.list" :key="index">
<el-button @click="openTest(item)" type="text" style="margin-left: 7px;">{{
item.testName
}}</el-button>
</span>
</el-col>
</el-col>
<el-col v-else :span="7" style="margin-top: 10px;">
<el-form-item :label="$t('test_track.case.relate_test')" :label-width="labelWidth">
<el-cascader :options="sysList" filterable placeholder="请选择要关联的测试" show-all-levels
@ -86,6 +88,7 @@ import MsRichText from "@/business/components/track/case/components/MsRichText";
import {TEST} from "@/business/components/api/definition/model/JsonData";
import TestCaseAttachment from "@/business/components/track/case/components/TestCaseAttachment";
import TestCaseIssueRelate from "@/business/components/track/case/components/TestCaseIssueRelate";
import {enableModules} from "@/common/js/utils";
export default {
name: "TestCaseEditOtherInfo",
@ -105,7 +108,7 @@ export default {
//lazy: true,
//lazyLoad:this.lazyLoad
},
}
};
},
watch: {
tabActiveName() {
@ -177,10 +180,10 @@ export default {
aTag.download = file.name;
aTag.href = URL.createObjectURL(blob);
aTag.click();
URL.revokeObjectURL(aTag.href)
URL.revokeObjectURL(aTag.href);
} else {
// IE10+
navigator.msSaveBlob(blob, this.filename)
navigator.msSaveBlob(blob, this.filename);
}
}).catch(e => {
Message.error({message: e.message, showClose: true});
@ -240,19 +243,23 @@ export default {
this.result = {loading: true};
this.$get("demand/list/" + this.projectId).then(response => {
this.demandOptions = response.data.data;
this.demandOptions.unshift({id: 'other', name: this.$t('test_track.case.other'), platform: 'Other'})
this.demandOptions.unshift({id: 'other', name: this.$t('test_track.case.other'), platform: 'Other'});
this.result = {loading: false};
}).catch(() => {
this.demandOptions.unshift({id: 'other', name: this.$t('test_track.case.other'), platform: 'Other'})
this.demandOptions.unshift({id: 'other', name: this.$t('test_track.case.other'), platform: 'Other'});
this.result = {loading: false};
})
});
}
},
async loadOptions(sysLib) {
if (this.form.list) {
return;
}
sysLib = TEST
.filter(item => {
return enableModules([item.module]);
})//
.map(item => ({
value: item.id,
label: item.name,
@ -288,14 +295,14 @@ export default {
leaf: true
}));
this.result.loading = false;
resolve(data)
resolve(data);
}).catch((err) => {
reject(err)
reject(err);
});
});
},
}
}
};
</script>
<style scoped>

View File

@ -13,15 +13,18 @@
<el-menu v-if="isMenuShow" :active-text-color="color" :default-active="activeIndex"
class="el-menu-demo header-menu" mode="horizontal" @select="handleSelect">
<el-menu-item index="functional">功能测试用例</el-menu-item>
<el-menu-item index="api">接口测试用例</el-menu-item>
<el-menu-item index="load">性能测试用例</el-menu-item>
<el-menu-item index="api" v-modules="['api']">接口测试用例</el-menu-item>
<el-menu-item index="load" v-modules="['performance']">性能测试用例</el-menu-item>
<el-menu-item index="report">报告统计</el-menu-item>
</el-menu>
</template>
</ms-test-plan-header-bar>
<test-plan-functional v-if="activeIndex === 'functional'" :redirectCharType="redirectCharType" :clickType="clickType" :plan-id="planId"/>
<test-plan-api v-if="activeIndex === 'api'" :redirectCharType="redirectCharType" :clickType="clickType" :plan-id="planId"/>
<test-plan-load v-if="activeIndex === 'load'" :redirectCharType="redirectCharType" :clickType="clickType" :plan-id="planId"/>
<test-plan-functional v-if="activeIndex === 'functional'" :redirectCharType="redirectCharType"
:clickType="clickType" :plan-id="planId"/>
<test-plan-api v-if="activeIndex === 'api'" :redirectCharType="redirectCharType" :clickType="clickType"
:plan-id="planId"/>
<test-plan-load v-if="activeIndex === 'load'" :redirectCharType="redirectCharType" :clickType="clickType"
:plan-id="planId"/>
<test-case-statistics-report-view :test-plan="currentPlan" v-if="activeIndex === 'report'"/>
<test-report-template-list @openReport="openReport" ref="testReportTemplateList"/>
@ -32,132 +35,133 @@
<script>
import NodeTree from "../../common/NodeTree";
import TestPlanTestCaseList from "./comonents/functional/FunctionalTestCaseList";
import TestCaseRelevance from "./comonents/functional/TestCaseFunctionalRelevance";
import SelectMenu from "../../common/SelectMenu";
import MsContainer from "../../../common/components/MsContainer";
import MsAsideContainer from "../../../common/components/MsAsideContainer";
import MsMainContainer from "../../../common/components/MsMainContainer";
import MsTestPlanHeaderBar from "./comonents/head/TestPlanHeaderBar";
import TestPlanFunctional from "./comonents/functional/TestPlanFunctional";
import TestPlanApi from "./comonents/api/TestPlanApi";
import TestCaseStatisticsReportView from "./comonents/report/statistics/TestCaseStatisticsReportView";
import TestReportTemplateList from "./comonents/TestReportTemplateList";
import TestPlanLoad from "@/business/components/track/plan/view/comonents/load/TestPlanLoad";
import NodeTree from "../../common/NodeTree";
import TestPlanTestCaseList from "./comonents/functional/FunctionalTestCaseList";
import TestCaseRelevance from "./comonents/functional/TestCaseFunctionalRelevance";
import SelectMenu from "../../common/SelectMenu";
import MsContainer from "../../../common/components/MsContainer";
import MsAsideContainer from "../../../common/components/MsAsideContainer";
import MsMainContainer from "../../../common/components/MsMainContainer";
import MsTestPlanHeaderBar from "./comonents/head/TestPlanHeaderBar";
import TestPlanFunctional from "./comonents/functional/TestPlanFunctional";
import TestPlanApi from "./comonents/api/TestPlanApi";
import TestCaseStatisticsReportView from "./comonents/report/statistics/TestCaseStatisticsReportView";
import TestReportTemplateList from "./comonents/TestReportTemplateList";
import TestPlanLoad from "@/business/components/track/plan/view/comonents/load/TestPlanLoad";
export default {
name: "TestPlanView",
components: {
TestReportTemplateList,
TestCaseStatisticsReportView,
TestPlanApi,
TestPlanFunctional,
MsTestPlanHeaderBar,
MsMainContainer,
MsAsideContainer, MsContainer, NodeTree, TestPlanTestCaseList, TestCaseRelevance, SelectMenu, TestPlanLoad},
data() {
return {
testPlans: [],
currentPlan: {},
activeIndex: "functional",
isMenuShow: true,
//-
redirectCharType:'',
//-
clickType:'',
}
},
computed: {
planId: function () {
return this.$route.params.planId;
},
color: function () {
return `var(--primary_color)`
}
},
watch: {
'$route.params.planId'() {
this.genRedirectParam();
this.getTestPlans();
}
},
mounted() {
this.getTestPlans();
},
activated() {
this.genRedirectParam();
},
methods: {
genRedirectParam(){
this.redirectCharType = this.$route.params.charType;
this.clickType = this.$route.params.clickType;
if(this.redirectCharType != ""){
if(this.redirectCharType=='scenario'){
this.activeIndex = 'api';
}else if(this.redirectCharType != null && this.redirectCharType != ''){
this.activeIndex = this.redirectCharType;
}
}else{
this.activeIndex = "functional";
}
},
getTestPlans() {
this.$post('/test/plan/list/all', {}, response => {
this.testPlans = response.data;
this.testPlans.forEach(plan => {
if (this.planId && plan.id === this.planId) {
this.currentPlan = plan;
}
});
});
},
changePlan(plan) {
this.currentPlan = plan;
this.$router.push('/track/plan/view/' + plan.id);
},
handleSelect(key) {
this.activeIndex = key;
if (key === 'report' && !this.currentPlan.reportId) {
this.$refs.testReportTemplateList.open(this.planId);
}
},
openTemplateReport() {
this.$refs.testReportTemplateList.open(this.planId);
},
openReport(planId, id) {
this.currentPlan.reportId = id;
},
reloadMenu() {
this.isMenuShow = false;
this.$nextTick(() => {
this.isMenuShow = true;
});
}
},
export default {
name: "TestPlanView",
components: {
TestReportTemplateList,
TestCaseStatisticsReportView,
TestPlanApi,
TestPlanFunctional,
MsTestPlanHeaderBar,
MsMainContainer,
MsAsideContainer, MsContainer, NodeTree, TestPlanTestCaseList, TestCaseRelevance, SelectMenu, TestPlanLoad
},
data() {
return {
testPlans: [],
currentPlan: {},
activeIndex: "functional",
isMenuShow: true,
//-
redirectCharType: '',
//-
clickType: '',
};
},
computed: {
planId: function () {
return this.$route.params.planId;
},
color: function () {
return `var(--primary_color)`;
}
},
watch: {
'$route.params.planId'() {
this.genRedirectParam();
this.getTestPlans();
}
},
mounted() {
this.getTestPlans();
},
activated() {
this.genRedirectParam();
},
methods: {
genRedirectParam() {
this.redirectCharType = this.$route.params.charType;
this.clickType = this.$route.params.clickType;
if (this.redirectCharType != "") {
if (this.redirectCharType == 'scenario') {
this.activeIndex = 'api';
} else if (this.redirectCharType != null && this.redirectCharType != '') {
this.activeIndex = this.redirectCharType;
}
} else {
this.activeIndex = "functional";
}
},
getTestPlans() {
this.$post('/test/plan/list/all', {}, response => {
this.testPlans = response.data;
this.testPlans.forEach(plan => {
if (this.planId && plan.id === this.planId) {
this.currentPlan = plan;
}
});
});
},
changePlan(plan) {
this.currentPlan = plan;
this.$router.push('/track/plan/view/' + plan.id);
},
handleSelect(key) {
this.activeIndex = key;
if (key === 'report' && !this.currentPlan.reportId) {
this.$refs.testReportTemplateList.open(this.planId);
}
},
openTemplateReport() {
this.$refs.testReportTemplateList.open(this.planId);
},
openReport(planId, id) {
this.currentPlan.reportId = id;
},
reloadMenu() {
this.isMenuShow = false;
this.$nextTick(() => {
this.isMenuShow = true;
});
}
},
};
</script>
<style scoped>
.select-menu {
display: inline-block;
}
.select-menu {
display: inline-block;
}
/deep/ .ms-main-container {
height: calc(100vh - 80px - 53px);
}
/deep/ .ms-main-container {
height: calc(100vh - 80px - 53px);
}
/deep/ .ms-aside-container {
height: calc(100vh - 80px - 53px);
margin-top: 1px;
}
/deep/ .ms-aside-container {
height: calc(100vh - 80px - 53px);
margin-top: 1px;
}
.header-menu.el-menu--horizontal > li {
height: 49px;
line-height: 50px;
color: dimgray;
}
.header-menu.el-menu--horizontal > li {
height: 49px;
line-height: 50px;
color: dimgray;
}
</style>

@ -1 +1 @@
Subproject commit e4b1f5838f00791b42b394ad00a365a14f28be83
Subproject commit e7709b9a340394e78610b91105b2cec0f1b8289d

View File

@ -11,7 +11,7 @@ import YanProgress from 'yan-progress';
import './permission' // permission control
import i18n from "../i18n/i18n";
import store from "../store";
import {permission, roles, tester, xpack} from './permission'
import {permission, roles, tester, xpack, modules} from './permission';
import chart from "../common/js/chart";
import CalendarHeatmap from "../common/js/calendar-heatmap";
import '../common/css/menu-header.css';
@ -55,6 +55,8 @@ Vue.directive('xpack', xpack);
Vue.directive('tester', tester);
Vue.directive('modules', modules);
//支持左右拖拽
Vue.directive('left-to-right-drag', left2RightDrag);
Vue.directive('right-to-left-drag', right2LeftDrag);

View File

@ -1,11 +1,59 @@
import router from './components/common/router/router'
import router from './components/common/router/router';
import {TokenKey} from '@/common/js/constants';
import {checkoutTestManagerOrTestUser, hasLicense, hasRolePermissions, hasRoles} from "@/common/js/utils";
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import {
checkoutTestManagerOrTestUser,
enableModules,
hasLicense,
hasRolePermissions,
hasRoles
} from "@/common/js/utils";
import NProgress from 'nprogress'; // progress bar
import 'nprogress/nprogress.css'; // progress bar style
const whiteList = ['/login']; // no redirect whitelist
NProgress.configure({showSpinner: false}) // NProgress Configuration
NProgress.configure({showSpinner: false}); // NProgress Configuration
function checkTestManagerOrTestUser(el, binding) {
let v = checkoutTestManagerOrTestUser();
if (!v) {
el.parentNode && el.parentNode.removeChild(el);
}
}
function checkLicense(el, binding, type) {
let v = hasLicense();
if (!v) {
el.parentNode && el.parentNode.removeChild(el);
}
}
function checkRolePermission(el, binding, type) {
const {value} = binding;
if (value && value instanceof Array && value.length > 0) {
const permissionRoles = value;
let hasPermission = false;
if (type === 'roles') {
hasPermission = hasRoles(...permissionRoles);
} else if (type === 'permission') {
hasPermission = hasRolePermissions(...permissionRoles);
}
if (!hasPermission) {
el.parentNode && el.parentNode.removeChild(el);
}
}
}
function checkModule(el, binding) {
const {value} = binding;
if (value && value instanceof Array && value.length > 0) {
let v = enableModules(...value);
if (!v) {
el.parentNode && el.parentNode.removeChild(el);
}
}
}
export const permission = {
inserted(el, binding) {
@ -31,37 +79,11 @@ export const tester = {
}
};
function checkTestManagerOrTestUser(el, binding) {
let v = checkoutTestManagerOrTestUser();
if (!v) {
el.parentNode && el.parentNode.removeChild(el)
export const modules = {
inserted(el, binding) {
checkModule(el, binding);
}
}
function checkLicense(el, binding, type) {
let v = hasLicense()
if (!v) {
el.parentNode && el.parentNode.removeChild(el)
}
}
function checkRolePermission(el, binding, type) {
const {value} = binding;
if (value && value instanceof Array && value.length > 0) {
const permissionRoles = value;
let hasPermission = false;
if (type === 'roles') {
hasPermission = hasRoles(...permissionRoles);
} else if (type === 'permission') {
hasPermission = hasRolePermissions(...permissionRoles);
}
if (!hasPermission) {
el.parentNode && el.parentNode.removeChild(el)
}
}
}
};
router.beforeEach(async (to, from, next) => {
// start progress bar
@ -77,7 +99,7 @@ router.beforeEach(async (to, from, next) => {
} else {
// const roles = user.roles.filter(r => r.id);
// TODO 设置路由的权限
next()
next();
}
} else {
/* has no token*/

View File

@ -3,7 +3,8 @@ import {
COUNT_NUMBER_SHALLOW,
LicenseKey,
ORIGIN_COLOR,
ORIGIN_COLOR_SHALLOW, PRIMARY_COLOR,
ORIGIN_COLOR_SHALLOW,
PRIMARY_COLOR,
PROJECT_ID,
REFRESH_SESSION_USER_URL,
ROLE_ADMIN,
@ -18,363 +19,373 @@ import {jsPDF} from "jspdf";
import JSEncrypt from 'jsencrypt';
export function hasRole(role) {
let user = getCurrentUser();
let roles = user.roles.map(r => r.id);
return roles.indexOf(role) > -1;
let user = getCurrentUser();
let roles = user.roles.map(r => r.id);
return roles.indexOf(role) > -1;
}
// 是否含有某个角色
export function hasRoles(...roles) {
let user = getCurrentUser();
let rs = user.roles.map(r => r.id);
for (let item of roles) {
if (rs.indexOf(item) > -1) {
return true;
}
let user = getCurrentUser();
let rs = user.roles.map(r => r.id);
for (let item of roles) {
if (rs.indexOf(item) > -1) {
return true;
}
return false;
}
return false;
}
export function hasRolePermission(role) {
let user = getCurrentUser();
for (let ur of user.userRoles) {
if (role === ur.roleId) {
if (ur.roleId === ROLE_ADMIN) {
return true;
} else if (ur.roleId === ROLE_ORG_ADMIN && user.lastOrganizationId === ur.sourceId) {
return true;
} else if (user.lastWorkspaceId === ur.sourceId) {
return true;
}
}
let user = getCurrentUser();
for (let ur of user.userRoles) {
if (role === ur.roleId) {
if (ur.roleId === ROLE_ADMIN) {
return true;
} else if (ur.roleId === ROLE_ORG_ADMIN && user.lastOrganizationId === ur.sourceId) {
return true;
} else if (user.lastWorkspaceId === ur.sourceId) {
return true;
}
}
return false
}
return false;
}
export function hasLicense() {
let v = localStorage.getItem(LicenseKey);
return v === 'valid';
let v = localStorage.getItem(LicenseKey);
return v === 'valid';
}
//是否含有对应组织或工作空间的角色
export function hasRolePermissions(...roles) {
for (let role of roles) {
if (hasRolePermission(role)) {
return true;
}
for (let role of roles) {
if (hasRolePermission(role)) {
return true;
}
return false;
}
return false;
}
export function checkoutCurrentOrganization() {
// 查看当前用户是否是 lastOrganizationId 的组织管理员
return hasRolePermissions(ROLE_ORG_ADMIN);
// 查看当前用户是否是 lastOrganizationId 的组织管理员
return hasRolePermissions(ROLE_ORG_ADMIN);
}
export function checkoutCurrentWorkspace() {
// 查看当前用户是否是 lastWorkspaceId 的工作空间用户
return hasRolePermissions(ROLE_TEST_MANAGER, ROLE_TEST_USER, ROLE_TEST_VIEWER);
// 查看当前用户是否是 lastWorkspaceId 的工作空间用户
return hasRolePermissions(ROLE_TEST_MANAGER, ROLE_TEST_USER, ROLE_TEST_VIEWER);
}
export function checkoutTestManagerOrTestUser() {
return hasRolePermissions(ROLE_TEST_MANAGER, ROLE_TEST_USER);
return hasRolePermissions(ROLE_TEST_MANAGER, ROLE_TEST_USER);
}
export function getCurrentOrganizationId() {
let user = getCurrentUser();
return user.lastOrganizationId;
let user = getCurrentUser();
return user.lastOrganizationId;
}
export function getCurrentWorkspaceId() {
let user = getCurrentUser();
return user.lastWorkspaceId;
let user = getCurrentUser();
return user.lastWorkspaceId;
}
export function getCurrentUser() {
return JSON.parse(localStorage.getItem(TokenKey));
return JSON.parse(localStorage.getItem(TokenKey));
}
export function getCurrentProjectID() {
return localStorage.getItem(PROJECT_ID);
return localStorage.getItem(PROJECT_ID);
}
export function enableModules(...modules) {
for (let module of modules) {
let moduleStatus = localStorage.getItem('module_' + module);
if (moduleStatus === 'DISABLE') {
return false;
}
}
return true;
}
export function saveLocalStorage(response) {
// 登录信息保存 cookie
localStorage.setItem(TokenKey, JSON.stringify(response.data));
let rolesArray = response.data.roles;
let roles = rolesArray.map(r => r.id);
// 保存角色
localStorage.setItem("roles", roles);
// 登录信息保存 cookie
localStorage.setItem(TokenKey, JSON.stringify(response.data));
let rolesArray = response.data.roles;
let roles = rolesArray.map(r => r.id);
// 保存角色
localStorage.setItem("roles", roles);
}
export function saveLicense(data) {
// 保存License
localStorage.setItem(LicenseKey, data);
// 保存License
localStorage.setItem(LicenseKey, data);
}
export function refreshSessionAndCookies(sign, sourceId) {
axios.post(REFRESH_SESSION_USER_URL + "/" + sign + "/" + sourceId).then(r => {
saveLocalStorage(r.data);
window.location.reload();
})
axios.post(REFRESH_SESSION_USER_URL + "/" + sign + "/" + sourceId).then(r => {
saveLocalStorage(r.data);
window.location.reload();
});
}
export function jsonToMap(jsonStr) {
let obj = JSON.parse(jsonStr);
let strMap = new Map();
for (let k of Object.keys(obj)) {
strMap.set(k, obj[k]);
}
return strMap;
let obj = JSON.parse(jsonStr);
let strMap = new Map();
for (let k of Object.keys(obj)) {
strMap.set(k, obj[k]);
}
return strMap;
}
export function mapToJson(strMap) {
let obj = Object.create(null);
for (let [k, v] of strMap) {
obj[k] = v;
}
return JSON.stringify(obj);
let obj = Object.create(null);
for (let [k, v] of strMap) {
obj[k] = v;
}
return JSON.stringify(obj);
}
// 驼峰转换下划线
export function humpToLine(name) {
return name.replace(/([A-Z])/g, "_$1").toLowerCase();
return name.replace(/([A-Z])/g, "_$1").toLowerCase();
}
export function downloadFile(name, content) {
const blob = new Blob([content]);
if ("download" in document.createElement("a")) {
// 非IE下载
// chrome/firefox
let aTag = document.createElement('a');
aTag.download = name;
aTag.href = URL.createObjectURL(blob);
aTag.click();
URL.revokeObjectURL(aTag.href)
} else {
// IE10+下载
navigator.msSaveBlob(blob, name)
}
const blob = new Blob([content]);
if ("download" in document.createElement("a")) {
// 非IE下载
// chrome/firefox
let aTag = document.createElement('a');
aTag.download = name;
aTag.href = URL.createObjectURL(blob);
aTag.click();
URL.revokeObjectURL(aTag.href);
} else {
// IE10+下载
navigator.msSaveBlob(blob, name);
}
}
export function listenGoBack(callback) {
//监听浏览器返回操作,关闭该对话框
if (window.history && window.history.pushState) {
history.pushState(null, null, document.URL);
window.addEventListener('popstate', callback);
}
//监听浏览器返回操作,关闭该对话框
if (window.history && window.history.pushState) {
history.pushState(null, null, document.URL);
window.addEventListener('popstate', callback);
}
}
export function removeGoBackListener(callback) {
window.removeEventListener('popstate', callback);
window.removeEventListener('popstate', callback);
}
export const uuid = function () {
let d = new Date().getTime();
let d2 = (performance && performance.now && (performance.now() * 1000)) || 0;
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
let r = Math.random() * 16;
if (d > 0) {
r = (d + r) % 16 | 0;
d = Math.floor(d / 16);
} else {
r = (d2 + r) % 16 | 0;
d2 = Math.floor(d2 / 16);
}
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
let d = new Date().getTime();
let d2 = (performance && performance.now && (performance.now() * 1000)) || 0;
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
let r = Math.random() * 16;
if (d > 0) {
r = (d + r) % 16 | 0;
d = Math.floor(d / 16);
} else {
r = (d2 + r) % 16 | 0;
d2 = Math.floor(d2 / 16);
}
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
};
export function getUUID() {
function S4() {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}
function S4() {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}
return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
}
export function exportPdf(name, canvasList) {
let pdf = new jsPDF('', 'pt', 'a4');
let pdf = new jsPDF('', 'pt', 'a4');
// 当前页面的当前高度
let currentHeight = 0;
for (let canvas of canvasList) {
if (canvas) {
// 当前页面的当前高度
let currentHeight = 0;
for (let canvas of canvasList) {
if (canvas) {
let contentWidth = canvas.width;
let contentHeight = canvas.height;
let contentWidth = canvas.width;
let contentHeight = canvas.height;
//a4纸的尺寸[595.28,841.89]
let a4Width = 592.28;
let a4Height = 841.89;
//a4纸的尺寸[595.28,841.89]
let a4Width = 592.28;
let a4Height = 841.89;
// html页面生成的canvas在pdf中图片的宽高
let imgWidth = a4Width;
let imgHeight = a4Width / contentWidth * contentHeight;
// html页面生成的canvas在pdf中图片的宽高
let imgWidth = a4Width;
let imgHeight = a4Width / contentWidth * contentHeight;
let pageData = canvas.toDataURL('image/jpeg', 1.0);
let pageData = canvas.toDataURL('image/jpeg', 1.0);
// 当前图片的剩余高度
let leftHeight = imgHeight;
// 当前图片的剩余高度
let leftHeight = imgHeight;
// 当前页面的剩余高度
let blankHeight = a4Height - currentHeight;
// 当前页面的剩余高度
let blankHeight = a4Height - currentHeight;
if (leftHeight > blankHeight) {
//页面偏移
let position = 0;
while (leftHeight > 0) {
// 本次添加占用的高度
let occupation = a4Height - currentHeight;
pdf.addImage(pageData, 'JPEG', 0, position + currentHeight, imgWidth, imgHeight);
currentHeight = leftHeight;
leftHeight -= occupation;
position -= occupation;
//避免添加空白页
if (leftHeight > 0) {
pdf.addPage();
currentHeight = 0;
}
}
} else {
pdf.addImage(pageData, 'JPEG', 0, currentHeight, imgWidth, imgHeight);
currentHeight += imgHeight;
}
if (leftHeight > blankHeight) {
//页面偏移
let position = 0;
while (leftHeight > 0) {
// 本次添加占用的高度
let occupation = a4Height - currentHeight;
pdf.addImage(pageData, 'JPEG', 0, position + currentHeight, imgWidth, imgHeight);
currentHeight = leftHeight;
leftHeight -= occupation;
position -= occupation;
//避免添加空白页
if (leftHeight > 0) {
pdf.addPage();
currentHeight = 0;
}
}
} else {
pdf.addImage(pageData, 'JPEG', 0, currentHeight, imgWidth, imgHeight);
currentHeight += imgHeight;
}
}
}
pdf.save(name.replace(" ", "_") + '.pdf');
pdf.save(name.replace(" ", "_") + '.pdf');
}
export function windowPrint(id, zoom) {
//根据div标签ID拿到div中的局部内容
let bdhtml = window.document.body.innerHTML;
let el = document.getElementById(id);
var jubuData = el.innerHTML;
document.getElementsByTagName('body')[0].style.zoom = zoom;
//把获取的 局部div内容赋给body标签, 相当于重置了 body里的内容
window.document.body.innerHTML = jubuData;
//调用打印功能
window.print();
window.document.body.innerHTML = bdhtml;//重新给页面内容赋值;
return false;
//根据div标签ID拿到div中的局部内容
let bdhtml = window.document.body.innerHTML;
let el = document.getElementById(id);
var jubuData = el.innerHTML;
document.getElementsByTagName('body')[0].style.zoom = zoom;
//把获取的 局部div内容赋给body标签, 相当于重置了 body里的内容
window.document.body.innerHTML = jubuData;
//调用打印功能
window.print();
window.document.body.innerHTML = bdhtml;//重新给页面内容赋值;
return false;
}
export function getBodyUploadFiles(obj, runData) {
let bodyUploadFiles = [];
obj.bodyUploadIds = [];
if (runData) {
if (runData instanceof Array) {
runData.forEach(request => {
_getBodyUploadFiles(request, bodyUploadFiles, obj);
});
} else {
_getBodyUploadFiles(runData, bodyUploadFiles, obj);
}
let bodyUploadFiles = [];
obj.bodyUploadIds = [];
if (runData) {
if (runData instanceof Array) {
runData.forEach(request => {
_getBodyUploadFiles(request, bodyUploadFiles, obj);
});
} else {
_getBodyUploadFiles(runData, bodyUploadFiles, obj);
}
return bodyUploadFiles;
}
return bodyUploadFiles;
}
export function _getBodyUploadFiles(request, bodyUploadFiles, obj) {
let body = null;
if (request.hashTree && request.hashTree.length > 0 && request.hashTree[0] && request.hashTree[0].body) {
body = request.hashTree[0].body;
} else if (request.body) {
body = request.body;
}
if (body) {
if (body.kvs) {
body.kvs.forEach(param => {
if (param.files) {
param.files.forEach(item => {
if (item.file) {
if (!item.id) {
let fileId = getUUID().substring(0, 12);
item.name = item.file.name;
item.id = fileId;
}
obj.bodyUploadIds.push(item.id);
bodyUploadFiles.push(item.file);
}
});
}
});
}
if (body.binary) {
body.binary.forEach(param => {
if (param.files) {
param.files.forEach(item => {
if (item.file) {
if (!item.id) {
let fileId = getUUID().substring(0, 12);
item.name = item.file.name;
item.id = fileId;
}
obj.bodyUploadIds.push(item.id);
bodyUploadFiles.push(item.file);
}
});
}
});
let body = null;
if (request.hashTree && request.hashTree.length > 0 && request.hashTree[0] && request.hashTree[0].body) {
body = request.hashTree[0].body;
} else if (request.body) {
body = request.body;
}
if (body) {
if (body.kvs) {
body.kvs.forEach(param => {
if (param.files) {
param.files.forEach(item => {
if (item.file) {
if (!item.id) {
let fileId = getUUID().substring(0, 12);
item.name = item.file.name;
item.id = fileId;
}
obj.bodyUploadIds.push(item.id);
bodyUploadFiles.push(item.file);
}
});
}
});
}
if (body.binary) {
body.binary.forEach(param => {
if (param.files) {
param.files.forEach(item => {
if (item.file) {
if (!item.id) {
let fileId = getUUID().substring(0, 12);
item.name = item.file.name;
item.id = fileId;
}
obj.bodyUploadIds.push(item.id);
bodyUploadFiles.push(item.file);
}
});
}
});
}
}
}
export function handleCtrlSEvent(event, func) {
if (event.keyCode === 83 && event.ctrlKey) {
// console.log('拦截到 ctrl + s');//ctrl+s
func();
event.preventDefault();
event.returnValue = false;
return false;
}
if (event.keyCode === 83 && event.ctrlKey) {
// console.log('拦截到 ctrl + s');//ctrl+s
func();
event.preventDefault();
event.returnValue = false;
return false;
}
}
export function strMapToObj(strMap) {
if (strMap) {
let obj = Object.create(null);
for (let [k, v] of strMap) {
obj[k] = v;
}
return obj;
if (strMap) {
let obj = Object.create(null);
for (let [k, v] of strMap) {
obj[k] = v;
}
return null;
return obj;
}
return null;
}
export function objToStrMap(obj) {
let strMap = new Map();
for (let k of Object.keys(obj)) {
strMap.set(k, obj[k]);
}
return strMap;
let strMap = new Map();
for (let k of Object.keys(obj)) {
strMap.set(k, obj[k]);
}
return strMap;
}
export function setColor(a, b, c, d, e) {
// 顶部菜单背景色
document.body.style.setProperty('--color', a);
document.body.style.setProperty('--color_shallow', b);
// 首页颜色
document.body.style.setProperty('--count_number', c);
document.body.style.setProperty('--count_number_shallow', d);
// 主颜色
document.body.style.setProperty('--primary_color', e);
// 顶部菜单背景色
document.body.style.setProperty('--color', a);
document.body.style.setProperty('--color_shallow', b);
// 首页颜色
document.body.style.setProperty('--count_number', c);
document.body.style.setProperty('--count_number_shallow', d);
// 主颜色
document.body.style.setProperty('--primary_color', e);
}
export function setDefaultTheme() {
setColor(ORIGIN_COLOR, ORIGIN_COLOR_SHALLOW, COUNT_NUMBER, COUNT_NUMBER_SHALLOW, PRIMARY_COLOR);
setColor(ORIGIN_COLOR, ORIGIN_COLOR_SHALLOW, COUNT_NUMBER, COUNT_NUMBER_SHALLOW, PRIMARY_COLOR);
}
export function publicKeyEncrypt(input, publicKey) {
let jsencrypt = new JSEncrypt({default_key_size: 1024});
jsencrypt.setPublicKey(publicKey);
let jsencrypt = new JSEncrypt({default_key_size: 1024});
jsencrypt.setPublicKey(publicKey);
return jsencrypt.encrypt(input);
return jsencrypt.encrypt(input);
}
export function getNodePath(id, moduleOptions) {