From 09b4b6756af4d8f0009f4903473c942fa84fdf1a Mon Sep 17 00:00:00 2001 From: RubyLiu Date: Tue, 23 Jan 2024 20:04:41 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=A1=B5=E9=9D=A2=E5=8F=8A=E6=8C=89?= =?UTF-8?q?=E9=92=AE=E6=9D=83=E9=99=90&=E7=8E=AF=E5=A2=83=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E6=96=B0=E5=A2=9E=E7=8E=AF=E5=A2=83=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=AF=B9=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/App.vue | 4 + .../project-management/envManagement.ts | 13 +- .../api/modules/project-management/project.ts | 4 + .../api/requrls/project-management/project.ts | 1 + .../business/ms-assertion/comp/ScriptTab.vue | 246 ++++++++++++++++++ .../business/ms-assertion/index.vue | 2 + .../src/components/business/ms-menu/index.vue | 2 + .../components/business/ms-top-menu/index.vue | 4 +- frontend/src/directive/permission/index.ts | 11 +- frontend/src/enums/routeEnum.ts | 4 +- frontend/src/hooks/usePermission.ts | 34 +-- .../models/projectManagement/environmental.ts | 8 +- frontend/src/models/setting/project.ts | 1 + frontend/src/models/user.ts | 49 +--- .../routes/modules/projectManagement.ts | 2 +- frontend/src/router/routes/modules/setting.ts | 2 +- frontend/src/store/modules/app/index.ts | 14 + frontend/src/store/modules/app/types.ts | 2 + .../modules/setting/useProjectEnvStore.ts | 17 +- frontend/src/store/modules/user/index.ts | 21 +- frontend/src/store/modules/user/types.ts | 22 ++ frontend/src/utils/permission.ts | 67 +++++ .../environmental/components/EnvParamBox.vue | 60 +++-- .../components/envParams/AssertTab.vue | 15 +- .../components/envParams/DatabaseTab.vue | 22 +- .../components/envParams/DisplayTab.vue | 13 - .../components/envParams/EnvParamsTab.vue | 13 +- .../components/envParams/HostTab.vue | 21 +- .../components/envParams/HttpTab.vue | 14 +- .../components/envParams/PostTab.vue | 17 +- .../components/envParams/PreTab.vue | 17 +- .../components/systemOrganization.vue | 30 ++- .../components/systemProject.vue | 34 ++- 33 files changed, 591 insertions(+), 195 deletions(-) create mode 100644 frontend/src/components/business/ms-assertion/comp/ScriptTab.vue create mode 100644 frontend/src/utils/permission.ts delete mode 100644 frontend/src/views/project-management/environmental/components/envParams/DisplayTab.vue diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 8b28a9dc18..4de1b00b93 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -67,6 +67,10 @@ const checkIsLogin = async () => { const isLogin = await userStore.isLogin(); const isLoginPage = route.name === 'login'; + if (isLogin && appStore.currentProjectId) { + // 当前为登陆状态,且已经选择了项目,初始化当前项目配置 + appStore.setCurrentMenuConfig(); + } if (isLoginPage && isLogin) { // 当前页面为登录页面,且已经登录,跳转到首页 router.push(WorkbenchRouteEnum.WORKBENCH); diff --git a/frontend/src/api/modules/project-management/envManagement.ts b/frontend/src/api/modules/project-management/envManagement.ts index 9d273d7794..86172199b3 100644 --- a/frontend/src/api/modules/project-management/envManagement.ts +++ b/frontend/src/api/modules/project-management/envManagement.ts @@ -12,8 +12,8 @@ import type { } from '@/models/projectManagement/environmental'; import { OptionsItem } from '@/models/setting/log'; -export function updateEnv(data: EnvListItem) { - return MSR.post({ url: envURL.updateEnvUrl, data }); +export function updateOrAddEnv(data: EnvDetailItem) { + return MSR.post({ url: data.id ? envURL.updateEnvUrl : envURL.addEnvUrl, data }); } export function listEnv(data: { projectId: string; keyword: string }) { return MSR.post({ url: envURL.listEnvUrl, data }); @@ -24,8 +24,8 @@ export function importEnv(data: { request: EnvListItem; fileList: FileItem[] }) export function getEntryEnv(data: EnvListItem) { return MSR.post({ url: envURL.getEntryEnvUrl, data }); } -export function exportEnv(data: EnvListItem) { - return MSR.post({ url: envURL.exportEnvUrl, data }); +export function exportEnv(id: string) { + return MSR.get({ url: envURL.exportEnvUrl + id, responseType: 'blob' }, { isTransformResponse: false }); } export function editPosEnv(data: EnvListItem) { return MSR.post({ url: envURL.editPosEnvUrl, data }); @@ -85,5 +85,8 @@ export function getGlobalParamDetail(id: string) { } /** 项目管理-环境-全局参数-导出 */ export function exportGlobalParam(id: string) { - return MSR.get({ url: envURL.exportGlobalParamUrl + id }); + return MSR.get( + { url: envURL.exportGlobalParamUrl + id, responseType: 'blob' }, + { isTransformResponse: false } + ); } diff --git a/frontend/src/api/modules/project-management/project.ts b/frontend/src/api/modules/project-management/project.ts index fb2f6c2206..ffa6ee0ef5 100644 --- a/frontend/src/api/modules/project-management/project.ts +++ b/frontend/src/api/modules/project-management/project.ts @@ -10,3 +10,7 @@ export function getProjectList(organizationId: string) { export function switchProject(data: { projectId: string; userId: string }) { return MSR.post({ url: ProjectSwitchUrl, data }); } + +export function getProjectInfo(projectId: string) { + return MSR.get({ url: `/project/get/${projectId}` }); +} diff --git a/frontend/src/api/requrls/project-management/project.ts b/frontend/src/api/requrls/project-management/project.ts index d6d4d12fb1..9ea894dff9 100644 --- a/frontend/src/api/requrls/project-management/project.ts +++ b/frontend/src/api/requrls/project-management/project.ts @@ -1,2 +1,3 @@ export const ProjectListUrl = '/project/list/options'; // 项目列表 export const ProjectSwitchUrl = '/project/switch'; // 切换项目 +export const projectModuleInfoUrl = '/project/get/'; // 获取项目模块信息 diff --git a/frontend/src/components/business/ms-assertion/comp/ScriptTab.vue b/frontend/src/components/business/ms-assertion/comp/ScriptTab.vue new file mode 100644 index 0000000000..d85783ca88 --- /dev/null +++ b/frontend/src/components/business/ms-assertion/comp/ScriptTab.vue @@ -0,0 +1,246 @@ + + + + + diff --git a/frontend/src/components/business/ms-assertion/index.vue b/frontend/src/components/business/ms-assertion/index.vue index c8a68ea951..fd27312f6b 100644 --- a/frontend/src/components/business/ms-assertion/index.vue +++ b/frontend/src/components/business/ms-assertion/index.vue @@ -63,6 +63,7 @@ + @@ -77,6 +78,7 @@ import { ActionsItem } from '@/components/pure/ms-table-more-action/types'; import ResponseHeaderTab from './comp/ResponseHeaderTab.vue'; import ResponseTimeTab from './comp/ResponseTimeTab.vue'; + import ScriptTab from './comp/ScriptTab.vue'; import StatusCodeTab from './comp/StatusCodeTab.vue'; import VariableTab from './comp/VariableTab.vue'; diff --git a/frontend/src/components/business/ms-menu/index.vue b/frontend/src/components/business/ms-menu/index.vue index fcb8d9c150..06c24714fe 100644 --- a/frontend/src/components/business/ms-menu/index.vue +++ b/frontend/src/components/business/ms-menu/index.vue @@ -89,6 +89,7 @@ }); } }; + menuTree.value?.forEach((el: RouteRecordRaw | null) => { if (isFind) return; // 节省性能 backtrack(el, [el?.name as string]); @@ -336,6 +337,7 @@ } return nodes; } + return travel(menuTree.value); }; diff --git a/frontend/src/components/business/ms-top-menu/index.vue b/frontend/src/components/business/ms-top-menu/index.vue index 6b82e5ed16..4e7cdad313 100644 --- a/frontend/src/components/business/ms-top-menu/index.vue +++ b/frontend/src/components/business/ms-top-menu/index.vue @@ -79,7 +79,9 @@ (item) => name && item?.name && (name as string).includes(item.name as string) ); } - appStore.setTopMenus(currentParent?.children?.filter((item) => item.meta?.isTopMenu)); + appStore.setTopMenus( + currentParent?.children?.filter((item) => permission.accessRouter(item) && item.meta?.isTopMenu) + ); setCurrentTopMenu(name as string); return; } diff --git a/frontend/src/directive/permission/index.ts b/frontend/src/directive/permission/index.ts index 7258180968..7d93873872 100644 --- a/frontend/src/directive/permission/index.ts +++ b/frontend/src/directive/permission/index.ts @@ -1,22 +1,17 @@ import { DirectiveBinding } from 'vue'; -import { useUserStore } from '@/store'; +import { hasAnyPermission } from '@/utils/permission'; /** - * 权限指令,TODO:权限判定按权限点来 + * 权限指令 * @param el dom 节点 * @param binding vue 绑定的数据 */ function checkPermission(el: HTMLElement, binding: DirectiveBinding) { const { value } = binding; - const userStore = useUserStore(); - const { role } = userStore; - if (Array.isArray(value)) { if (value.length > 0) { - const permissionValues = value; - - const hasPermission = permissionValues.includes(role); + const hasPermission = hasAnyPermission(value); if (!hasPermission && el.parentNode) { el.parentNode.removeChild(el); } diff --git a/frontend/src/enums/routeEnum.ts b/frontend/src/enums/routeEnum.ts index ae07ad64bf..0a40877d28 100644 --- a/frontend/src/enums/routeEnum.ts +++ b/frontend/src/enums/routeEnum.ts @@ -23,7 +23,7 @@ export enum CaseManagementRouteEnum { } export enum PerformanceTestRouteEnum { - PERFORMANCE_TEST = 'performanceTest', + PERFORMANCE_TEST = 'loadTest', } export enum ProjectManagementRouteEnum { @@ -57,7 +57,7 @@ export enum UITestRouteEnum { } export enum WorkbenchRouteEnum { - WORKBENCH = 'workbench', + WORKBENCH = 'workstation', } export enum SettingRouteEnum { diff --git a/frontend/src/hooks/usePermission.ts b/frontend/src/hooks/usePermission.ts index 7ebb304953..29cadbd4ac 100644 --- a/frontend/src/hooks/usePermission.ts +++ b/frontend/src/hooks/usePermission.ts @@ -1,13 +1,15 @@ import { RouteLocationNormalized, RouteRecordRaw } from 'vue-router'; +import { includes } from 'lodash-es'; -import { useUserStore } from '@/store'; +import { hasAnyPermission, hasFirstMenuPermission } from '@/utils/permission'; + +const firstLevelMenu = ['workstation', 'testPlan', 'bugManagement', 'caseManagement', 'apiTest', 'uiTest', 'loadTest']; /** * 用户权限 * @returns 调用方法 */ export default function usePermission() { - const userStore = useUserStore(); return { /** * 是否为允许访问的路由 @@ -15,35 +17,17 @@ export default function usePermission() { * @returns 是否 */ accessRouter(route: RouteLocationNormalized | RouteRecordRaw) { + if (includes(firstLevelMenu, route.name)) { + // 一级菜单 + return hasFirstMenuPermission(route.name as string); + } return ( route.meta?.requiresAuth === false || !route.meta?.roles || route.meta?.roles?.includes('*') || - route.meta?.roles?.includes(userStore.role) + hasAnyPermission(route.meta?.roles || []) ); }, - /** - * 查找第一个允许访问的路由 - * @param _routers 路由数组 - * @param role 用户角色 - * @returns 路由信息 or null - */ - findFirstPermissionRoute(_routers: any, role = 'admin') { - const cloneRouters = [..._routers]; - while (cloneRouters.length) { - const firstElement = cloneRouters.shift(); - if ( - firstElement?.meta?.roles?.find((el: string[]) => { - return el.includes('*') || el.includes(role); - }) - ) - return { name: firstElement.name }; - if (firstElement?.children) { - cloneRouters.push(...firstElement.children); - } - } - return null; - }, // You can add any rules you want }; } diff --git a/frontend/src/models/projectManagement/environmental.ts b/frontend/src/models/projectManagement/environmental.ts index bb98b1b26a..e108b90c8e 100644 --- a/frontend/src/models/projectManagement/environmental.ts +++ b/frontend/src/models/projectManagement/environmental.ts @@ -38,16 +38,16 @@ export interface EnvConfig { dataSource?: DataSourceItem[]; hostConfig?: EnvConfigItem; authConfig?: EnvConfigItem; - preScript?: EnvConfigItem; - postScript?: EnvConfigItem; - assertions?: EnvConfigItem; + preScript?: EnvConfigItem[]; + postScript?: EnvConfigItem[]; + assertions?: EnvConfigItem[]; } export interface EnvDetailItem { id?: string; projectId: string; name: string; config: EnvConfig; - mock?: string; + mock?: boolean; description?: string; } export interface GlobalParamsItem { diff --git a/frontend/src/models/setting/project.ts b/frontend/src/models/setting/project.ts index 18682fb3df..2fea47488f 100644 --- a/frontend/src/models/setting/project.ts +++ b/frontend/src/models/setting/project.ts @@ -13,4 +13,5 @@ export interface ProjectListItem { deleted: boolean; deleteUser: string; enable: boolean; + moduleIds: string[]; } diff --git a/frontend/src/models/user.ts b/frontend/src/models/user.ts index 8c3ba4902c..efa837dc7f 100644 --- a/frontend/src/models/user.ts +++ b/frontend/src/models/user.ts @@ -1,3 +1,5 @@ +import { UserState } from '@/store/modules/user/types'; + // 登录信息 export interface LoginData { username: string; @@ -5,37 +7,11 @@ export interface LoginData { authenticate: string; } -export interface UserRole { - id: string; - createTime: number; - createUser: string; - roleId: string; - sourceId: string; - userId: string; -} - // 登录返回 -export interface LoginRes { +export interface LoginRes extends UserState { csrfToken: string; - createTime: number; - createUser: string; - email: string; - enabled: boolean; - id: string; - language: string; - lastOrganizationId: string; - lastProjectId: string; - name: string; - phone: string; - platformInfo: string; - seleniumServer: string; sessionId: string; - source: string; - updateTime: number; - updateUser: string; - userRolePermissions: UserRole[]; - userRoleRelations: UserRole[]; - userRoles: UserRole[]; + token: string; } // 更新本地执行配置 export interface UpdateLocalConfigParams { @@ -94,23 +70,6 @@ export interface Resource { name: string; license: boolean; } -export interface UserRolePermission { - resource: Resource; - permissions: Permission[]; - type: string; - userRole: UserRole; - userRolePermissions: Permission[]; -} - -export interface UserRoleRelation { - id: string; - userId: string; - roleId: string; - sourceId: string; - organizationId: string; - createTime: number; - createUser: string; -} // 个人信息 export interface PersonalOrganization { id: string; diff --git a/frontend/src/router/routes/modules/projectManagement.ts b/frontend/src/router/routes/modules/projectManagement.ts index ee9d24b9ea..b08ad03079 100644 --- a/frontend/src/router/routes/modules/projectManagement.ts +++ b/frontend/src/router/routes/modules/projectManagement.ts @@ -270,7 +270,7 @@ const ProjectManagement: AppRouteRecordRaw = { component: () => import('@/views/project-management/environmental/index.vue'), meta: { locale: 'menu.projectManagement.environmentManagement', - roles: ['*'], + roles: ['PROJECT_ENVIRONMENT:READ'], isTopMenu: true, }, }, diff --git a/frontend/src/router/routes/modules/setting.ts b/frontend/src/router/routes/modules/setting.ts index 074e813113..ab1a49c0a9 100644 --- a/frontend/src/router/routes/modules/setting.ts +++ b/frontend/src/router/routes/modules/setting.ts @@ -50,7 +50,7 @@ const Setting: AppRouteRecordRaw = { component: () => import('@/views/setting/system/organizationAndProject/index.vue'), meta: { locale: 'menu.settings.system.organizationAndProject', - roles: ['*'], + roles: ['SYSTEM_ORGANIZATION_PROJECT:READ'], isTopMenu: true, }, }, diff --git a/frontend/src/store/modules/app/index.ts b/frontend/src/store/modules/app/index.ts index ec8df73dbc..92c2ece6b3 100644 --- a/frontend/src/store/modules/app/index.ts +++ b/frontend/src/store/modules/app/index.ts @@ -4,6 +4,7 @@ import { cloneDeep } from 'lodash-es'; import type { BreadcrumbItem } from '@/components/business/ms-breadcrumb/types'; +import { getProjectInfo } from '@/api/modules/project-management/basicInfo'; import { getPageConfig } from '@/api/modules/setting/config'; import { getSystemVersion } from '@/api/modules/system'; import { getMenuList } from '@/api/modules/user'; @@ -51,6 +52,7 @@ const useAppStore = defineStore('app', { defaultLoginConfig, defaultPlatformConfig, innerHeight: 0, + currentMenuConfig: [], pageConfig: { ...defaultThemeConfig, ...defaultLoginConfig, @@ -273,6 +275,18 @@ const useAppStore = defineStore('app', { console.log(error); } }, + + /** + * 设置当前项目菜单配置 + */ + async setCurrentMenuConfig() { + try { + const res = await getProjectInfo(this.currentProjectId); + this.currentMenuConfig = res.moduleIds; + } catch (error) { + console.log(error); + } + }, }, persist: { paths: ['currentOrgId', 'currentProjectId', 'pageConfig'], diff --git a/frontend/src/store/modules/app/types.ts b/frontend/src/store/modules/app/types.ts index 3b60bdb7f8..ed39cbf0ce 100644 --- a/frontend/src/store/modules/app/types.ts +++ b/frontend/src/store/modules/app/types.ts @@ -2,6 +2,7 @@ import type { MsFileItem } from '@/components/pure/ms-upload/types'; import type { BreadcrumbItem } from '@/components/business/ms-breadcrumb/types'; import type { LoginConfig, PageConfig, PlatformConfig, ThemeConfig } from '@/models/setting/config'; +import { UserGroupAuthSetting } from '@/models/setting/usergroup'; import type { RouteRecordNormalized, RouteRecordRaw } from 'vue-router'; @@ -35,6 +36,7 @@ export interface AppState { defaultPlatformConfig: PlatformConfig; pageConfig: PageConfig; innerHeight: number; + currentMenuConfig: string[]; } export interface UploadFileTaskState { diff --git a/frontend/src/store/modules/setting/useProjectEnvStore.ts b/frontend/src/store/modules/setting/useProjectEnvStore.ts index 5456dd7bd9..10506e8d98 100644 --- a/frontend/src/store/modules/setting/useProjectEnvStore.ts +++ b/frontend/src/store/modules/setting/useProjectEnvStore.ts @@ -12,7 +12,8 @@ const useProjectEnvStore = defineStore( 'projectEnv', () => { const currentId = ref(ALL_PARAM); // 当前选中的key值 - const currentEnvDetailInfo = ref(); // 当前选中的环境详情 + const currentEnvDetailInfo = ref({ projectId: '', name: '', config: {} }); // 当前选中的环境详情 + const backupEnvDetailInfo = ref({ projectId: '', name: '', config: {} }); // 当前选中的环境详情-备份 const allParamDetailInfo = ref(); // 全局参数详情 const httpNoWarning = ref(true); const getHttpNoWarning = computed(() => httpNoWarning.value); @@ -25,10 +26,6 @@ const useProjectEnvStore = defineStore( function setHttpNoWarning(noWarning: boolean) { httpNoWarning.value = noWarning; } - // 设置环境详情 - function setEnvDetailInfo(item: EnvDetailItem) { - currentEnvDetailInfo.value = item; - } // 设置全局参数 function setAllParamDetailInfo(item: GlobalParams) { allParamDetailInfo.value = item; @@ -39,11 +36,14 @@ const useProjectEnvStore = defineStore( const appStore = useAppStore(); try { if (id === NEW_ENV_PARAM) { - currentEnvDetailInfo.value = undefined; + currentEnvDetailInfo.value = { projectId: appStore.currentProjectId, name: '', config: {} }; + backupEnvDetailInfo.value = { projectId: appStore.currentProjectId, name: '', config: {} }; } else if (id === ALL_PARAM) { allParamDetailInfo.value = await getGlobalParamDetail(appStore.currentProjectId); } else if (id !== ALL_PARAM && id) { - currentEnvDetailInfo.value = await getDetailEnv(id); + const tmpObj = await getDetailEnv(id); + currentEnvDetailInfo.value = tmpObj; + backupEnvDetailInfo.value = JSON.parse(JSON.stringify(tmpObj)); } } catch (e) { // eslint-disable-next-line no-console @@ -56,10 +56,11 @@ const useProjectEnvStore = defineStore( getHttpNoWarning, httpNoWarning, allParamDetailInfo, + currentEnvDetailInfo, + backupEnvDetailInfo, groupLength, setCurrentId, setHttpNoWarning, - setEnvDetailInfo, setAllParamDetailInfo, initEnvDetail, }; diff --git a/frontend/src/store/modules/user/index.ts b/frontend/src/store/modules/user/index.ts index 13be7c83b0..fe4424d2ea 100644 --- a/frontend/src/store/modules/user/index.ts +++ b/frontend/src/store/modules/user/index.ts @@ -4,13 +4,14 @@ import { isLogin as userIsLogin, login as userLogin, logout as userLogout } from import { useI18n } from '@/hooks/useI18n'; import { getHashParameters } from '@/utils'; import { clearToken, setToken } from '@/utils/auth'; +import { composePermissions } from '@/utils/permission'; import { removeRouteListener } from '@/utils/route-listener'; import type { LoginData } from '@/models/user'; import useAppStore from '../app'; import useLicenseStore from '../setting/license'; -import type { UserState } from './types'; +import { UserState } from './types'; const useUserStore = defineStore('user', { // 开启数据持久化 @@ -32,12 +33,29 @@ const useUserStore = defineStore('user', { id: undefined, certification: undefined, role: '', + userRolePermissions: [], }), getters: { userInfo(state: UserState): UserState { return { ...state }; }, + isAdmin(state: UserState): boolean { + if (!state.userRolePermissions) return false; + return state.userRolePermissions.findIndex((ur) => ur.userRole.id === 'admin') > -1; + }, + currentRole(state: UserState): { + projectPermissions: string[]; + orgPermissions: string[]; + systemPermissions: string[]; + } { + const appStore = useAppStore(); + return { + projectPermissions: composePermissions(state.userRolePermissions || [], 'PROJECT', appStore.currentProjectId), + orgPermissions: composePermissions(state.userRolePermissions || [], 'ORGANIZATION', appStore.currentOrgId), + systemPermissions: composePermissions(state.userRolePermissions || [], 'SYSTEM', 'global'), + }; + }, }, actions: { @@ -51,7 +69,6 @@ const useUserStore = defineStore('user', { setInfo(partial: Partial) { this.$patch(partial); }, - // 重置用户信息 resetInfo() { this.$reset(); diff --git a/frontend/src/store/modules/user/types.ts b/frontend/src/store/modules/user/types.ts index bac6ec8df3..8a0bec53ad 100644 --- a/frontend/src/store/modules/user/types.ts +++ b/frontend/src/store/modules/user/types.ts @@ -1,4 +1,25 @@ export type RoleType = '' | '*' | 'admin' | 'user'; +export type SystemScopeType = 'PROJECT' | 'ORGANIZATION' | 'SYSTEM'; + +export interface UserRole { + createTime: number; + updateTime: number; + createUser: string; + description?: string; + id: string; + name: string; + scopeId: string; // 项目/组织/系统 id + type: SystemScopeType; +} +export interface permissionsItem { + id: string; + permissionId: string; + roleId: string; +} +export interface UserRolePermissions { + userRole: UserRole; + userRolePermissions: permissionsItem[]; +} export interface UserState { name?: string; avatar?: string; @@ -18,4 +39,5 @@ export interface UserState { role: RoleType; lastOrganizationId?: string; lastProjectId?: string; + userRolePermissions?: UserRolePermissions[]; } diff --git a/frontend/src/utils/permission.ts b/frontend/src/utils/permission.ts new file mode 100644 index 0000000000..b9ae8faa8a --- /dev/null +++ b/frontend/src/utils/permission.ts @@ -0,0 +1,67 @@ +import { useAppStore, useUserStore } from '@/store'; +import { SystemScopeType, UserRole, UserRolePermissions } from '@/store/modules/user/types'; + +export function hasPermission(permission: string, typeList: string[]) { + const userStore = useUserStore(); + if (userStore.isAdmin) { + return true; + } + const { projectPermissions, orgPermissions, systemPermissions } = userStore.currentRole; + + if (typeList.includes('PROJECT') && projectPermissions.includes(permission)) { + return true; + } + if (typeList.includes('ORGANIZATION') && orgPermissions.includes(permission)) { + return true; + } + if (typeList.includes('SYSTEM') && systemPermissions.includes(permission)) { + return true; + } + return false; +} + +// 判断是否有权限 +export function hasAnyPermission(permissions: string[], typeList = ['PROJECT', 'ORGANIZATION', 'SYSTEM']) { + return permissions.some((permission) => hasPermission(permission, typeList)); +} + +function filterProject(role: UserRole, id: string) { + return role && role.type === 'PROJECT' && role.scopeId === id; +} +function filterOrganization(role: UserRole, id: string) { + return role && role.type === 'ORGANIZATION' && role.scopeId === id; +} +function filterSystem(role: UserRole, id: string) { + return role && role.type === 'SYSTEM' && role.scopeId === id; +} + +export function composePermissions(userRolePermissions: UserRolePermissions[], type: SystemScopeType, id: string) { + let func: (role: UserRole, val: string) => boolean; + switch (type) { + case 'PROJECT': + func = filterProject; + break; + case 'ORGANIZATION': + func = filterOrganization; + break; + default: + func = filterSystem; + break; + } + return userRolePermissions + .filter((ur) => func(ur.userRole, id)) + .flatMap((role) => role.userRolePermissions) + .map((g) => g.permissionId); +} + +// 判断当前一级菜单是否有权限 +export function hasFirstMenuPermission(menuName: string) { + const userStore = useUserStore(); + const appStore = useAppStore(); + if (userStore.isAdmin || menuName === 'setting' || menuName === 'projectManagement') { + // 如果是超级管理员,或者是系统设置菜单,或者是项目菜单,都有权限 + return true; + } + const { currentMenuConfig } = appStore; + return currentMenuConfig.includes(menuName); +} diff --git a/frontend/src/views/project-management/environmental/components/EnvParamBox.vue b/frontend/src/views/project-management/environmental/components/EnvParamBox.vue index d8fcfce3bf..97f7ad4add 100644 --- a/frontend/src/views/project-management/environmental/components/EnvParamBox.vue +++ b/frontend/src/views/project-management/environmental/components/EnvParamBox.vue @@ -15,6 +15,7 @@ :max-length="255" class="w-[732px]" :placeholder="t('project.environmental.envNamePlaceholder')" + @blur="store.currentEnvDetailInfo.name = form.name" /> @@ -32,20 +33,21 @@ - diff --git a/frontend/src/views/project-management/environmental/components/envParams/AssertTab.vue b/frontend/src/views/project-management/environmental/components/envParams/AssertTab.vue index 1176ec86ce..9f987dbe5b 100644 --- a/frontend/src/views/project-management/environmental/components/envParams/AssertTab.vue +++ b/frontend/src/views/project-management/environmental/components/envParams/AssertTab.vue @@ -1,15 +1,20 @@ diff --git a/frontend/src/views/project-management/environmental/components/envParams/DatabaseTab.vue b/frontend/src/views/project-management/environmental/components/envParams/DatabaseTab.vue index 764c3e6c09..dc46a3bb35 100644 --- a/frontend/src/views/project-management/environmental/components/envParams/DatabaseTab.vue +++ b/frontend/src/views/project-management/environmental/components/envParams/DatabaseTab.vue @@ -49,9 +49,14 @@ import { TableKeyEnum } from '@/enums/tableEnum'; const { t } = useI18n(); - const store = useProjectEnvStore(); + const innerParam = computed({ + get: () => (store.currentEnvDetailInfo.config.dataSource || []) as DataSourceItem[], + set: (value: DataSourceItem[] | undefined) => { + store.currentEnvDetailInfo.config.dataSource = value; + }, + }); const keyword = ref(''); const tableStore = useTableStore(); const addVisible = ref(false); @@ -156,21 +161,8 @@ addVisible.value = true; }; const fetchData = () => {}; - const handleNoWarning = () => { - store.setHttpNoWarning(false); - }; const initData = () => { - propsRes.value.data = [ - { - id: '1', - name: 'test', - desc: 'test', - url: 'test', - username: 'test', - poolMax: 'test', - timeout: 'test', - }, - ]; + propsRes.value.data = innerParam.value; }; onMounted(() => { initData(); diff --git a/frontend/src/views/project-management/environmental/components/envParams/DisplayTab.vue b/frontend/src/views/project-management/environmental/components/envParams/DisplayTab.vue deleted file mode 100644 index a7b4987b14..0000000000 --- a/frontend/src/views/project-management/environmental/components/envParams/DisplayTab.vue +++ /dev/null @@ -1,13 +0,0 @@ - - - - - diff --git a/frontend/src/views/project-management/environmental/components/envParams/EnvParamsTab.vue b/frontend/src/views/project-management/environmental/components/envParams/EnvParamsTab.vue index 59cefd4912..7d6eb8bc08 100644 --- a/frontend/src/views/project-management/environmental/components/envParams/EnvParamsTab.vue +++ b/frontend/src/views/project-management/environmental/components/envParams/EnvParamsTab.vue @@ -1,13 +1,22 @@ diff --git a/frontend/src/views/project-management/environmental/components/envParams/HostTab.vue b/frontend/src/views/project-management/environmental/components/envParams/HostTab.vue index 5f64a2d96d..998c9c741b 100644 --- a/frontend/src/views/project-management/environmental/components/envParams/HostTab.vue +++ b/frontend/src/views/project-management/environmental/components/envParams/HostTab.vue @@ -1,7 +1,7 @@ diff --git a/frontend/src/views/project-management/environmental/components/envParams/PreTab.vue b/frontend/src/views/project-management/environmental/components/envParams/PreTab.vue index a7b4987b14..7c9153da20 100644 --- a/frontend/src/views/project-management/environmental/components/envParams/PreTab.vue +++ b/frontend/src/views/project-management/environmental/components/envParams/PreTab.vue @@ -1,13 +1,20 @@ diff --git a/frontend/src/views/setting/system/organizationAndProject/components/systemOrganization.vue b/frontend/src/views/setting/system/organizationAndProject/components/systemOrganization.vue index 2fb2737447..8bed88152b 100644 --- a/frontend/src/views/setting/system/organizationAndProject/components/systemOrganization.vue +++ b/frontend/src/views/setting/system/organizationAndProject/components/systemOrganization.vue @@ -20,17 +20,33 @@ diff --git a/frontend/src/views/setting/system/organizationAndProject/components/systemProject.vue b/frontend/src/views/setting/system/organizationAndProject/components/systemProject.vue index a669a813c2..aa515522d8 100644 --- a/frontend/src/views/setting/system/organizationAndProject/components/systemProject.vue +++ b/frontend/src/views/setting/system/organizationAndProject/components/systemProject.vue @@ -17,17 +17,37 @@