feat: 新增权限管理&表格样式调整
This commit is contained in:
parent
7ab276d3b9
commit
802efe9900
|
@ -59,7 +59,9 @@
|
||||||
:style="{ width: props.width }"
|
:style="{ width: props.width }"
|
||||||
>
|
>
|
||||||
<ms-button :disabled="!canSave" @click="handleReset">{{ t('system.userGroup.reset') }}</ms-button>
|
<ms-button :disabled="!canSave" @click="handleReset">{{ t('system.userGroup.reset') }}</ms-button>
|
||||||
<a-button :disabled="!canSave" type="primary" @click="handleSave">{{ t('system.userGroup.save') }}</a-button>
|
<a-button v-permission="props.savePermission || []" :disabled="!canSave" type="primary" @click="handleSave">{{
|
||||||
|
t('system.userGroup.save')
|
||||||
|
}}</a-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -101,6 +103,7 @@
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
current: CurrentUserGroupItem;
|
current: CurrentUserGroupItem;
|
||||||
|
savePermission?: string[];
|
||||||
width?: string;
|
width?: string;
|
||||||
showBottom?: boolean;
|
showBottom?: boolean;
|
||||||
scroll?: {
|
scroll?: {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
@search="searchData"
|
@search="searchData"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="showSystem" class="mt-2">
|
<div v-if="showSystem" v-permission="['SYSTEM_USER_ROLE:READ']" class="mt-2">
|
||||||
<CreateUserGroupPopup
|
<CreateUserGroupPopup
|
||||||
:list="systemUserGroupList"
|
:list="systemUserGroupList"
|
||||||
:visible="systemUserGroupVisible"
|
:visible="systemUserGroupVisible"
|
||||||
|
@ -36,7 +36,11 @@
|
||||||
{{ t('system.userGroup.systemUserGroup') }}
|
{{ t('system.userGroup.systemUserGroup') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MsMoreAction :list="createSystemUGActionItem" @select="handleCreateUG(AuthScopeEnum.SYSTEM)">
|
<MsMoreAction
|
||||||
|
v-permission="['SYSTEM_USER_ROLE:READ+ADD']"
|
||||||
|
:list="createSystemUGActionItem"
|
||||||
|
@select="handleCreateUG(AuthScopeEnum.SYSTEM)"
|
||||||
|
>
|
||||||
<icon-plus-circle-fill class="cursor-pointer text-[rgb(var(--primary-7))]" size="20" />
|
<icon-plus-circle-fill class="cursor-pointer text-[rgb(var(--primary-7))]" size="20" />
|
||||||
</MsMoreAction>
|
</MsMoreAction>
|
||||||
</div>
|
</div>
|
||||||
|
@ -67,6 +71,7 @@
|
||||||
<div v-if="element.id === currentId && !element.internal" class="flex flex-row items-center gap-[8px]">
|
<div v-if="element.id === currentId && !element.internal" class="flex flex-row items-center gap-[8px]">
|
||||||
<MsMoreAction
|
<MsMoreAction
|
||||||
v-if="element.type === systemType"
|
v-if="element.type === systemType"
|
||||||
|
v-permission="['SYSTEM_USER_ROLE:READ+UPDATE']"
|
||||||
:list="addMemberActionItem"
|
:list="addMemberActionItem"
|
||||||
@select="handleAddMember"
|
@select="handleAddMember"
|
||||||
>
|
>
|
||||||
|
@ -75,7 +80,7 @@
|
||||||
</div>
|
</div>
|
||||||
</MsMoreAction>
|
</MsMoreAction>
|
||||||
<MsMoreAction
|
<MsMoreAction
|
||||||
:list="moreAction"
|
:list="systemMoreAction"
|
||||||
@select="(value) => handleMoreAction(value, element.id, AuthScopeEnum.SYSTEM)"
|
@select="(value) => handleMoreAction(value, element.id, AuthScopeEnum.SYSTEM)"
|
||||||
>
|
>
|
||||||
<div class="icon-button">
|
<div class="icon-button">
|
||||||
|
@ -90,7 +95,7 @@
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="showOrg" class="mt-2">
|
<div v-if="showOrg" v-permission="['ORGANIZATION_USER_ROLE:READ']" class="mt-2">
|
||||||
<CreateUserGroupPopup
|
<CreateUserGroupPopup
|
||||||
:list="orgUserGroupList"
|
:list="orgUserGroupList"
|
||||||
:visible="orgUserGroupVisible"
|
:visible="orgUserGroupVisible"
|
||||||
|
@ -118,7 +123,11 @@
|
||||||
{{ t('system.userGroup.orgUserGroup') }}
|
{{ t('system.userGroup.orgUserGroup') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MsMoreAction :list="createOrgUGActionItem" @select="orgUserGroupVisible = true">
|
<MsMoreAction
|
||||||
|
v-permission="['ORGANIZATION_USER_ROLE:READ+ADD']"
|
||||||
|
:list="createOrgUGActionItem"
|
||||||
|
@select="orgUserGroupVisible = true"
|
||||||
|
>
|
||||||
<icon-plus-circle-fill class="cursor-pointer text-[rgb(var(--primary-7))]" size="20" />
|
<icon-plus-circle-fill class="cursor-pointer text-[rgb(var(--primary-7))]" size="20" />
|
||||||
</MsMoreAction>
|
</MsMoreAction>
|
||||||
</div>
|
</div>
|
||||||
|
@ -149,6 +158,7 @@
|
||||||
<div v-if="element.id === currentId && !element.internal" class="flex flex-row items-center gap-[8px]">
|
<div v-if="element.id === currentId && !element.internal" class="flex flex-row items-center gap-[8px]">
|
||||||
<MsMoreAction
|
<MsMoreAction
|
||||||
v-if="element.type === systemType"
|
v-if="element.type === systemType"
|
||||||
|
v-permission="['ORGANIZATION_USER_ROLE:READ+UPDATE']"
|
||||||
:list="addMemberActionItem"
|
:list="addMemberActionItem"
|
||||||
@select="handleAddMember"
|
@select="handleAddMember"
|
||||||
>
|
>
|
||||||
|
@ -157,7 +167,7 @@
|
||||||
</div>
|
</div>
|
||||||
</MsMoreAction>
|
</MsMoreAction>
|
||||||
<MsMoreAction
|
<MsMoreAction
|
||||||
:list="moreAction"
|
:list="orgMoreAction"
|
||||||
@select="(value) => handleMoreAction(value, element.id, AuthScopeEnum.ORGANIZATION)"
|
@select="(value) => handleMoreAction(value, element.id, AuthScopeEnum.ORGANIZATION)"
|
||||||
>
|
>
|
||||||
<div class="icon-button">
|
<div class="icon-button">
|
||||||
|
@ -172,7 +182,7 @@
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="showProject" class="mt-2">
|
<div v-if="showProject" v-permission="['PROJECT_GROUP:READ']" class="mt-2">
|
||||||
<CreateUserGroupPopup
|
<CreateUserGroupPopup
|
||||||
:list="projectUserGroupList"
|
:list="projectUserGroupList"
|
||||||
:visible="projectUserGroupVisible"
|
:visible="projectUserGroupVisible"
|
||||||
|
@ -200,7 +210,11 @@
|
||||||
{{ t('system.userGroup.projectUserGroup') }}
|
{{ t('system.userGroup.projectUserGroup') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MsMoreAction :list="createProjectUGActionItem" @select="projectUserGroupVisible = true">
|
<MsMoreAction
|
||||||
|
v-permission="['PROJECT_GROUP:READ+ADD']"
|
||||||
|
:list="createProjectUGActionItem"
|
||||||
|
@select="projectUserGroupVisible = true"
|
||||||
|
>
|
||||||
<icon-plus-circle-fill class="cursor-pointer text-[rgb(var(--primary-7))]" size="20" />
|
<icon-plus-circle-fill class="cursor-pointer text-[rgb(var(--primary-7))]" size="20" />
|
||||||
</MsMoreAction>
|
</MsMoreAction>
|
||||||
</div>
|
</div>
|
||||||
|
@ -231,6 +245,7 @@
|
||||||
<div v-if="element.id === currentId && !element.internal" class="flex flex-row items-center gap-[8px]">
|
<div v-if="element.id === currentId && !element.internal" class="flex flex-row items-center gap-[8px]">
|
||||||
<MsMoreAction
|
<MsMoreAction
|
||||||
v-if="element.type === systemType"
|
v-if="element.type === systemType"
|
||||||
|
v-permission="['PROJECT_GROUP:READ+UPDATE']"
|
||||||
:list="addMemberActionItem"
|
:list="addMemberActionItem"
|
||||||
@select="handleAddMember"
|
@select="handleAddMember"
|
||||||
>
|
>
|
||||||
|
@ -239,7 +254,7 @@
|
||||||
</div>
|
</div>
|
||||||
</MsMoreAction>
|
</MsMoreAction>
|
||||||
<MsMoreAction
|
<MsMoreAction
|
||||||
:list="moreAction"
|
:list="projectMoreAction"
|
||||||
@select="(value) => handleMoreAction(value, element.id, AuthScopeEnum.PROJECT)"
|
@select="(value) => handleMoreAction(value, element.id, AuthScopeEnum.PROJECT)"
|
||||||
>
|
>
|
||||||
<div class="icon-button">
|
<div class="icon-button">
|
||||||
|
@ -278,6 +293,7 @@
|
||||||
import useModal from '@/hooks/useModal';
|
import useModal from '@/hooks/useModal';
|
||||||
import { useAppStore } from '@/store';
|
import { useAppStore } from '@/store';
|
||||||
import { characterLimit } from '@/utils';
|
import { characterLimit } from '@/utils';
|
||||||
|
import { hasAnyPermission } from '@/utils/permission';
|
||||||
|
|
||||||
import { CurrentUserGroupItem, PopVisible, PopVisibleItem, UserGroupItem } from '@/models/setting/usergroup';
|
import { CurrentUserGroupItem, PopVisible, PopVisibleItem, UserGroupItem } from '@/models/setting/usergroup';
|
||||||
import { AuthScopeEnum } from '@/enums/commonEnum';
|
import { AuthScopeEnum } from '@/enums/commonEnum';
|
||||||
|
@ -362,6 +378,57 @@
|
||||||
eventTag: 'delete',
|
eventTag: 'delete',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
const systemMoreAction: ActionsItem[] = [
|
||||||
|
{
|
||||||
|
label: 'system.userGroup.rename',
|
||||||
|
danger: false,
|
||||||
|
eventTag: 'rename',
|
||||||
|
permission: ['SYSTEM_USER_ROLE:READ+UPDATE'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
isDivider: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'system.userGroup.delete',
|
||||||
|
danger: true,
|
||||||
|
eventTag: 'delete',
|
||||||
|
permission: ['SYSTEM_USER_ROLE:READ+DELETE'],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const orgMoreAction: ActionsItem[] = [
|
||||||
|
{
|
||||||
|
label: 'system.userGroup.rename',
|
||||||
|
danger: false,
|
||||||
|
eventTag: 'rename',
|
||||||
|
permission: ['ORGANIZATION_USER_ROLE:READ+UPDATE'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
isDivider: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'system.userGroup.delete',
|
||||||
|
danger: true,
|
||||||
|
eventTag: 'delete',
|
||||||
|
permission: ['ORGANIZATION_USER_ROLE:READ+UPDATE'],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const projectMoreAction: ActionsItem[] = [
|
||||||
|
{
|
||||||
|
label: 'system.userGroup.rename',
|
||||||
|
danger: false,
|
||||||
|
eventTag: 'rename',
|
||||||
|
permission: ['PROJECT_GROUP:READ+UPDATE'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
isDivider: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'system.userGroup.delete',
|
||||||
|
danger: true,
|
||||||
|
eventTag: 'delete',
|
||||||
|
permission: ['PROJECT_GROUP:READ+UPDATE'],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
// 点击用户组列表
|
// 点击用户组列表
|
||||||
const handleListItemClick = (element: UserGroupItem) => {
|
const handleListItemClick = (element: UserGroupItem) => {
|
||||||
|
@ -375,11 +442,11 @@
|
||||||
const initData = async (id?: string, isSelect = true) => {
|
const initData = async (id?: string, isSelect = true) => {
|
||||||
try {
|
try {
|
||||||
let res: UserGroupItem[] = [];
|
let res: UserGroupItem[] = [];
|
||||||
if (systemType === AuthScopeEnum.SYSTEM) {
|
if (systemType === AuthScopeEnum.SYSTEM && hasAnyPermission(['SYSTEM_USER_ROLE:READ'])) {
|
||||||
res = await getUserGroupList();
|
res = await getUserGroupList();
|
||||||
} else if (systemType === AuthScopeEnum.ORGANIZATION) {
|
} else if (systemType === AuthScopeEnum.ORGANIZATION && hasAnyPermission(['ORGANIZATION_USER_ROLE:READ'])) {
|
||||||
res = await getOrgUserGroupList(appStore.currentOrgId);
|
res = await getOrgUserGroupList(appStore.currentOrgId);
|
||||||
} else if (systemType === AuthScopeEnum.PROJECT) {
|
} else if (systemType === AuthScopeEnum.PROJECT && hasAnyPermission(['PROJECT_GROUP:READ'])) {
|
||||||
res = await getProjectUserGroupList(appStore.currentProjectId);
|
res = await getProjectUserGroupList(appStore.currentProjectId);
|
||||||
}
|
}
|
||||||
if (res.length > 0) {
|
if (res.length > 0) {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<MsBaseTable class="mt-[16px]" v-bind="propsRes" v-on="propsEvent">
|
<MsBaseTable class="mt-[16px]" v-bind="propsRes" v-on="propsEvent">
|
||||||
<template #quickCreate>
|
<template v-if="hasAnyPermission(props.updatePermission || [])" #quickCreate>
|
||||||
<!-- <a-button type="primary" @click="handleAddUser">{{ t('system.userGroup.quickAddUser') }}</a-button> -->
|
|
||||||
<MsConfirmUserSelector :ok-loading="okLoading" v-bind="userSelectorProps" @confirm="handleAddMember" />
|
<MsConfirmUserSelector :ok-loading="okLoading" v-bind="userSelectorProps" @confirm="handleAddMember" />
|
||||||
</template>
|
</template>
|
||||||
<template #action="{ record }">
|
<template #action="{ record }">
|
||||||
|
@ -33,6 +32,7 @@
|
||||||
} from '@/api/modules/setting/usergroup';
|
} from '@/api/modules/setting/usergroup';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import { useAppStore } from '@/store';
|
import { useAppStore } from '@/store';
|
||||||
|
import { hasAnyPermission } from '@/utils/permission';
|
||||||
|
|
||||||
import { CurrentUserGroupItem, UserTableItem } from '@/models/setting/usergroup';
|
import { CurrentUserGroupItem, UserTableItem } from '@/models/setting/usergroup';
|
||||||
import { AuthScopeEnum } from '@/enums/commonEnum';
|
import { AuthScopeEnum } from '@/enums/commonEnum';
|
||||||
|
@ -48,6 +48,9 @@
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
keyword: string;
|
keyword: string;
|
||||||
current: CurrentUserGroupItem;
|
current: CurrentUserGroupItem;
|
||||||
|
deletePermission?: string[];
|
||||||
|
readPermission?: string[];
|
||||||
|
updatePermission?: string[];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const userSelectorProps = computed(() => {
|
const userSelectorProps = computed(() => {
|
||||||
|
@ -112,11 +115,21 @@
|
||||||
heightUsed: 288,
|
heightUsed: 288,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const handlePermission = (permission: string[], cb: () => void) => {
|
||||||
|
if (!hasAnyPermission(permission)) {
|
||||||
|
Message.error(t('common.noPermission'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cb();
|
||||||
|
};
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
|
handlePermission(props.readPermission || [], async () => {
|
||||||
setKeyword(props.keyword);
|
setKeyword(props.keyword);
|
||||||
await loadList();
|
await loadList();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
const handleRemove = async (record: UserTableItem) => {
|
const handleRemove = async (record: UserTableItem) => {
|
||||||
|
handlePermission(props.deletePermission || [], async () => {
|
||||||
try {
|
try {
|
||||||
if (systemType === AuthScopeEnum.SYSTEM) {
|
if (systemType === AuthScopeEnum.SYSTEM) {
|
||||||
await deleteUserFromUserGroup(record.id);
|
await deleteUserFromUserGroup(record.id);
|
||||||
|
@ -132,6 +145,7 @@
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -59,10 +59,22 @@
|
||||||
<a-button :disabled="props.okLoading" @click="handleCancel">
|
<a-button :disabled="props.okLoading" @click="handleCancel">
|
||||||
{{ t(props.cancelText || 'ms.drawer.cancel') }}
|
{{ t(props.cancelText || 'ms.drawer.cancel') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button v-if="showContinue" type="secondary" :loading="props.okLoading" @click="handleContinue">
|
<a-button
|
||||||
|
v-if="showContinue"
|
||||||
|
v-permission="props.okPermission || []"
|
||||||
|
type="secondary"
|
||||||
|
:loading="props.okLoading"
|
||||||
|
@click="handleContinue"
|
||||||
|
>
|
||||||
{{ t(props.saveContinueText || 'ms.drawer.saveContinue') }}
|
{{ t(props.saveContinueText || 'ms.drawer.saveContinue') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button type="primary" :disabled="okDisabled" :loading="props.okLoading" @click="handleOk">
|
<a-button
|
||||||
|
v-permission="props.okPermission || []"
|
||||||
|
type="primary"
|
||||||
|
:disabled="okDisabled"
|
||||||
|
:loading="props.okLoading"
|
||||||
|
@click="handleOk"
|
||||||
|
>
|
||||||
{{ t(props.okText || 'ms.drawer.ok') }}
|
{{ t(props.okText || 'ms.drawer.ok') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -93,6 +105,7 @@
|
||||||
showSkeleton?: boolean; // 是否显示骨架屏
|
showSkeleton?: boolean; // 是否显示骨架屏
|
||||||
okLoading?: boolean;
|
okLoading?: boolean;
|
||||||
okDisabled?: boolean;
|
okDisabled?: boolean;
|
||||||
|
okPermission?: string[]; // 确认按钮权限
|
||||||
okText?: string;
|
okText?: string;
|
||||||
cancelText?: string;
|
cancelText?: string;
|
||||||
saveContinueText?: string;
|
saveContinueText?: string;
|
||||||
|
@ -110,6 +123,7 @@
|
||||||
showContinue: false,
|
showContinue: false,
|
||||||
popupContainer: 'body',
|
popupContainer: 'body',
|
||||||
disabledWidthDrag: false,
|
disabledWidthDrag: false,
|
||||||
|
okPermission: () => [], // 确认按钮权限
|
||||||
});
|
});
|
||||||
const emit = defineEmits(['update:visible', 'confirm', 'cancel', 'continue']);
|
const emit = defineEmits(['update:visible', 'confirm', 'cancel', 'continue']);
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
<a-doption
|
<a-doption
|
||||||
v-else
|
v-else
|
||||||
:key="item.label"
|
:key="item.label"
|
||||||
|
v-permission="item.permission || []"
|
||||||
:class="item.danger ? 'error-6' : ''"
|
:class="item.danger ? 'error-6' : ''"
|
||||||
:disabled="item.disabled"
|
:disabled="item.disabled"
|
||||||
:value="item.eventTag"
|
:value="item.eventTag"
|
||||||
|
|
|
@ -5,6 +5,7 @@ export interface ActionsItem {
|
||||||
danger?: boolean; // 是否危险操作,true 的话会显示红色按钮
|
danger?: boolean; // 是否危险操作,true 的话会显示红色按钮
|
||||||
disabled?: boolean; // 是否禁用
|
disabled?: boolean; // 是否禁用
|
||||||
icon?: string; // 按钮图标
|
icon?: string; // 按钮图标
|
||||||
|
permission?: string[]; // 权限标识
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SelectedValue = string | number | Record<string, any> | undefined;
|
export type SelectedValue = string | number | Record<string, any> | undefined;
|
||||||
|
|
|
@ -75,7 +75,6 @@
|
||||||
@show-setting="handleShowSetting"
|
@show-setting="handleShowSetting"
|
||||||
@init-data="handleInitColumn"
|
@init-data="handleInitColumn"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<slot v-else-if="item.filterConfig" :name="item.filterConfig.filterSlotName">
|
<slot v-else-if="item.filterConfig" :name="item.filterConfig.filterSlotName">
|
||||||
<DefaultFilter
|
<DefaultFilter
|
||||||
class="ml-[4px]"
|
class="ml-[4px]"
|
||||||
|
@ -541,9 +540,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
:deep(.arco-table-th-title) {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.setting-icon {
|
.setting-icon {
|
||||||
margin-left: 16px;
|
margin-left: 16px;
|
||||||
color: var(--color-text-4);
|
color: var(--color-text-4);
|
||||||
|
|
|
@ -103,6 +103,7 @@ export interface MsTableProps<T> {
|
||||||
emptyDataShowLine?: boolean; // 空数据是否显示 "-"
|
emptyDataShowLine?: boolean; // 空数据是否显示 "-"
|
||||||
showJumpMethod?: boolean; // 是否展示跳转方法
|
showJumpMethod?: boolean; // 是否展示跳转方法
|
||||||
isSimpleSetting?: boolean; // 是否是简单的设置
|
isSimpleSetting?: boolean; // 是否是简单的设置
|
||||||
|
filterIconAlignLeft?: boolean; // 筛选图标是否靠左
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,7 @@ export default function useTableProps<T>(
|
||||||
showJumpMethod: false, // 是否显示跳转方法
|
showJumpMethod: false, // 是否显示跳转方法
|
||||||
showFooterActionWrap: false, // 是否显示底部操作区域
|
showFooterActionWrap: false, // 是否显示底部操作区域
|
||||||
isSimpleSetting: false, // 是否是简易column设置
|
isSimpleSetting: false, // 是否是简易column设置
|
||||||
|
filterIconAlignLeft: true, // 筛选图标是否靠左
|
||||||
...props,
|
...props,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
:min="0"
|
:min="0"
|
||||||
hide-button
|
hide-button
|
||||||
size="small"
|
size="small"
|
||||||
|
:disabled="props.disabled"
|
||||||
@press-enter="handleEnter(false)"
|
@press-enter="handleEnter(false)"
|
||||||
@blur="handleEnter(true)"
|
@blur="handleEnter(true)"
|
||||||
>
|
>
|
||||||
|
@ -14,6 +15,7 @@
|
||||||
v-model:model-value="current.type"
|
v-model:model-value="current.type"
|
||||||
size="small"
|
size="small"
|
||||||
class="max-w-[64px]"
|
class="max-w-[64px]"
|
||||||
|
:disabled="props.disabled"
|
||||||
:options="option"
|
:options="option"
|
||||||
:trigger-props="{ autoFitPopupMinWidth: true }"
|
:trigger-props="{ autoFitPopupMinWidth: true }"
|
||||||
@change="handleEnter(false)"
|
@change="handleEnter(false)"
|
||||||
|
@ -28,7 +30,7 @@
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const props = defineProps<{ modelValue?: string; defaultValue?: string }>();
|
const props = defineProps<{ modelValue?: string; defaultValue?: string; disabled?: boolean }>();
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:modelValue', value: string): void;
|
(e: 'update:modelValue', value: string): void;
|
||||||
(e: 'change', value: string): void;
|
(e: 'change', value: string): void;
|
||||||
|
|
|
@ -101,4 +101,5 @@ export default {
|
||||||
'common.noProject': 'No project, please contact the administrator',
|
'common.noProject': 'No project, please contact the administrator',
|
||||||
'common.noResource': 'No resource, please contact the administrator',
|
'common.noResource': 'No resource, please contact the administrator',
|
||||||
'common.noSelectProject': 'No optional items available',
|
'common.noSelectProject': 'No optional items available',
|
||||||
|
'common.noPermission': 'No permission',
|
||||||
};
|
};
|
||||||
|
|
|
@ -104,4 +104,5 @@ export default {
|
||||||
'common.noProject': '暂无项目权限,请联系管理员',
|
'common.noProject': '暂无项目权限,请联系管理员',
|
||||||
'common.noResource': '暂无资源权限,请联系管理员',
|
'common.noResource': '暂无资源权限,请联系管理员',
|
||||||
'common.noSelectProject': '无可选项目',
|
'common.noSelectProject': '无可选项目',
|
||||||
|
'common.noPermission': '无权限',
|
||||||
};
|
};
|
||||||
|
|
|
@ -44,7 +44,15 @@ const ProjectManagement: AppRouteRecordRaw = {
|
||||||
component: () => import('@/views/project-management/projectAndPermission/menuManagement/menuManagement.vue'),
|
component: () => import('@/views/project-management/projectAndPermission/menuManagement/menuManagement.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
locale: 'project.permission.menuManagement',
|
locale: 'project.permission.menuManagement',
|
||||||
roles: ['PROJECT_APPLICATION_WORKSTATION:READ'],
|
roles: [
|
||||||
|
'PROJECT_APPLICATION_WORKSTATION:READ',
|
||||||
|
'PROJECT_APPLICATION_TEST_PLAN:READ',
|
||||||
|
'PROJECT_APPLICATION_BUG:READ',
|
||||||
|
'PROJECT_APPLICATION_CASE:READ',
|
||||||
|
'PROJECT_APPLICATION_API:READ',
|
||||||
|
'PROJECT_APPLICATION_UI:READ',
|
||||||
|
'PROJECT_APPLICATION_PERFORMANCE_TEST:READ',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// 项目版本
|
// 项目版本
|
||||||
|
@ -250,7 +258,7 @@ const ProjectManagement: AppRouteRecordRaw = {
|
||||||
import('@/views/project-management/projectAndPermission/menuManagement/components/falseAlermRule.vue'),
|
import('@/views/project-management/projectAndPermission/menuManagement/components/falseAlermRule.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
locale: 'project.menu.API_ERROR_REPORT_RULE',
|
locale: 'project.menu.API_ERROR_REPORT_RULE',
|
||||||
roles: ['*'],
|
roles: ['PROJECT_APPLICATION_API:READ'],
|
||||||
breadcrumbs: [
|
breadcrumbs: [
|
||||||
{
|
{
|
||||||
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_PERMISSION_MENU_MANAGEMENT,
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_PERMISSION_MENU_MANAGEMENT,
|
||||||
|
|
|
@ -44,7 +44,7 @@ const Setting: AppRouteRecordRaw = {
|
||||||
component: () => import('@/views/setting/system/usergroup/systemUserGroup.vue'),
|
component: () => import('@/views/setting/system/usergroup/systemUserGroup.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
locale: 'menu.settings.system.usergroup',
|
locale: 'menu.settings.system.usergroup',
|
||||||
roles: ['*'],
|
roles: ['SYSTEM_USER_ROLE:READ'],
|
||||||
isTopMenu: true,
|
isTopMenu: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -158,7 +158,7 @@ const Setting: AppRouteRecordRaw = {
|
||||||
component: () => import('@/views/setting/organization/usergroup/orgUserGroup.vue'),
|
component: () => import('@/views/setting/organization/usergroup/orgUserGroup.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
locale: 'menu.settings.organization.userGroup',
|
locale: 'menu.settings.organization.userGroup',
|
||||||
roles: ['*'],
|
roles: ['ORGANIZATION_USER_ROLE:READ'],
|
||||||
isTopMenu: true,
|
isTopMenu: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -168,7 +168,7 @@ const Setting: AppRouteRecordRaw = {
|
||||||
component: () => import('@/views/setting/organization/project/orgProject.vue'),
|
component: () => import('@/views/setting/organization/project/orgProject.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
locale: 'menu.settings.organization.project',
|
locale: 'menu.settings.organization.project',
|
||||||
roles: ['*'],
|
roles: ['ORGANIZATION_PROJECT:READ'],
|
||||||
isTopMenu: true,
|
isTopMenu: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -24,11 +24,13 @@
|
||||||
import MsMenuPanel from '@/components/pure/ms-menu-panel/index.vue';
|
import MsMenuPanel from '@/components/pure/ms-menu-panel/index.vue';
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import usePermission from '@/hooks/usePermission';
|
||||||
import useLicenseStore from '@/store/modules/setting/license';
|
import useLicenseStore from '@/store/modules/setting/license';
|
||||||
|
|
||||||
import { ProjectManagementRouteEnum } from '@/enums/routeEnum';
|
import { ProjectManagementRouteEnum } from '@/enums/routeEnum';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
const permission = usePermission();
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
@ -47,7 +49,7 @@
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const menuList = ref([
|
const sourceMenuList = [
|
||||||
{
|
{
|
||||||
key: 'project',
|
key: 'project',
|
||||||
title: t('project.permission.project'),
|
title: t('project.permission.project'),
|
||||||
|
@ -85,7 +87,18 @@
|
||||||
level: 2,
|
level: 2,
|
||||||
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_PERMISSION_USER_GROUP,
|
name: ProjectManagementRouteEnum.PROJECT_MANAGEMENT_PERMISSION_USER_GROUP,
|
||||||
},
|
},
|
||||||
]);
|
];
|
||||||
|
const menuList = computed(() => {
|
||||||
|
const routerList = router.getRoutes();
|
||||||
|
return sourceMenuList.filter((item) => {
|
||||||
|
if (item.name) {
|
||||||
|
const routerItem = routerList.find((rou) => rou.name === item.name);
|
||||||
|
if (!routerItem) return false;
|
||||||
|
return permission.accessRouter(routerItem);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const currentKey = ref<string>('');
|
const currentKey = ref<string>('');
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
:width="680"
|
:width="680"
|
||||||
:ok-loading="okLoading"
|
:ok-loading="okLoading"
|
||||||
:ok-disabled="okDisabled"
|
:ok-disabled="okDisabled"
|
||||||
|
:ok-permission="['PROJECT_APPLICATION_CASE:READ+UPDATE']"
|
||||||
@cancel="handleCancel(false)"
|
@cancel="handleCancel(false)"
|
||||||
@confirm="handleConfirm"
|
@confirm="handleConfirm"
|
||||||
>
|
>
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-4 flex items-center justify-between">
|
<div class="mb-4 flex items-center justify-between">
|
||||||
<a-button type="primary" @click="showAddRule(undefined)">{{ t('project.menu.addFalseAlertRules') }}</a-button>
|
<a-button v-permission="['PROJECT_APPLICATION_API:READ+ADD']" type="primary" @click="showAddRule(undefined)">{{
|
||||||
|
t('project.menu.addFalseAlertRules')
|
||||||
|
}}</a-button>
|
||||||
<a-input-search
|
<a-input-search
|
||||||
v-model="keyword"
|
v-model="keyword"
|
||||||
:placeholder="t('project.menu.nameSearch')"
|
:placeholder="t('project.menu.nameSearch')"
|
||||||
|
@ -24,18 +26,36 @@
|
||||||
>
|
>
|
||||||
<template #operation="{ record }">
|
<template #operation="{ record }">
|
||||||
<template v-if="!record.enable">
|
<template v-if="!record.enable">
|
||||||
<MsButton class="!mr-0" @click="handleEnableOrDisableProject(record.id)">{{ t('common.enable') }}</MsButton>
|
<div class="flex flex-row">
|
||||||
|
<span v-permission="['PROJECT_APPLICATION_API:READ+UPDATE']" class="flex flex-row">
|
||||||
|
<MsButton class="!mr-0" @click="handleEnableOrDisableProject(record.id)">{{
|
||||||
|
t('common.enable')
|
||||||
|
}}</MsButton>
|
||||||
<a-divider direction="vertical" />
|
<a-divider direction="vertical" />
|
||||||
<MsButton class="!mr-0" @click="handleDelete(record.id)">{{ t('common.delete') }}</MsButton>
|
</span>
|
||||||
|
<span>
|
||||||
|
<MsButton
|
||||||
|
v-permission="['PROJECT_APPLICATION_API:READ+DELETE']"
|
||||||
|
class="!mr-0"
|
||||||
|
@click="handleDelete(record.id)"
|
||||||
|
>{{ t('common.delete') }}</MsButton
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
|
<span v-permission="['PROJECT_APPLICATION_API:READ+UPDATE']" class="flex flex-row">
|
||||||
<MsButton class="!mr-0" @click="showAddRule(record)">{{ t('common.edit') }}</MsButton>
|
<MsButton class="!mr-0" @click="showAddRule(record)">{{ t('common.edit') }}</MsButton>
|
||||||
<a-divider direction="vertical" />
|
<a-divider direction="vertical" />
|
||||||
|
</span>
|
||||||
|
<span v-permission="['PROJECT_APPLICATION_API:READ+UPDATE']" class="flex flex-row">
|
||||||
<MsButton class="!mr-0" @click="handleEnableOrDisableProject(record.id, false)">{{
|
<MsButton class="!mr-0" @click="handleEnableOrDisableProject(record.id, false)">{{
|
||||||
t('common.disable')
|
t('common.disable')
|
||||||
}}</MsButton>
|
}}</MsButton>
|
||||||
<a-divider direction="vertical" />
|
<a-divider direction="vertical" />
|
||||||
|
</span>
|
||||||
<MsTableMoreAction
|
<MsTableMoreAction
|
||||||
|
v-permission="['PROJECT_APPLICATION_API:READ+DELETE']"
|
||||||
class="!mr-0"
|
class="!mr-0"
|
||||||
:list="tableActions"
|
:list="tableActions"
|
||||||
@select="handleMoreAction($event, record)"
|
@select="handleMoreAction($event, record)"
|
||||||
|
@ -70,7 +90,7 @@
|
||||||
</MsDrawer>
|
</MsDrawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script async lang="ts" setup>
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { Message, TableData } from '@arco-design/web-vue';
|
import { Message, TableData } from '@arco-design/web-vue';
|
||||||
|
|
||||||
|
@ -94,7 +114,7 @@
|
||||||
} from '@/api/modules/project-management/menuManagement';
|
} from '@/api/modules/project-management/menuManagement';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useModal from '@/hooks/useModal';
|
import useModal from '@/hooks/useModal';
|
||||||
import { useAppStore } from '@/store';
|
import { useAppStore, useTableStore } from '@/store';
|
||||||
|
|
||||||
import { FakeTableListItem } from '@/models/projectManagement/menuManagement';
|
import { FakeTableListItem } from '@/models/projectManagement/menuManagement';
|
||||||
import { ProjectManagementRouteEnum } from '@/enums/routeEnum';
|
import { ProjectManagementRouteEnum } from '@/enums/routeEnum';
|
||||||
|
@ -111,6 +131,7 @@
|
||||||
const batchFormRef = ref();
|
const batchFormRef = ref();
|
||||||
const ruleFormMode = ref<UserModalMode>('create');
|
const ruleFormMode = ref<UserModalMode>('create');
|
||||||
const currentList = ref<FakeTableListItem[]>([]);
|
const currentList = ref<FakeTableListItem[]>([]);
|
||||||
|
const tableStore = useTableStore();
|
||||||
const headerOptions = computed(() => [
|
const headerOptions = computed(() => [
|
||||||
{ label: 'Response Headers', value: 'headers' },
|
{ label: 'Response Headers', value: 'headers' },
|
||||||
{ label: 'Response Data', value: 'data' },
|
{ label: 'Response Data', value: 'data' },
|
||||||
|
@ -131,15 +152,18 @@
|
||||||
{
|
{
|
||||||
label: 'common.enable',
|
label: 'common.enable',
|
||||||
eventTag: 'batchEnable',
|
eventTag: 'batchEnable',
|
||||||
|
permission: ['PROJECT_APPLICATION_API:READ+UPDATE'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'common.disable',
|
label: 'common.disable',
|
||||||
eventTag: 'batchDisable',
|
eventTag: 'batchDisable',
|
||||||
|
permission: ['PROJECT_APPLICATION_API:READ+UPDATE'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'common.delete',
|
label: 'common.delete',
|
||||||
eventTag: 'batchDelete',
|
eventTag: 'batchDelete',
|
||||||
danger: true,
|
danger: true,
|
||||||
|
permission: ['PROJECT_APPLICATION_API:READ+UPDATE'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
@ -196,17 +220,16 @@
|
||||||
width: 169,
|
width: 169,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
await tableStore.initColumn(TableKeyEnum.PROJECT_MANAGEMENT_MENU_FALSE_ALERT, rulesColumn, 'drawer');
|
||||||
const { propsRes, propsEvent, loadList, setKeyword, setLoadListParams, resetSelector } = useTable(
|
const { propsRes, propsEvent, loadList, setKeyword, setLoadListParams, resetSelector } = useTable(
|
||||||
postFakeTableList,
|
postFakeTableList,
|
||||||
{
|
{
|
||||||
scroll: { x: 1200 },
|
scroll: { x: 1200 },
|
||||||
columns: rulesColumn,
|
|
||||||
tableKey: TableKeyEnum.PROJECT_MANAGEMENT_MENU_FALSE_ALERT,
|
tableKey: TableKeyEnum.PROJECT_MANAGEMENT_MENU_FALSE_ALERT,
|
||||||
selectable: true,
|
selectable: true,
|
||||||
noDisable: false,
|
noDisable: false,
|
||||||
size: 'default',
|
size: 'default',
|
||||||
debug: true,
|
showSetting: true,
|
||||||
},
|
},
|
||||||
(record: TableData) => {
|
(record: TableData) => {
|
||||||
record.typeList = record.type ? record.type.split(',') : [];
|
record.typeList = record.type ? record.type.split(',') : [];
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
:width="680"
|
:width="680"
|
||||||
:ok-loading="okLoading"
|
:ok-loading="okLoading"
|
||||||
:ok-disabled="okDisabled"
|
:ok-disabled="okDisabled"
|
||||||
|
:ok-permission="['PROJECT_APPLICATION_CASE:READ+UPDATE']"
|
||||||
@cancel="handleCancel(false)"
|
@cancel="handleCancel(false)"
|
||||||
@confirm="handleConfirm"
|
@confirm="handleConfirm"
|
||||||
>
|
>
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
<!-- 测试计划 报告保留时间范围 -->
|
<!-- 测试计划 报告保留时间范围 -->
|
||||||
<MsTimeSelectorVue
|
<MsTimeSelectorVue
|
||||||
v-model="allValueMap['TEST_PLAN_CLEAN_REPORT']"
|
v-model="allValueMap['TEST_PLAN_CLEAN_REPORT']"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_APPLICATION_TEST_PLAN:READ+UPDATE'])"
|
||||||
@change="(v: string) => handleMenuStatusChange('TEST_PLAN_CLEAN_REPORT',v,MenuEnum.testPlan)"
|
@change="(v: string) => handleMenuStatusChange('TEST_PLAN_CLEAN_REPORT',v,MenuEnum.testPlan)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -40,15 +41,19 @@
|
||||||
<!-- 测试计划 报告链接有效期 -->
|
<!-- 测试计划 报告链接有效期 -->
|
||||||
<MsTimeSelectorVue
|
<MsTimeSelectorVue
|
||||||
v-model="allValueMap['TEST_PLAN_SHARE_REPORT']"
|
v-model="allValueMap['TEST_PLAN_SHARE_REPORT']"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_APPLICATION_TEST_PLAN:READ+UPDATE'])"
|
||||||
@change="(v: string) => handleMenuStatusChange('TEST_PLAN_SHARE_REPORT',v,MenuEnum.testPlan)"
|
@change="(v: string) => handleMenuStatusChange('TEST_PLAN_SHARE_REPORT',v,MenuEnum.testPlan)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="record.type === 'BUG_SYNC'">
|
<template v-if="record.type === 'BUG_SYNC'">
|
||||||
<!-- 同步缺陷 -->
|
<!-- 同步缺陷 -->
|
||||||
<span>{{ t('project.menu.row2') }}</span>
|
<span>{{ t('project.menu.row2') }}</span>
|
||||||
<div class="ml-[8px] cursor-pointer text-[rgb(var(--primary-7))]" @click="showDefectDrawer">{{
|
<div
|
||||||
t('project.menu.BUG_SYNC')
|
v-permission="['PROJECT_APPLICATION_BUG:READ+UPDATE']"
|
||||||
}}</div>
|
class="ml-[8px] cursor-pointer text-[rgb(var(--primary-7))]"
|
||||||
|
@click="showDefectDrawer"
|
||||||
|
>{{ t('project.menu.BUG_SYNC') }}</div
|
||||||
|
>
|
||||||
</template>
|
</template>
|
||||||
<div v-if="record.type === 'CASE_PUBLIC'">
|
<div v-if="record.type === 'CASE_PUBLIC'">
|
||||||
<!-- 用例 公共用例库 -->
|
<!-- 用例 公共用例库 -->
|
||||||
|
@ -57,9 +62,12 @@
|
||||||
<div v-if="record.type === 'CASE_RELATED'" class="flex flex-row">
|
<div v-if="record.type === 'CASE_RELATED'" class="flex flex-row">
|
||||||
<!-- 用例 关联需求 -->
|
<!-- 用例 关联需求 -->
|
||||||
<div>{{ t('project.menu.row4') }}</div>
|
<div>{{ t('project.menu.row4') }}</div>
|
||||||
<div class="ml-[8px] cursor-pointer text-[rgb(var(--primary-7))]" @click="showRelatedCaseDrawer">{{
|
<div
|
||||||
t('project.menu.CASE_RELATED')
|
v-permission="['PROJECT_APPLICATION_CASE:READ+UPDATE']"
|
||||||
}}</div>
|
class="ml-[8px] cursor-pointer text-[rgb(var(--primary-7))]"
|
||||||
|
@click="showRelatedCaseDrawer"
|
||||||
|
>{{ t('project.menu.CASE_RELATED') }}</div
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="record.type === 'CASE_RE_REVIEW'">
|
<div v-if="record.type === 'CASE_RE_REVIEW'">
|
||||||
<!-- 用例 重新提审 -->
|
<!-- 用例 重新提审 -->
|
||||||
|
@ -72,6 +80,7 @@
|
||||||
<div v-if="record.type === 'API_CLEAN_REPORT'">
|
<div v-if="record.type === 'API_CLEAN_REPORT'">
|
||||||
<MsTimeSelectorVue
|
<MsTimeSelectorVue
|
||||||
v-model="allValueMap['API_CLEAN_REPORT']"
|
v-model="allValueMap['API_CLEAN_REPORT']"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_APPLICATION_API:READ+UPDATE'])"
|
||||||
@change="(v: string) => handleMenuStatusChange('API_CLEAN_REPORT',v,MenuEnum.apiTest)"
|
@change="(v: string) => handleMenuStatusChange('API_CLEAN_REPORT',v,MenuEnum.apiTest)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -79,6 +88,7 @@
|
||||||
<!--接口测试 报告链接有效期 -->
|
<!--接口测试 报告链接有效期 -->
|
||||||
<MsTimeSelectorVue
|
<MsTimeSelectorVue
|
||||||
v-model="allValueMap['API_SHARE_REPORT']"
|
v-model="allValueMap['API_SHARE_REPORT']"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_APPLICATION_API:READ+UPDATE'])"
|
||||||
@change="(v: string) => handleMenuStatusChange('API_SHARE_REPORT',v,MenuEnum.apiTest)"
|
@change="(v: string) => handleMenuStatusChange('API_SHARE_REPORT',v,MenuEnum.apiTest)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -89,6 +99,7 @@
|
||||||
:field-names="{ label: 'name', value: 'id' }"
|
:field-names="{ label: 'name', value: 'id' }"
|
||||||
:options="apiPoolOption"
|
:options="apiPoolOption"
|
||||||
class="w-[120px]"
|
class="w-[120px]"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_APPLICATION_API:READ+UPDATE'])"
|
||||||
@change="(v: SelectValue) => handleMenuStatusChange('API_RESOURCE_POOL_ID',v as string,MenuEnum.apiTest)"
|
@change="(v: SelectValue) => handleMenuStatusChange('API_RESOURCE_POOL_ID',v as string,MenuEnum.apiTest)"
|
||||||
/>
|
/>
|
||||||
<a-tooltip
|
<a-tooltip
|
||||||
|
@ -110,6 +121,7 @@
|
||||||
v-model="allValueMap['API_SCRIPT_REVIEWER_ID']"
|
v-model="allValueMap['API_SCRIPT_REVIEWER_ID']"
|
||||||
:field-names="{ label: 'name', value: 'id' }"
|
:field-names="{ label: 'name', value: 'id' }"
|
||||||
:options="apiAuditorOption"
|
:options="apiAuditorOption"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_APPLICATION_API:READ+UPDATE'])"
|
||||||
class="w-[120px]"
|
class="w-[120px]"
|
||||||
@change="(v: SelectValue) => handleMenuStatusChange('API_SCRIPT_REVIEWER_ID',v as string,MenuEnum.apiTest)"
|
@change="(v: SelectValue) => handleMenuStatusChange('API_SCRIPT_REVIEWER_ID',v as string,MenuEnum.apiTest)"
|
||||||
/>
|
/>
|
||||||
|
@ -133,9 +145,12 @@
|
||||||
</template>
|
</template>
|
||||||
</a-input-number>
|
</a-input-number>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-[8px] cursor-pointer text-[rgb(var(--primary-7))]" @click="pushFar">{{
|
<div
|
||||||
t('project.menu.API_ERROR_REPORT_RULE')
|
v-permission="['PROJECT_APPLICATION_API:READ+UPDATE']"
|
||||||
}}</div>
|
class="ml-[8px] cursor-pointer text-[rgb(var(--primary-7))]"
|
||||||
|
@click="pushFar"
|
||||||
|
>{{ t('project.menu.API_ERROR_REPORT_RULE') }}</div
|
||||||
|
>
|
||||||
<a-tooltip :content="t('project.menu.API_ERROR_REPORT_RULE_TIP')" position="right">
|
<a-tooltip :content="t('project.menu.API_ERROR_REPORT_RULE_TIP')" position="right">
|
||||||
<div>
|
<div>
|
||||||
<MsIcon class="ml-[4px] text-[rgb(var(--primary-5))]" type="icon-icon-maybe_outlined" />
|
<MsIcon class="ml-[4px] text-[rgb(var(--primary-5))]" type="icon-icon-maybe_outlined" />
|
||||||
|
@ -147,6 +162,7 @@
|
||||||
<!--UI 报告保留时间范围 -->
|
<!--UI 报告保留时间范围 -->
|
||||||
<MsTimeSelectorVue
|
<MsTimeSelectorVue
|
||||||
v-model="allValueMap['UI_CLEAN_REPORT']"
|
v-model="allValueMap['UI_CLEAN_REPORT']"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_APPLICATION_UI:READ+UPDATE'])"
|
||||||
@change="(v: string) => handleMenuStatusChange('UI_CLEAN_REPORT',v,MenuEnum.uiTest)"
|
@change="(v: string) => handleMenuStatusChange('UI_CLEAN_REPORT',v,MenuEnum.uiTest)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -154,6 +170,7 @@
|
||||||
<!--UI 报告链接有效期 -->
|
<!--UI 报告链接有效期 -->
|
||||||
<MsTimeSelectorVue
|
<MsTimeSelectorVue
|
||||||
v-model="allValueMap['UI_SHARE_REPORT']"
|
v-model="allValueMap['UI_SHARE_REPORT']"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_APPLICATION_UI:READ+UPDATE'])"
|
||||||
@change="(v: string) => handleMenuStatusChange('UI_SHARE_REPORT',v,MenuEnum.uiTest)"
|
@change="(v: string) => handleMenuStatusChange('UI_SHARE_REPORT',v,MenuEnum.uiTest)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -164,6 +181,7 @@
|
||||||
:field-names="{ label: 'name', value: 'id' }"
|
:field-names="{ label: 'name', value: 'id' }"
|
||||||
:options="uiPoolOption"
|
:options="uiPoolOption"
|
||||||
class="w-[120px]"
|
class="w-[120px]"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_APPLICATION_UI:READ+UPDATE'])"
|
||||||
@change="(v: SelectValue) => handleMenuStatusChange('UI_RESOURCE_POOL_ID',v as string,MenuEnum.uiTest)"
|
@change="(v: SelectValue) => handleMenuStatusChange('UI_RESOURCE_POOL_ID',v as string,MenuEnum.uiTest)"
|
||||||
/>
|
/>
|
||||||
<a-tooltip
|
<a-tooltip
|
||||||
|
@ -183,6 +201,7 @@
|
||||||
<!--性能测试 报告保留时间范围 -->
|
<!--性能测试 报告保留时间范围 -->
|
||||||
<MsTimeSelectorVue
|
<MsTimeSelectorVue
|
||||||
v-model="allValueMap['PERFORMANCE_TEST_CLEAN_REPORT']"
|
v-model="allValueMap['PERFORMANCE_TEST_CLEAN_REPORT']"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_APPLICATION_PERFORMANCE_TEST:READ+UPDATE'])"
|
||||||
@change="(v: string) => handleMenuStatusChange('PERFORMANCE_TEST_CLEAN_REPORT',v,MenuEnum.loadTest)"
|
@change="(v: string) => handleMenuStatusChange('PERFORMANCE_TEST_CLEAN_REPORT',v,MenuEnum.loadTest)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -190,6 +209,7 @@
|
||||||
<!--性能测试 报告链接有效期 -->
|
<!--性能测试 报告链接有效期 -->
|
||||||
<MsTimeSelectorVue
|
<MsTimeSelectorVue
|
||||||
v-model="allValueMap['PERFORMANCE_TEST_SHARE_REPORT']"
|
v-model="allValueMap['PERFORMANCE_TEST_SHARE_REPORT']"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_APPLICATION_PERFORMANCE_TEST:READ+UPDATE'])"
|
||||||
@change="(v: string) => handleMenuStatusChange('PERFORMANCE_TEST_SHARE_REPORT',v,MenuEnum.loadTest)"
|
@change="(v: string) => handleMenuStatusChange('PERFORMANCE_TEST_SHARE_REPORT',v,MenuEnum.loadTest)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -200,6 +220,7 @@
|
||||||
:field-names="{ label: 'name', value: 'id' }"
|
:field-names="{ label: 'name', value: 'id' }"
|
||||||
:options="performanceAuditorOption"
|
:options="performanceAuditorOption"
|
||||||
class="w-[120px]"
|
class="w-[120px]"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_APPLICATION_PERFORMANCE_TEST:READ+UPDATE'])"
|
||||||
@change="(v: SelectValue) => handleMenuStatusChange('PERFORMANCE_TEST_SCRIPT_REVIEWER_ID',v as string,MenuEnum.loadTest)"
|
@change="(v: SelectValue) => handleMenuStatusChange('PERFORMANCE_TEST_SCRIPT_REVIEWER_ID',v as string,MenuEnum.loadTest)"
|
||||||
/>
|
/>
|
||||||
<a-tooltip :content="t('project.menu.PERFORMANCE_TEST_SCRIPT_REVIEWER_TIP')" position="right">
|
<a-tooltip :content="t('project.menu.PERFORMANCE_TEST_SCRIPT_REVIEWER_TIP')" position="right">
|
||||||
|
@ -210,8 +231,12 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #operation="{ record }">
|
<template #operation="{ record }">
|
||||||
<!-- 同步缺陷状态 -->
|
<!-- 用例 同步缺陷状态 -->
|
||||||
<a-tooltip v-if="record.type === 'BUG_SYNC' && !allValueMap['BUG_SYNC_SYNC_ENABLE']" position="tr">
|
<a-tooltip
|
||||||
|
v-if="record.type === 'BUG_SYNC' && !allValueMap['BUG_SYNC_SYNC_ENABLE']"
|
||||||
|
v-permission="['PROJECT_APPLICATION_BUG:READ+UPDATE']"
|
||||||
|
position="tr"
|
||||||
|
>
|
||||||
<template #content>
|
<template #content>
|
||||||
<span>
|
<span>
|
||||||
{{ t('project.menu.notConfig') }}
|
{{ t('project.menu.notConfig') }}
|
||||||
|
@ -224,6 +249,7 @@
|
||||||
<a-switch
|
<a-switch
|
||||||
checked-value="true"
|
checked-value="true"
|
||||||
unchecked-value="false"
|
unchecked-value="false"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_APPLICATION_BUG:READ+UPDATE'])"
|
||||||
:value="allValueMap['BUG_SYNC_SYNC_ENABLE']"
|
:value="allValueMap['BUG_SYNC_SYNC_ENABLE']"
|
||||||
size="small"
|
size="small"
|
||||||
type="line"
|
type="line"
|
||||||
|
@ -234,12 +260,17 @@
|
||||||
v-if="record.type === 'BUG_SYNC' && allValueMap['BUG_SYNC_SYNC_ENABLE']"
|
v-if="record.type === 'BUG_SYNC' && allValueMap['BUG_SYNC_SYNC_ENABLE']"
|
||||||
checked-value="true"
|
checked-value="true"
|
||||||
unchecked-value="false"
|
unchecked-value="false"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_APPLICATION_BUG:READ+UPDATE'])"
|
||||||
size="small"
|
size="small"
|
||||||
type="line"
|
type="line"
|
||||||
@change="(v: boolean | string| number) => handleMenuStatusChange('BUG_SYNC_SYNC_ENABLE',v as boolean, MenuEnum.bugManagement)"
|
@change="(v: boolean | string| number) => handleMenuStatusChange('BUG_SYNC_SYNC_ENABLE',v as boolean, MenuEnum.bugManagement)"
|
||||||
/>
|
/>
|
||||||
<!-- 关联需求状态 -->
|
<!-- 功能测试 同步缺陷 -->
|
||||||
<a-tooltip v-if="record.type === 'CASE_RELATED' && !allValueMap['CASE_RELATED_CASE_ENABLE']" position="tr">
|
<a-tooltip
|
||||||
|
v-if="record.type === 'CASE_RELATED' && !allValueMap['CASE_RELATED_CASE_ENABLE']"
|
||||||
|
v-permission="['PROJECT_APPLICATION_BUG:READ+UPDATE']"
|
||||||
|
position="tr"
|
||||||
|
>
|
||||||
<template #content>
|
<template #content>
|
||||||
<span>
|
<span>
|
||||||
{{ t('project.menu.notConfig') }}
|
{{ t('project.menu.notConfig') }}
|
||||||
|
@ -252,6 +283,7 @@
|
||||||
<a-switch
|
<a-switch
|
||||||
checked-value="true"
|
checked-value="true"
|
||||||
unchecked-value="false"
|
unchecked-value="false"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_APPLICATION_CASE:READ+UPDATE'])"
|
||||||
:value="allValueMap['CASE_RELATED_CASE_ENABLE']"
|
:value="allValueMap['CASE_RELATED_CASE_ENABLE']"
|
||||||
size="small"
|
size="small"
|
||||||
type="line"
|
type="line"
|
||||||
|
@ -260,6 +292,7 @@
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-switch
|
<a-switch
|
||||||
v-if="record.type === 'CASE_RELATED' && allValueMap['CASE_RELATED_CASE_ENABLE']"
|
v-if="record.type === 'CASE_RELATED' && allValueMap['CASE_RELATED_CASE_ENABLE']"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_APPLICATION_BUG:READ+UPDATE'])"
|
||||||
checked-value="true"
|
checked-value="true"
|
||||||
unchecked-value="false"
|
unchecked-value="false"
|
||||||
size="small"
|
size="small"
|
||||||
|
@ -271,6 +304,7 @@
|
||||||
<a-switch
|
<a-switch
|
||||||
v-if="record.type === 'WORKSTATION_SYNC_RULE'"
|
v-if="record.type === 'WORKSTATION_SYNC_RULE'"
|
||||||
v-model="allValueMap['WORKSTATION_SYNC_RULE']"
|
v-model="allValueMap['WORKSTATION_SYNC_RULE']"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_APPLICATION_API:READ+UPDATE'])"
|
||||||
checked-value="true"
|
checked-value="true"
|
||||||
unchecked-value="false"
|
unchecked-value="false"
|
||||||
size="small"
|
size="small"
|
||||||
|
@ -281,6 +315,7 @@
|
||||||
<a-switch
|
<a-switch
|
||||||
v-if="record.type === 'CASE_PUBLIC'"
|
v-if="record.type === 'CASE_PUBLIC'"
|
||||||
v-model="allValueMap['CASE_PUBLIC']"
|
v-model="allValueMap['CASE_PUBLIC']"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_APPLICATION_CASE:READ+UPDATE'])"
|
||||||
checked-value="true"
|
checked-value="true"
|
||||||
unchecked-value="false"
|
unchecked-value="false"
|
||||||
size="small"
|
size="small"
|
||||||
|
@ -291,6 +326,7 @@
|
||||||
<a-switch
|
<a-switch
|
||||||
v-if="record.type === 'CASE_RE_REVIEW'"
|
v-if="record.type === 'CASE_RE_REVIEW'"
|
||||||
v-model="allValueMap['CASE_RE_REVIEW']"
|
v-model="allValueMap['CASE_RE_REVIEW']"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_APPLICATION_CASE:READ+UPDATE'])"
|
||||||
checked-value="true"
|
checked-value="true"
|
||||||
unchecked-value="false"
|
unchecked-value="false"
|
||||||
size="small"
|
size="small"
|
||||||
|
@ -301,6 +337,7 @@
|
||||||
<a-switch
|
<a-switch
|
||||||
v-if="record.type === 'API_URL_REPEATABLE'"
|
v-if="record.type === 'API_URL_REPEATABLE'"
|
||||||
v-model="allValueMap['API_URL_REPEATABLE']"
|
v-model="allValueMap['API_URL_REPEATABLE']"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_APPLICATION_API:READ+UPDATE'])"
|
||||||
checked-value="true"
|
checked-value="true"
|
||||||
unchecked-value="false"
|
unchecked-value="false"
|
||||||
size="small"
|
size="small"
|
||||||
|
@ -311,6 +348,7 @@
|
||||||
<a-switch
|
<a-switch
|
||||||
v-if="record.type === 'API_SYNC_CASE'"
|
v-if="record.type === 'API_SYNC_CASE'"
|
||||||
v-model="allValueMap['API_SYNC_CASE']"
|
v-model="allValueMap['API_SYNC_CASE']"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_APPLICATION_API:READ+UPDATE'])"
|
||||||
checked-value="true"
|
checked-value="true"
|
||||||
unchecked-value="false"
|
unchecked-value="false"
|
||||||
size="small"
|
size="small"
|
||||||
|
@ -321,6 +359,7 @@
|
||||||
<a-switch
|
<a-switch
|
||||||
v-if="record.type === 'PERFORMANCE_TEST_SCRIPT_REVIEWER'"
|
v-if="record.type === 'PERFORMANCE_TEST_SCRIPT_REVIEWER'"
|
||||||
v-model="allValueMap['PERFORMANCE_TEST_SCRIPT_REVIEWER_ENABLE']"
|
v-model="allValueMap['PERFORMANCE_TEST_SCRIPT_REVIEWER_ENABLE']"
|
||||||
|
:disabled="!hasAnyPermission(['PROJECT_APPLICATION_PERFORMANCE_TEST:READ+UPDATE'])"
|
||||||
checked-value="true"
|
checked-value="true"
|
||||||
unchecked-value="false"
|
unchecked-value="false"
|
||||||
size="small"
|
size="small"
|
||||||
|
@ -356,6 +395,7 @@
|
||||||
} from '@/api/modules/project-management/menuManagement';
|
} from '@/api/modules/project-management/menuManagement';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import { useAppStore } from '@/store';
|
import { useAppStore } from '@/store';
|
||||||
|
import { hasAnyPermission } from '@/utils/permission';
|
||||||
|
|
||||||
import { MenuTableConfigItem, PoolOption, SelectValue } from '@/models/projectManagement/menuManagement';
|
import { MenuTableConfigItem, PoolOption, SelectValue } from '@/models/projectManagement/menuManagement';
|
||||||
import { MenuEnum } from '@/enums/commonEnum';
|
import { MenuEnum } from '@/enums/commonEnum';
|
||||||
|
@ -562,6 +602,52 @@
|
||||||
|
|
||||||
const getMenuConfig = async (type: string) => {
|
const getMenuConfig = async (type: string) => {
|
||||||
try {
|
try {
|
||||||
|
let hasAuth = false;
|
||||||
|
switch (type) {
|
||||||
|
case MenuEnum.workstation:
|
||||||
|
if (hasAnyPermission(['PROJECT_APPLICATION_WORKSTATION:READ'])) {
|
||||||
|
hasAuth = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MenuEnum.apiTest:
|
||||||
|
if (hasAnyPermission(['PROJECT_APPLICATION_API:READ'])) {
|
||||||
|
hasAuth = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MenuEnum.bugManagement:
|
||||||
|
if (hasAnyPermission(['PROJECT_APPLICATION_BUG:READ'])) {
|
||||||
|
hasAuth = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MenuEnum.caseManagement:
|
||||||
|
if (hasAnyPermission(['PROJECT_APPLICATION_CASE:READ'])) {
|
||||||
|
hasAuth = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'loadTest':
|
||||||
|
if (hasAnyPermission(['PROJECT_APPLICATION_PERFORMANCE_TEST:READ'])) {
|
||||||
|
hasAuth = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MenuEnum.testPlan:
|
||||||
|
if (hasAnyPermission(['PROJECT_APPLICATION_TEST_PLAN:READ'])) {
|
||||||
|
hasAuth = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MenuEnum.uiTest:
|
||||||
|
if (hasAnyPermission(['PROJECT_APPLICATION_UI:READ'])) {
|
||||||
|
hasAuth = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasAuth) {
|
||||||
|
Message.error(t('common.noPermission'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const resultObj = await getConfigByMenuItem({
|
const resultObj = await getConfigByMenuItem({
|
||||||
projectId: currentProjectId.value,
|
projectId: currentProjectId.value,
|
||||||
type,
|
type,
|
||||||
|
@ -584,14 +670,11 @@
|
||||||
getMenuConfig(record.module);
|
getMenuConfig(record.module);
|
||||||
if (record.module === MenuEnum.apiTest && !apiPoolOption.value.length) {
|
if (record.module === MenuEnum.apiTest && !apiPoolOption.value.length) {
|
||||||
apiPoolOption.value = await getPoolOptions(currentProjectId.value, record.module);
|
apiPoolOption.value = await getPoolOptions(currentProjectId.value, record.module);
|
||||||
}
|
} else if (record.module === MenuEnum.uiTest && !uiPoolOption.value.length) {
|
||||||
if (record.module === MenuEnum.uiTest && !uiPoolOption.value.length) {
|
|
||||||
uiPoolOption.value = await getPoolOptions(currentProjectId.value, record.module);
|
uiPoolOption.value = await getPoolOptions(currentProjectId.value, record.module);
|
||||||
}
|
} else if (record.module === MenuEnum.apiTest && !apiAuditorOption.value.length) {
|
||||||
if (record.module === MenuEnum.apiTest && !apiAuditorOption.value.length) {
|
|
||||||
apiAuditorOption.value = await getAuditorOptions(currentProjectId.value, record.module);
|
apiAuditorOption.value = await getAuditorOptions(currentProjectId.value, record.module);
|
||||||
}
|
} else if (record.module === MenuEnum.loadTest && !performanceAuditorOption.value.length) {
|
||||||
if (record.module === MenuEnum.loadTest && !performanceAuditorOption.value.length) {
|
|
||||||
performanceAuditorOption.value = await getAuditorOptions(currentProjectId.value, record.module);
|
performanceAuditorOption.value = await getAuditorOptions(currentProjectId.value, record.module);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -620,6 +703,53 @@
|
||||||
|
|
||||||
const handleMenuStatusChange = async (type: string, typeValue: string | boolean, suffix: string) => {
|
const handleMenuStatusChange = async (type: string, typeValue: string | boolean, suffix: string) => {
|
||||||
try {
|
try {
|
||||||
|
let hasAuth = false;
|
||||||
|
switch (suffix) {
|
||||||
|
case MenuEnum.workstation:
|
||||||
|
if (hasAnyPermission(['PROJECT_APPLICATION_WORKSTATION:READ+UPDATE'])) {
|
||||||
|
hasAuth = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MenuEnum.apiTest:
|
||||||
|
if (hasAnyPermission(['PROJECT_APPLICATION_API:READ+UPDATE'])) {
|
||||||
|
hasAuth = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MenuEnum.bugManagement:
|
||||||
|
if (hasAnyPermission(['PROJECT_APPLICATION_BUG:READ+UPDATE'])) {
|
||||||
|
hasAuth = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MenuEnum.caseManagement:
|
||||||
|
if (hasAnyPermission(['PROJECT_APPLICATION_CASE:READ+UPDATE'])) {
|
||||||
|
hasAuth = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MenuEnum.loadTest:
|
||||||
|
if (hasAnyPermission(['PROJECT_APPLICATION_PERFORMANCE_TEST:READ+UPDATE'])) {
|
||||||
|
hasAuth = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MenuEnum.testPlan:
|
||||||
|
if (hasAnyPermission(['PROJECT_APPLICATION_TEST_PLAN:READ+UPDATE'])) {
|
||||||
|
hasAuth = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MenuEnum.uiTest:
|
||||||
|
if (hasAnyPermission(['PROJECT_APPLICATION_UI:READ+UPDATE'])) {
|
||||||
|
hasAuth = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log('no ');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasAuth) {
|
||||||
|
Message.error(t('common.noPermission'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
await postUpdateMenu(
|
await postUpdateMenu(
|
||||||
{
|
{
|
||||||
projectId: currentProjectId.value,
|
projectId: currentProjectId.value,
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-row items-center justify-between">
|
<div class="flex flex-row items-center justify-between">
|
||||||
<a-button type="primary" @click="addUserGroup">{{ t('project.userGroup.add') }}</a-button>
|
<a-button v-permission="['PROJECT_GROUP:READ+ADD']" type="primary" @click="addUserGroup">{{
|
||||||
|
t('project.userGroup.add')
|
||||||
|
}}</a-button>
|
||||||
<a-input-search
|
<a-input-search
|
||||||
v-model="keyword"
|
v-model="keyword"
|
||||||
:placeholder="t('project.userGroup.searchUser')"
|
:placeholder="t('project.userGroup.searchUser')"
|
||||||
|
@ -61,9 +63,14 @@
|
||||||
<ms-button class="btn" :disabled="!canSave" @click="handleAuthReset">{{
|
<ms-button class="btn" :disabled="!canSave" @click="handleAuthReset">{{
|
||||||
t('system.userGroup.reset')
|
t('system.userGroup.reset')
|
||||||
}}</ms-button>
|
}}</ms-button>
|
||||||
<a-button class="btn" :disabled="!canSave" type="primary" @click="handleAuthSave">{{
|
<a-button
|
||||||
t('common.save')
|
v-permission="['PROJECT_GROUP:READ+UPDATE']"
|
||||||
}}</a-button>
|
class="btn"
|
||||||
|
:disabled="!canSave"
|
||||||
|
type="primary"
|
||||||
|
@click="handleAuthSave"
|
||||||
|
>{{ t('common.save') }}</a-button
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</MsDrawer>
|
</MsDrawer>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<MsCard simple>
|
<MsCard simple>
|
||||||
<div class="mb-4 flex items-center justify-between">
|
<div class="mb-[16px] flex items-center justify-between">
|
||||||
<a-button type="primary" @click="showAddProject">{{ t('system.organization.createProject') }}</a-button>
|
<a-button type="primary" @click="showAddProject">{{ t('system.organization.createProject') }}</a-button>
|
||||||
<a-input-search
|
<a-input-search
|
||||||
v-model="keyword"
|
v-model="keyword"
|
||||||
|
@ -31,17 +31,35 @@
|
||||||
</template>
|
</template>
|
||||||
<template #operation="{ record }">
|
<template #operation="{ record }">
|
||||||
<template v-if="record.deleted">
|
<template v-if="record.deleted">
|
||||||
<MsButton @click="handleRevokeDelete(record)">{{ t('common.revokeDelete') }}</MsButton>
|
<MsButton v-permission="['ORGANIZATION_PROJECT:READ+RECOVER']" @click="handleRevokeDelete(record)">{{
|
||||||
|
t('common.revokeDelete')
|
||||||
|
}}</MsButton>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="!record.enable">
|
<template v-else-if="!record.enable">
|
||||||
<MsButton @click="handleEnableOrDisableProject(record)">{{ t('common.enable') }}</MsButton>
|
<MsButton v-permission="['ORGANIZATION_PROJECT:READ+UPDATE']" @click="handleEnableOrDisableProject(record)">{{
|
||||||
<MsButton @click="handleDelete(record)">{{ t('common.delete') }}</MsButton>
|
t('common.enable')
|
||||||
|
}}</MsButton>
|
||||||
|
<MsButton v-permission="['ORGANIZATION_PROJECT:READ+DELETE']" @click="handleDelete(record)">{{
|
||||||
|
t('common.delete')
|
||||||
|
}}</MsButton>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<MsButton @click="showAddProjectModal(record)">{{ t('common.edit') }}</MsButton>
|
<MsButton v-permission="['ORGANIZATION_PROJECT:READ+UPDATE']" @click="showAddProjectModal(record)">{{
|
||||||
<MsButton @click="showAddUserModal(record)">{{ t('system.organization.addMember') }}</MsButton>
|
t('common.edit')
|
||||||
<MsButton @click="handleEnableOrDisableProject(record, false)">{{ t('common.end') }}</MsButton>
|
}}</MsButton>
|
||||||
<MsTableMoreAction :list="tableActions" @select="handleMoreAction($event, record)"></MsTableMoreAction>
|
<MsButton v-permission="['ORGANIZATION_PROJECT:READ+UPDATE']" @click="showAddUserModal(record)">{{
|
||||||
|
t('system.organization.addMember')
|
||||||
|
}}</MsButton>
|
||||||
|
<MsButton
|
||||||
|
v-permission="['ORGANIZATION_PROJECT:READ+UPDATE']"
|
||||||
|
@click="handleEnableOrDisableProject(record, false)"
|
||||||
|
>{{ t('common.end') }}</MsButton
|
||||||
|
>
|
||||||
|
<MsTableMoreAction
|
||||||
|
v-permission="['ORGANIZATION_PROJECT:READ+DELETE']"
|
||||||
|
:list="tableActions"
|
||||||
|
@select="handleMoreAction($event, record)"
|
||||||
|
></MsTableMoreAction>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</MsBaseTable>
|
</MsBaseTable>
|
||||||
|
@ -177,6 +195,10 @@
|
||||||
dataIndex: 'createTime',
|
dataIndex: 'createTime',
|
||||||
width: 180,
|
width: 180,
|
||||||
showDrag: true,
|
showDrag: true,
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'system.organization.operation',
|
title: 'system.organization.operation',
|
||||||
|
@ -205,9 +227,8 @@
|
||||||
tableKey: TableKeyEnum.ORGANIZATION_PROJECT,
|
tableKey: TableKeyEnum.ORGANIZATION_PROJECT,
|
||||||
selectable: false,
|
selectable: false,
|
||||||
noDisable: false,
|
noDisable: false,
|
||||||
size: 'default',
|
|
||||||
showSetting: true,
|
showSetting: true,
|
||||||
heightUsed: 286,
|
heightUsed: 300,
|
||||||
},
|
},
|
||||||
undefined,
|
undefined,
|
||||||
(record) => handleNameChange(record)
|
(record) => handleNameChange(record)
|
||||||
|
|
|
@ -36,11 +36,15 @@
|
||||||
ref="userRef"
|
ref="userRef"
|
||||||
:keyword="currentKeyword"
|
:keyword="currentKeyword"
|
||||||
:current="currentUserGroupItem"
|
:current="currentUserGroupItem"
|
||||||
|
:delete-permission="['ORGANIZATION_USER_ROLE:READ+DELETE']"
|
||||||
|
:read-permission="['ORGANIZATION_USER_ROLE:READ']"
|
||||||
|
:update-permission="['ORGANIZATION_USER_ROLE:READ+UPDATE']"
|
||||||
/>
|
/>
|
||||||
<AuthTable
|
<AuthTable
|
||||||
v-if="currentTable === 'auth' && couldShowAuth"
|
v-if="currentTable === 'auth' && couldShowAuth"
|
||||||
:current="currentUserGroupItem"
|
:current="currentUserGroupItem"
|
||||||
:width="bottomWidth"
|
:width="bottomWidth"
|
||||||
|
:save-permission="['ORGANIZATION_GROUP:READ+UPDATE']"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,8 +3,15 @@
|
||||||
<template #revokeDelete="{ record }">
|
<template #revokeDelete="{ record }">
|
||||||
<a-tooltip background-color="#FFFFFF">
|
<a-tooltip background-color="#FFFFFF">
|
||||||
<template #content>
|
<template #content>
|
||||||
|
<span>
|
||||||
<span class="text-[var(--color-text-1)]">{{ t('system.organization.revokeDeleteToolTip') }}</span>
|
<span class="text-[var(--color-text-1)]">{{ t('system.organization.revokeDeleteToolTip') }}</span>
|
||||||
<MsButton class="ml-[8px]" @click="handleRevokeDelete(record)">{{ t('common.revokeDelete') }}</MsButton>
|
<MsButton
|
||||||
|
v-permission="['SYSTEM_ORGANIZATION_PROJECT:READ+RECOVER']"
|
||||||
|
class="ml-[8px]"
|
||||||
|
@click="handleRevokeDelete(record)"
|
||||||
|
>{{ t('common.revokeDelete') }}</MsButton
|
||||||
|
>
|
||||||
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<MsIcon v-if="record.deleted" type="icon-icon_alarm_clock" class="ml-[4px] text-[rgb(var(--danger-6))]" />
|
<MsIcon v-if="record.deleted" type="icon-icon_alarm_clock" class="ml-[4px] text-[rgb(var(--danger-6))]" />
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
|
@ -93,6 +100,7 @@
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useModal from '@/hooks/useModal';
|
import useModal from '@/hooks/useModal';
|
||||||
import { useTableStore } from '@/store';
|
import { useTableStore } from '@/store';
|
||||||
|
import { hasAnyPermission } from '@/utils/permission';
|
||||||
|
|
||||||
import { CreateOrUpdateSystemOrgParams, OrgProjectTableItem } from '@/models/setting/system/orgAndProject';
|
import { CreateOrUpdateSystemOrgParams, OrgProjectTableItem } from '@/models/setting/system/orgAndProject';
|
||||||
import { ColumnEditTypeEnum, TableKeyEnum } from '@/enums/tableEnum';
|
import { ColumnEditTypeEnum, TableKeyEnum } from '@/enums/tableEnum';
|
||||||
|
@ -122,7 +130,7 @@
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
width: 300,
|
width: 300,
|
||||||
revokeDeletedSlot: 'revokeDelete',
|
revokeDeletedSlot: 'revokeDelete',
|
||||||
editType: ColumnEditTypeEnum.INPUT,
|
editType: hasAnyPermission(['SYSTEM_ORGANIZATIN_PROJECT:READ+UPDATE']) ? ColumnEditTypeEnum.INPUT : undefined,
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,8 +3,15 @@
|
||||||
<template #revokeDelete="{ record }">
|
<template #revokeDelete="{ record }">
|
||||||
<a-tooltip background-color="#FFFFFF">
|
<a-tooltip background-color="#FFFFFF">
|
||||||
<template #content>
|
<template #content>
|
||||||
|
<span>
|
||||||
<span class="text-[var(--color-text-1)]">{{ t('system.project.revokeDeleteToolTip') }}</span>
|
<span class="text-[var(--color-text-1)]">{{ t('system.project.revokeDeleteToolTip') }}</span>
|
||||||
<MsButton class="ml-[8px]" @click="handleRevokeDelete(record)">{{ t('common.revokeDelete') }}</MsButton>
|
<MsButton
|
||||||
|
v-permission="['SYSTEM_ORGANIZATION_PROJECT:READ+RECOVER']"
|
||||||
|
class="ml-[8px]"
|
||||||
|
@click="handleRevokeDelete(record)"
|
||||||
|
>{{ t('common.revokeDelete') }}</MsButton
|
||||||
|
>
|
||||||
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<MsIcon v-if="record.deleted" type="icon-icon_alarm_clock" class="ml-[4px] text-[rgb(var(--danger-6))]" />
|
<MsIcon v-if="record.deleted" type="icon-icon_alarm_clock" class="ml-[4px] text-[rgb(var(--danger-6))]" />
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
|
@ -91,6 +98,7 @@
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useModal from '@/hooks/useModal';
|
import useModal from '@/hooks/useModal';
|
||||||
import { useTableStore } from '@/store';
|
import { useTableStore } from '@/store';
|
||||||
|
import { hasAnyPermission } from '@/utils/permission';
|
||||||
|
|
||||||
import { UserItem } from '@/models/setting/log';
|
import { UserItem } from '@/models/setting/log';
|
||||||
import { CreateOrUpdateSystemProjectParams, OrgProjectTableItem } from '@/models/setting/system/orgAndProject';
|
import { CreateOrUpdateSystemProjectParams, OrgProjectTableItem } from '@/models/setting/system/orgAndProject';
|
||||||
|
@ -120,7 +128,7 @@
|
||||||
title: 'system.organization.name',
|
title: 'system.organization.name',
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
revokeDeletedSlot: 'revokeDelete',
|
revokeDeletedSlot: 'revokeDelete',
|
||||||
editType: ColumnEditTypeEnum.INPUT,
|
editType: hasAnyPermission(['SYSTEM_ORGANIZATIN_PROJECT:READ+UPDATE']) ? ColumnEditTypeEnum.INPUT : undefined,
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,11 +2,16 @@
|
||||||
<MsCard simple>
|
<MsCard simple>
|
||||||
<div class="mb-4 flex items-center justify-between">
|
<div class="mb-4 flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<a-button type="primary" @click="handleAddOrganization">{{
|
<a-button
|
||||||
|
v-permission="['SYSTEM_ORGANIZATION_PROJECT:READ+ADD']"
|
||||||
|
type="primary"
|
||||||
|
@click="handleAddOrganization"
|
||||||
|
>{{
|
||||||
currentTable === 'organization'
|
currentTable === 'organization'
|
||||||
? t('system.organization.createOrganization')
|
? t('system.organization.createOrganization')
|
||||||
: t('system.organization.createProject')
|
: t('system.organization.createProject')
|
||||||
}}</a-button>
|
}}</a-button
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<a-input-search
|
<a-input-search
|
||||||
|
|
|
@ -36,11 +36,15 @@
|
||||||
ref="userRef"
|
ref="userRef"
|
||||||
:keyword="currentKeyword"
|
:keyword="currentKeyword"
|
||||||
:current="currentUserGroupItem"
|
:current="currentUserGroupItem"
|
||||||
|
:delete-permission="['SYSTEM_USER_ROLE:READ+DELETE']"
|
||||||
|
:read-permission="['SYSTEM_USER_ROLE:READ']"
|
||||||
|
:update-permission="['SYSTEM_USER_ROLE:READ+UPDATE']"
|
||||||
/>
|
/>
|
||||||
<AuthTable
|
<AuthTable
|
||||||
v-if="currentTable === 'auth' && couldShowAuth"
|
v-if="currentTable === 'auth' && couldShowAuth"
|
||||||
:current="currentUserGroupItem"
|
:current="currentUserGroupItem"
|
||||||
:width="bottomWidth"
|
:width="bottomWidth"
|
||||||
|
:save-permission="['PROJECT_GROUP:READ+UPDATE']"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue