fix(系统管理): 修改部分xpackbug&权限补充

This commit is contained in:
xinxin.wu 2024-01-30 17:22:46 +08:00 committed by 刘瑞斌
parent 357325017a
commit 0700c81946
35 changed files with 298 additions and 182 deletions

View File

@ -52,7 +52,6 @@
onBeforeMount(async () => {
try {
await appStore.initSystemPackage(); //
await appStore.initSystemVersion(); //
// license
if (appStore.packageType === 'enterprise') {

View File

@ -19,5 +19,5 @@ export function switchUserOrg(organizationId: string, userId: string) {
// 获取当前系统的版本
export function getPackageType() {
return MSR.get<'community' | 'enterprise'>({ url: PackageTypeUrl }, { ignoreCancelToken: true });
return MSR.get<string>({ url: PackageTypeUrl });
}

View File

@ -78,6 +78,11 @@
margin-top: 16px;
}
}
.arco-modal-wrapper.arco-modal-wrapper-align-center {
.arco-modal {
top: -5% !important;
}
}
.ms-usemodal {
.arco-modal-body {
@apply p-0;

View File

@ -48,7 +48,7 @@
</div>
</div>
</div>
<div class="config-card">
<div v-xpack class="config-card">
<div class="config-card-title">
<div class="config-card-title-text">{{ t('ms.personal.uiLocalExecution') }}</div>
<MsTag

View File

@ -21,13 +21,10 @@
import usePermission from '@/hooks/usePermission';
import appClientMenus from '@/router/app-menus';
import { useAppStore } from '@/store';
import useLicenseStore from '@/store/modules/setting/license';
import { listenerRouteChange } from '@/utils/route-listener';
import { RouteEnum } from '@/enums/routeEnum';
const licenseStore = useLicenseStore();
const copyRouters = cloneDeep(appClientMenus) as RouteRecordRaw[];
const permission = usePermission();
const appStore = useAppStore();
@ -111,6 +108,10 @@
function menuClickHandler() {
activeMenus.value = [appStore.getCurrentTopMenu?.name || ''];
}
onBeforeMount(() => {
appStore.initSystemPackage();
});
</script>
<style lang="less" scoped>

View File

@ -21,7 +21,7 @@ export default {
'menu.workbench': '工作台',
'menu.testPlan': '测试计划',
'menu.bugManagement': '缺陷管理',
'menu.caseManagement': '功能测试',
'menu.caseManagement': '用例管理',
'menu.apiTest': '接口测试',
'menu.apiTest.debug': '接口调试',
'menu.apiTest.management': '接口管理',

View File

@ -1,22 +1,30 @@
import { useAppStore } from '@/store';
import { clearToken, hasToken, isLoginExpires } from '@/utils/auth';
import NProgress from 'nprogress'; // progress bar
import type { LocationQueryRaw, Router } from 'vue-router';
export default function setupUserLoginInfoGuard(router: Router) {
router.beforeEach((to, from, next) => {
router.beforeEach(async (to, from, next) => {
NProgress.start();
if (isLoginExpires()) {
clearToken();
}
if (to.name !== 'login' && hasToken(to.name as string)) {
const appStore = useAppStore();
if (!appStore.packageType) {
await appStore.initSystemPackage();
next();
} else {
next();
}
} else {
// 未登录的都直接跳转至登录页,访问的页面地址缓存到 query 上
if (to.name === 'login') {
next();
return;
}
next({
name: 'login',
query: {

View File

@ -3,28 +3,28 @@ import { PerformanceTestRouteEnum } from '@/enums/routeEnum';
import { DEFAULT_LAYOUT } from '../base';
import type { AppRouteRecordRaw } from '../types';
const PerformanceTest: AppRouteRecordRaw = {
path: '/performance-test',
name: PerformanceTestRouteEnum.PERFORMANCE_TEST,
redirect: '/performance-test/index',
component: DEFAULT_LAYOUT,
meta: {
locale: 'menu.performanceTest',
icon: 'icon-icon_performance-test-filled',
order: 6,
hideChildrenInMenu: true,
roles: ['LOAD_TEST:READ'],
},
children: [
{
path: 'index',
name: 'performanceTestIndex',
component: () => import('@/views/performance-test/index.vue'),
meta: {
roles: ['LOAD_TEST:READ'],
},
},
],
};
// const PerformanceTest: AppRouteRecordRaw = {
// path: '/performance-test',
// name: PerformanceTestRouteEnum.PERFORMANCE_TEST,
// redirect: '/performance-test/index',
// component: DEFAULT_LAYOUT,
// meta: {
// locale: 'menu.performanceTest',
// icon: 'icon-icon_performance-test-filled',
// order: 6,
// hideChildrenInMenu: true,
// roles: ['LOAD_TEST:READ'],
// },
// children: [
// {
// path: 'index',
// name: 'performanceTestIndex',
// component: () => import('@/views/performance-test/index.vue'),
// meta: {
// roles: ['LOAD_TEST:READ'],
// },
// },
// ],
// };
export default PerformanceTest;
// export default PerformanceTest;

View File

@ -227,7 +227,7 @@ const Setting: AppRouteRecordRaw = {
component: () => import('@/views/setting/organization/template/components/ordFieldSetting.vue'),
meta: {
locale: 'menu.settings.organization.templateFieldSetting',
roles: ['*'],
roles: ['ORGANIZATION_TEMPLATE:READ'],
breadcrumbs: [
{
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE,
@ -248,7 +248,7 @@ const Setting: AppRouteRecordRaw = {
component: () => import('@/views/setting/organization/template/components/templateManagement.vue'),
meta: {
locale: 'menu.settings.organization.templateManagementList',
roles: ['*'],
roles: ['ORGANIZATION_TEMPLATE:READ'],
breadcrumbs: [
{
name: SettingRouteEnum.SETTING_ORGANIZATION_TEMPLATE,

View File

@ -3,31 +3,31 @@ import { TestPlanRouteEnum } from '@/enums/routeEnum';
import { DEFAULT_LAYOUT } from '../base';
import type { AppRouteRecordRaw } from '../types';
const TestPlan: AppRouteRecordRaw = {
path: '/test-plan',
name: TestPlanRouteEnum.TEST_PLAN,
redirect: '/test-plan/testPlanIndex',
component: DEFAULT_LAYOUT,
meta: {
locale: 'menu.testPlan',
icon: 'icon-icon_test-tracking_filled',
order: 1,
hideChildrenInMenu: true,
roles: ['TEST_PLAN:READ'],
},
children: [
// 测试计划
{
path: 'testPlanIndex',
name: TestPlanRouteEnum.TEST_PLAN_INDEX,
component: () => import('@/views/test-plan/testPlan/index.vue'),
meta: {
locale: 'menu.testPlan',
roles: ['TEST_PLAN:READ'],
isTopMenu: true,
},
},
],
};
// const TestPlan: AppRouteRecordRaw = {
// path: '/test-plan',
// name: TestPlanRouteEnum.TEST_PLAN,
// redirect: '/test-plan/testPlanIndex',
// component: DEFAULT_LAYOUT,
// meta: {
// locale: 'menu.testPlan',
// icon: 'icon-icon_test-tracking_filled',
// order: 1,
// hideChildrenInMenu: true,
// roles: ['TEST_PLAN:READ'],
// },
// children: [
// // 测试计划
// {
// path: 'testPlanIndex',
// name: TestPlanRouteEnum.TEST_PLAN_INDEX,
// component: () => import('@/views/test-plan/testPlan/index.vue'),
// meta: {
// locale: 'menu.testPlan',
// roles: ['TEST_PLAN:READ'],
// isTopMenu: true,
// },
// },
// ],
// };
export default TestPlan;
// export default TestPlan;

View File

@ -3,28 +3,28 @@ import { UITestRouteEnum } from '@/enums/routeEnum';
import { DEFAULT_LAYOUT } from '../base';
import type { AppRouteRecordRaw } from '../types';
const UiTest: AppRouteRecordRaw = {
path: '/ui-test',
name: UITestRouteEnum.UI_TEST,
redirect: '/ui-test/index',
component: DEFAULT_LAYOUT,
meta: {
locale: 'menu.uiTest',
icon: 'icon-icon_ui-test-filled',
order: 5,
hideChildrenInMenu: true,
roles: ['UI_INDEX:READ'],
},
children: [
{
path: 'index',
name: 'uiTestIndex',
component: () => import('@/views/ui-test/index.vue'),
meta: {
roles: ['UI_INDEX:READ'],
},
},
],
};
// const UiTest: AppRouteRecordRaw = {
// path: '/ui-test',
// name: UITestRouteEnum.UI_TEST,
// redirect: '/ui-test/index',
// component: DEFAULT_LAYOUT,
// meta: {
// locale: 'menu.uiTest',
// icon: 'icon-icon_ui-test-filled',
// order: 5,
// hideChildrenInMenu: true,
// roles: ['UI_INDEX:READ'],
// },
// children: [
// {
// path: 'index',
// name: 'uiTestIndex',
// component: () => import('@/views/ui-test/index.vue'),
// meta: {
// roles: ['UI_INDEX:READ'],
// },
// },
// ],
// };
export default UiTest;
// export default UiTest;

View File

@ -3,28 +3,28 @@ import { WorkbenchRouteEnum } from '@/enums/routeEnum';
import { DEFAULT_LAYOUT } from '../base';
import type { AppRouteRecordRaw } from '../types';
const Workbench: AppRouteRecordRaw = {
path: '/workbench',
name: WorkbenchRouteEnum.WORKBENCH,
redirect: '/workbench/index',
component: DEFAULT_LAYOUT,
meta: {
locale: 'menu.workbench',
icon: 'icon-icon_pc_filled',
order: 0,
hideChildrenInMenu: true,
roles: ['WORKSTATION_INDEX:READ'],
},
children: [
{
path: 'index',
name: 'workbenchIndex',
component: () => import('@/views/workbench/index.vue'),
meta: {
roles: ['WORKSTATION_INDEX:READ'],
},
},
],
};
// const Workbench: AppRouteRecordRaw = {
// path: '/workbench',
// name: WorkbenchRouteEnum.WORKBENCH,
// redirect: '/workbench/index',
// component: DEFAULT_LAYOUT,
// meta: {
// locale: 'menu.workbench',
// icon: 'icon-icon_pc_filled',
// order: 0,
// hideChildrenInMenu: true,
// roles: ['WORKSTATION_INDEX:READ'],
// },
// children: [
// {
// path: 'index',
// name: 'workbenchIndex',
// component: () => import('@/views/workbench/index.vue'),
// meta: {
// roles: ['WORKSTATION_INDEX:READ'],
// },
// },
// ],
// };
export default Workbench;
// export default Workbench;

View File

@ -58,7 +58,7 @@ const useAppStore = defineStore('app', {
...defaultLoginConfig,
...defaultPlatformConfig,
},
packageType: 'community',
packageType: '',
}),
getters: {
@ -201,6 +201,16 @@ const useAppStore = defineStore('app', {
setCurrentProjectId(id: string) {
this.currentProjectId = id;
},
/**
*
*/
setPackageType(type: string) {
this.packageType = type;
},
// 重置系统包的版本
resetSystemPackageType() {
this.packageType = '';
},
/**
*
*/

View File

@ -37,7 +37,7 @@ export interface AppState {
pageConfig: PageConfig;
innerHeight: number;
currentMenuConfig: string[];
packageType: 'community' | 'enterprise';
packageType: string;
}
export interface UploadFileTaskState {

View File

@ -1,11 +1,11 @@
import { defineStore } from 'pinia';
import { getOrdTemplate, getProTemplate } from '@/api/modules/setting/template';
import { hasAnyPermission } from '@/utils/permission';
import useAppStore from '../app';
const appStore = useAppStore();
const useTemplateStore = defineStore('template', {
persist: true,
state: (): {
@ -33,8 +33,13 @@ const useTemplateStore = defineStore('template', {
const currentOrgId = computed(() => appStore.currentOrgId);
const currentProjectId = computed(() => appStore.currentProjectId);
try {
if (currentOrgId.value && hasAnyPermission(['ORGANIZATION_TEMPLATE:READ'])) {
this.ordStatus = await getOrdTemplate(currentOrgId.value);
}
if (currentProjectId.value && hasAnyPermission(['PROJECT_TEMPLATE:READ'])) {
this.projectStatus = await getProTemplate(currentProjectId.value);
}
} catch (error) {
console.log(error);
}

View File

@ -83,12 +83,6 @@ const useUserStore = defineStore('user', {
appStore.setCurrentOrgId(res.lastOrganizationId || '');
appStore.setCurrentProjectId(res.lastProjectId || '');
this.setInfo(res);
// 登录后初始化系统包版本
appStore.initSystemPackage();
if (appStore.packageType === 'enterprise') {
const licenseStore = useLicenseStore();
licenseStore.getValidateLicense();
}
} catch (err) {
clearToken();
throw err;
@ -104,6 +98,7 @@ const useUserStore = defineStore('user', {
licenseStore.removeLicenseStatus();
appStore.clearServerMenu();
appStore.hideLoading();
appStore.resetSystemPackageType();
},
// 登出
async logout() {

View File

@ -403,7 +403,7 @@
{
title: 'caseManagement.featureCase.tableColumnVersion',
slotName: 'versionName',
dataIndex: 'versionNam',
dataIndex: 'versionName',
width: 300,
showTooltip: true,
showInTable: true,
@ -481,20 +481,20 @@
const tableBatchActions = {
baseAction: [
{
label: 'caseManagement.featureCase.export',
eventTag: 'export',
children: [
{
label: 'caseManagement.featureCase.exportExcel',
eventTag: 'exportExcel',
},
{
label: 'caseManagement.featureCase.exportXMind',
eventTag: 'exportXMind',
},
],
},
// {
// label: 'caseManagement.featureCase.export',
// eventTag: 'export',
// children: [
// {
// label: 'caseManagement.featureCase.exportExcel',
// eventTag: 'exportExcel',
// },
// {
// label: 'caseManagement.featureCase.exportXMind',
// eventTag: 'exportXMind',
// },
// ],
// },
{
label: 'common.edit',
eventTag: 'batchEdit',
@ -1171,9 +1171,12 @@
}
function showCaseDetailEvent(record: TableData, column: TableColumnData, ev: Event) {
showDetailDrawer.value = false;
if (column.title === 'name' || column.title === 'num') {
const rowIndex = propsRes.value.data.map((item: any) => item.id).indexOf(record.id);
showCaseDetail(record.id, rowIndex);
showDetailDrawer.value = true;
activeDetailId.value = record.id;
activeCaseIndex.value = rowIndex;
}
}
onMounted(() => {

View File

@ -278,7 +278,7 @@
{
title: 'caseManagement.featureCase.tableColumnVersion',
slotName: 'versionName',
dataIndex: 'versionNam',
dataIndex: 'versionName',
width: 300,
showTooltip: true,
showInTable: true,

View File

@ -36,20 +36,7 @@
const route = useRoute();
const licenseStore = useLicenseStore();
function getProjectVersion() {
if (licenseStore.hasLicense()) {
return [
{
key: 'projectVersion',
title: t('project.permission.projectVersion'),
level: 2,
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_PERMISSION_VERSION,
},
];
}
return [];
}
const sourceMenuList = [
const sourceMenuList = ref([
{
key: 'project',
title: t('project.permission.project'),
@ -68,7 +55,12 @@
level: 2,
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_PERMISSION_MENU_MANAGEMENT,
},
...getProjectVersion(),
{
key: 'projectVersion',
title: t('project.permission.projectVersion'),
level: 2,
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_PERMISSION_VERSION,
},
{
key: 'memberPermission',
title: t('project.permission.memberPermission'),
@ -87,13 +79,16 @@
level: 2,
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_PERMISSION_USER_GROUP,
},
];
]);
const menuList = computed(() => {
const routerList = router.getRoutes();
return sourceMenuList.filter((item) => {
return sourceMenuList.value.filter((item) => {
if (item.name) {
const routerItem = routerList.find((rou) => rou.name === item.name);
if (!routerItem) return false;
if (routerItem.name === ProjectManagementRouteEnum.PROJECT_MANAGEMENT_PERMISSION_VERSION) {
return licenseStore.hasLicense() && permission.accessRouter(routerItem);
}
return permission.accessRouter(routerItem);
}
return true;
@ -122,6 +117,7 @@
onBeforeMount(() => {
setInitRoute();
licenseStore.getValidateLicense();
});
</script>

View File

@ -1,5 +1,11 @@
<template>
<MsCard has-breadcrumb simple> <FieldSetting mode="project" /></MsCard>
<MsCard has-breadcrumb simple>
<FieldSetting
mode="project"
:delete-permission="['PROJECT_TEMPLATE:READ+DELETE']"
:update-permission="['PROJECT_TEMPLATE:READ+UPDATE']"
:create-permission="['PROJECT_TEMPLATE:READ+ADD']"
/></MsCard>
</template>
<script setup lang="ts">

View File

@ -42,7 +42,7 @@
</div>
</template>
<template #operation="{ record }">
<div class="flex flex-row flex-nowrap items-center">
<div v-if="!record.enablePlatformDefault" class="flex flex-row flex-nowrap items-center">
<MsButton v-permission="['PROJECT_TEMPLATE:READ+UPDATE']" @click="editTemplate(record.id)">{{
t('system.orgTemplate.edit')
}}</MsButton>

View File

@ -1,6 +1,11 @@
<template>
<MsCard has-breadcrumb simple>
<WorkflowTable mode="project" />
<WorkflowTable
mode="project"
:delete-permission="['PROJECT_TEMPLATE:READ+DELETE']"
:update-permission="['PROJECT_TEMPLATE:READ+UPDATE']"
:create-permission="['PROJECT_TEMPLATE:READ+ADD']"
/>
</MsCard>
</template>

View File

@ -1,7 +1,9 @@
<template>
<MsCard simple>
<div class="mb-[16px] flex items-center justify-between">
<a-button type="primary" @click="showAddProject">{{ t('system.organization.createProject') }}</a-button>
<a-button v-permission="['ORGANIZATION_PROJECT:READ+ADD']" type="primary" @click="showAddProject">{{
t('system.organization.createProject')
}}</a-button>
<a-input-search
v-model="keyword"
:placeholder="t('system.user.searchUser')"

View File

@ -53,7 +53,7 @@
type="outline"
class="arco-btn-outline--secondary"
size="mini"
:disabled="!item.config"
:disabled="!item.config || !hasAnyPermission(['SYSTEM_SERVICE_INTEGRATION:READ+UPDATE'])"
@click="getValidateHandler(item)"
>{{ t('organization.service.testLink') }}</a-button
></span
@ -61,6 +61,7 @@
</a-tooltip>
<a-button
v-else
:disabled="!item.config || !hasAnyPermission(['SYSTEM_SERVICE_INTEGRATION:READ+UPDATE'])"
type="outline"
class="arco-btn-outline--secondary"
size="mini"
@ -112,6 +113,7 @@
v-model="item.enable"
size="small"
type="line"
:disabled="!hasAnyPermission(['SYSTEM_SERVICE_INTEGRATION:READ+UPDATE'])"
@change="(v) => changeStatus(v, item.id)"
/>
</span>
@ -138,6 +140,7 @@
import useModal from '@/hooks/useModal';
import { useAppStore } from '@/store';
import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
import type { ServiceItem, ServiceList } from '@/models/setting/serviceIntegration';
import { SettingRouteEnum } from '@/enums/routeEnum';

View File

@ -7,7 +7,13 @@
}}</a-alert>
<div class="mb-4 flex items-center justify-between">
<span v-if="isEnabledTemplate" class="font-medium">{{ t('system.orgTemplate.fieldList') }}</span>
<a-button v-else type="primary" :disabled="isDisabled" @click="fieldHandler">
<a-button
v-else
v-permission="props.createPermission"
type="primary"
:disabled="isDisabled"
@click="fieldHandler"
>
{{ t('system.orgTemplate.addField') }}
</a-button>
<a-input-search
@ -52,12 +58,15 @@
:ok-text="t('system.orgTemplate.confirm')"
@confirm="handleOk(record)"
>
<MsButton class="!mr-0">{{ t('system.orgTemplate.edit') }}</MsButton></MsPopConfirm
<MsButton v-permission="props.updatePermission" class="!mr-0">{{
t('system.orgTemplate.edit')
}}</MsButton></MsPopConfirm
>
<a-divider v-if="!record.internal" class="h-[12px]" direction="vertical" />
<MsTableMoreAction
v-if="!record.internal"
v-permission="props.deletePermission"
:list="moreActions"
@select="(item) => handleMoreActionSelect(item, record)"
/>
@ -157,6 +166,9 @@
const props = defineProps<{
mode: 'organization' | 'project';
deletePermission?: string[];
createPermission?: string[];
updatePermission?: string[];
}>();
const currentOrd = computed(() => appStore.currentOrgId);

View File

@ -1,5 +1,11 @@
<template>
<MsCard has-breadcrumb simple> <FieldSetting mode="organization" /></MsCard>
<MsCard has-breadcrumb simple>
<FieldSetting
mode="organization"
:delete-permission="['ORGANIZATION_TEMPLATE:READ+DELETE']"
:update-permission="['ORGANIZATION_TEMPLATE:READ+UPDATE']"
:create-permission="['ORGANIZATION_TEMPLATE:READ+ADD']"
/></MsCard>
</template>
<script setup lang="ts">

View File

@ -15,7 +15,7 @@
<span @click="fieldSetting">{{ t('system.orgTemplate.fieldSetting') }}</span>
<a-divider direction="vertical" />
</span>
<span v-permission="['ORGANIZATION_TEMPLATE:READ']" class="operation hover:text-[rgb(var(--primary-5))]">
<span class="operation hover:text-[rgb(var(--primary-5))]">
<span @click="templateManagement">{{ t('system.orgTemplate.TemplateManagement') }}</span>
<a-divider v-if="isEnableProject || props.cardItem.key === 'BUG'" direction="vertical" />
</span>

View File

@ -34,7 +34,7 @@
{{ record.enableThirdPart ? t('system.orgTemplate.yes') : t('system.orgTemplate.no') }}
</template>
<template #operation="{ record }">
<div class="flex flex-row flex-nowrap items-center">
<div v-if="!record.enablePlatformDefault" class="flex flex-row flex-nowrap items-center">
<MsButton v-permission="['ORGANIZATION_TEMPLATE:READ+UPDATE']" @click="editTemplate(record.id)">{{
t('system.orgTemplate.edit')
}}</MsButton>

View File

@ -1,6 +1,11 @@
<template>
<MsCard has-breadcrumb simple>
<WorkflowTable mode="organization" />
<WorkflowTable
mode="organization"
:delete-permission="['ORGANIZATION_TEMPLATE:READ+DELETE']"
:update-permission="['ORGANIZATION_TEMPLATE:READ+UPDATE']"
:create-permission="['ORGANIZATION_TEMPLATE:READ+ADD']"
/>
</MsCard>
</template>

View File

@ -74,6 +74,7 @@
import { useI18n } from '@/hooks/useI18n';
import useModal from '@/hooks/useModal';
import useTemplateStore from '@/store/modules/setting/template';
import { hasAnyPermission } from '@/utils/permission';
import type { UpdateWorkFlowSetting, WorkFlowType } from '@/models/setting/template';
@ -89,6 +90,9 @@
columnItem: TableColumnData;
cellCoordinates: { rowId: string; columnId: string };
totalData: WorkFlowType[];
deletePermission?: string[];
createPermission?: string[];
updatePermission?: string[];
}>();
const emit = defineEmits<{
@ -149,6 +153,9 @@
// class
function setSelectClass() {
if (!hasAnyPermission(props.updatePermission || [])) {
return;
}
if (isUnCreateWorkFlow.value && isSelected.value) {
styleClass.value = {
wrapper: { _select_unCreate_Selected: true },
@ -220,6 +227,9 @@
//
function createFlowStep() {
if (!hasAnyPermission(props.updatePermission || [])) {
return;
}
if (isEnableProjectState.value) {
return;
}
@ -231,6 +241,9 @@
const updateOrdWorkStateFlow = getWorkFlowRequestApi(props.mode).updateFlow;
//
async function changeWorkFlow(type: string) {
if (!hasAnyPermission(props.updatePermission || [])) {
return;
}
try {
loading.value = true;
const params: UpdateWorkFlowSetting = {
@ -254,6 +267,9 @@
//
function cancelFlowStep() {
if (!hasAnyPermission(props.updatePermission || [])) {
return;
}
if (isEnableProjectState.value) {
return;
}

View File

@ -9,9 +9,14 @@
</a-alert>
<div class="mb-4">
<div class="mb-4 flex items-center"
><a-button v-if="!isEnableProjectState" class="mr-2" type="outline" @click="addStatus">{{
t('system.orgTemplate.addState')
}}</a-button>
><a-button
v-if="!isEnableProjectState"
v-permission="props.createPermission"
class="mr-2"
type="outline"
@click="addStatus"
>{{ t('system.orgTemplate.addState') }}</a-button
>
<span v-else class="mr-2 font-medium text-[var(--color-text-1)]">工作流</span>
<a-popover title="" position="right">
<MsButton class="!mr-1">{{ t('system.orgTemplate.example') }}</MsButton>
@ -72,6 +77,7 @@
<div
v-if="!isEnableProjectState"
v-permission="props.updatePermission"
class="action mr-2 flex h-8 w-8 items-center justify-center rounded opacity-0"
>
<MsTableMoreAction
@ -88,6 +94,9 @@
:state-item="record"
:cell-coordinates="cellCoordinates"
:total-data="dataList"
:delete-permission="props.deletePermission"
:update-permission="props.updatePermission"
:create-permission="props.createPermission"
@click="selectCard(record, column.dataIndex)"
@ok="getWorkFetchList()"
/>
@ -102,16 +111,28 @@
>
<template #cell="{ record }">
<div class="ml-4 flex items-center">
<MsButton v-if="!isEnableProjectState" class="!mr-0 ml-4" @click="editWorkStatus(record)">{{
t('common.edit')
}}</MsButton>
<a-divider v-if="!isEnableProjectState" class="h-[12px]" direction="vertical" />
<MsButton
v-if="!isEnableProjectState"
v-permission="props.updatePermission"
class="!mr-0 ml-4"
@click="editWorkStatus(record)"
>{{ t('common.edit') }}</MsButton
>
<a-divider
v-if="!isEnableProjectState"
v-permission="props.updatePermission"
class="h-[12px]"
direction="vertical"
/>
<a-checkbox
v-if="!isEnableProjectState"
v-model="record.currentState"
:disabled="!hasAnyPermission(props.updatePermission || [])"
@change="(value) => changeState(value, record)"
>
<MsButton class="!mr-0">{{ t('system.orgTemplate.endState') }}</MsButton></a-checkbox
<MsButton v-permission="props.updatePermission" class="!mr-0">{{
t('system.orgTemplate.endState')
}}</MsButton></a-checkbox
>
<a-divider v-if="!isEnableProjectState" class="h-[12px]" direction="vertical" />
<MsButton class="!mr-0" @click="detailWorkStatus(record)">{{ t('system.orgTemplate.details') }}</MsButton>
@ -183,6 +204,7 @@
import { useAppStore } from '@/store';
import useTemplateStore from '@/store/modules/setting/template';
import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
import type { SetStateType, WorkFlowType } from '@/models/setting/template';
@ -195,6 +217,9 @@
const props = defineProps<{
mode: 'organization' | 'project'; // ||
deletePermission?: string[];
createPermission?: string[];
updatePermission?: string[];
}>();
const currentOrgId = computed(() => appStore.currentOrgId);
@ -356,6 +381,9 @@
const dragChangeRequest = getWorkFlowRequestApi(props.mode).dragChange;
//
async function handleChange(_data: TableData[]) {
if (!hasAnyPermission(props.updatePermission || [])) {
return;
}
const originIds = dataList.value.map((item: any) => item.id);
dataList.value = _data as WorkFlowType[];
const dataIds = _data.map((item: any) => item.id);

View File

@ -91,7 +91,7 @@
></a-input>
<MsFormItemSub :text="t('system.config.baseInfo.pageUrlSub', { url: defaultUrl })" @fill="fillDefaultUrl" />
</a-form-item>
<a-form-item :label="t('system.config.prometheus')" field="prometheusHost" asterisk-position="end">
<a-form-item v-xpack :label="t('system.config.prometheus')" field="prometheusHost" asterisk-position="end">
<a-input
v-model:model-value="baseInfoForm.prometheusHost"
:max-length="250"

View File

@ -33,7 +33,8 @@
const tabList = ref([
{ key: 'baseConfig', title: t('system.config.baseConfig'), permission: ['SYSTEM_PARAMETER_SETTING_BASE:READ'] },
{ key: 'pageConfig', title: t('system.config.pageConfig'), permission: ['SYSTEM_PARAMETER_SETTING_DISPLAY:READ'] },
{ key: 'authConfig', title: t('system.config.authConfig'), permission: ['SYSTEM_PARAMETER_SETTING_AUTH:READ'] },
// TODO
// { key: 'authConfig', title: t('system.config.authConfig'), permission: ['SYSTEM_PARAMETER_SETTING_AUTH:READ'] },
{ key: 'memoryCleanup', title: t('system.config.memoryCleanup'), permission: [] },
]);
@ -53,14 +54,19 @@
}
);
const licenseStore = useLicenseStore();
onMounted(() => {
if (route.query.tab === 'authConfig' && route.query.id) {
authConfigRef.value?.openAuthDetail(route.query.id as string);
}
async function getXpackTab() {
await licenseStore.getValidateLicense();
if (!licenseStore.hasLicense()) {
const excludes = ['baseConfig', 'memoryCleanup'];
tabList.value = tabList.value.filter((item: any) => excludes.includes(item.key));
}
}
onMounted(() => {
if (route.query.tab === 'authConfig' && route.query.id) {
authConfigRef.value?.openAuthDetail(route.query.id as string);
}
getXpackTab();
});
</script>

View File

@ -61,7 +61,7 @@ export default {
'system.plugin.enablePluginSuccess': '启用成功',
'system.plugin.disablePluginContent': '项目无法与该平台集成且该平台默认模版不可用,谨慎操作!',
'system.plugin.alertDescribe':
'MeterSphereV2.10LTS 版本支持 DevOps、API 导入、请求、项目管理、协议类型的插件,具体支持插件请',
'MeterSphere V2.10 LTS 版本支持 DevOps、API 导入、请求、项目管理、协议类型的插件,具体支持插件请',
'system.plugin.viewTable': '查看表格',
'system.plugin.downAddress': '更多开源插件,请在此下载',
'system.plugin.goDownload': '去下载',

View File

@ -38,7 +38,11 @@
<MsButton v-permission="['SYSTEM_USER:READ+UPDATE']" @click="showUserModal('edit', record)">{{
t('system.user.editUser')
}}</MsButton>
<MsTableMoreAction :list="tableActions" @select="handleSelect($event, record)"></MsTableMoreAction>
<MsTableMoreAction
v-if="hasAnyPermission(['SYSTEM_USER:READ+UPDATE', 'SYSTEM_USER:READ+UPDATE', 'SYSTEM_USER:READ+DELETE'])"
:list="tableActions"
@select="handleSelect($event, record)"
></MsTableMoreAction>
</template>
</template>
</ms-base-table>
@ -219,6 +223,7 @@
import useModal from '@/hooks/useModal';
import { useTableStore } from '@/store';
import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
import { validateEmail, validatePhone } from '@/utils/validate';
import type { SimpleUserInfo, SystemRole, UserListItem } from '@/models/setting/user';