diff --git a/frontend/src/api/modules/case-management/featureCase.ts b/frontend/src/api/modules/case-management/featureCase.ts index 8fcdcff921..b820874d56 100644 --- a/frontend/src/api/modules/case-management/featureCase.ts +++ b/frontend/src/api/modules/case-management/featureCase.ts @@ -5,6 +5,7 @@ import { AddDemandUrl, AddDependOnRelationUrl, AssociatedDebuggerUrl, + associatedProjectOptionsUrl, BatchAssociationDemandUrl, BatchCopyCaseUrl, BatchDeleteCaseUrl, @@ -94,6 +95,7 @@ import type { UpdateModule, } from '@/models/caseManagement/featureCase'; import type { CommonList, ModuleTreeNode, MoveModules, TableQueryParams } from '@/models/common'; +import { ProjectListItem } from '@/models/setting/project'; // 获取模块树 export function getCaseModuleTree(params: TableQueryParams) { @@ -421,5 +423,9 @@ export function dragSort(data: DragCase) { export function getChangeHistoryList(data: TableQueryParams) { return MSR.post>({ url: getChangeHistoryListUrl, data }); } +// 获取已关联缺陷列表 +export function getAssociatedProjectOptions(orgId: string, module: string) { + return MSR.get({ url: `${associatedProjectOptionsUrl}/${orgId}/${module}` }); +} export default {}; diff --git a/frontend/src/api/requrls/case-management/featureCase.ts b/frontend/src/api/requrls/case-management/featureCase.ts index 43744965e1..856e93f6be 100644 --- a/frontend/src/api/requrls/case-management/featureCase.ts +++ b/frontend/src/api/requrls/case-management/featureCase.ts @@ -149,3 +149,5 @@ export const dragSortUrl = '/functional/case/edit/pos'; export const getChangeHistoryListUrl = '/functional/case/operation-history'; // 取消关联用例 export const cancelDisassociate = '/functional/case/test/disassociate/case'; +// 关联用例关联功能用例项目下拉 +export const associatedProjectOptionsUrl = '/project/list/options'; diff --git a/frontend/src/components/business/ms-assertion/comp/ResponseBodyTab.vue b/frontend/src/components/business/ms-assertion/comp/ResponseBodyTab.vue index 82683618ca..2318086b14 100644 --- a/frontend/src/components/business/ms-assertion/comp/ResponseBodyTab.vue +++ b/frontend/src/components/business/ms-assertion/comp/ResponseBodyTab.vue @@ -363,7 +363,7 @@ import { TableColumnData, TableData } from '@arco-design/web-vue'; import { cloneDeep } from 'lodash-es'; - import { statusCodeOptions } from '@/components/pure/ms-advance-filter'; + import { EQUAL, statusCodeOptions } from '@/components/pure/ms-advance-filter'; import { ActionsItem } from '@/components/pure/ms-table-more-action/types'; import { TableOperationColumn } from '@/components/business/ms-user-group-comp/authTable.vue'; import fastExtraction from '@/views/api-test/components/fastExtraction/index.vue'; @@ -513,6 +513,7 @@ variableType: RequestExtractEnvType.TEMPORARY, extractScope: RequestExtractScope.BODY, expression: '', + condition: EQUAL.value, extractType: RequestExtractExpressionEnum.JSON_PATH, expressionMatchingRule: RequestExtractExpressionRuleType.EXPRESSION, resultMatchingRule: RequestExtractResultMatchingRule.RANDOM, diff --git a/frontend/src/components/business/ms-case-associate/index.vue b/frontend/src/components/business/ms-case-associate/index.vue index cb83e2d7be..f950ee5515 100644 --- a/frontend/src/components/business/ms-case-associate/index.vue +++ b/frontend/src/components/business/ms-case-associate/index.vue @@ -24,11 +24,24 @@
- +
+ + + + + {{ item.name }} + + + +
{{ item }} @@ -159,13 +172,15 @@ import type { MsTreeNodeData } from '@/components/business/ms-tree/types'; import caseLevel from './caseLevel.vue'; - import { getCustomFieldsTable } from '@/api/modules/case-management/featureCase'; + import { getAssociatedProjectOptions, getCustomFieldsTable } from '@/api/modules/case-management/featureCase'; import { useI18n } from '@/hooks/useI18n'; import useAppStore from '@/store/modules/app'; import { mapTree } from '@/utils'; import type { CaseManagementTable } from '@/models/caseManagement/featureCase'; import type { CommonList, ModuleTreeNode, TableQueryParams } from '@/models/common'; + import type { ProjectListItem } from '@/models/setting/project'; + import { CaseLinkEnum } from '@/enums/caseEnum'; import { CaseManagementRouteEnum } from '@/enums/routeEnum'; import type { CaseLevel } from './types'; @@ -185,7 +200,7 @@ getTableFunc: (params: TableQueryParams) => Promise>; // 获取表请求函数 tableParams?: TableQueryParams; // 查询表格的额外的参数 okButtonDisabled?: boolean; // 确认按钮是否禁用 - currentSelectCase: string | number | Record | undefined; // 当前选中的用例类型 + currentSelectCase: keyof typeof CaseLinkEnum; // 当前选中的用例类型 moduleOptions?: { label: string; value: string }[]; // 功能模块对应用例下拉 confirmLoading: boolean; associatedIds: string[]; // 已关联用例id集合用于去重已关联 @@ -239,7 +254,7 @@ } const innerVisible = useVModel(props, 'visible', emit); - const innerProject = useVModel(props, 'projectId', emit); + const innerProject = ref(props.projectId); const protocolType = ref('HTTP'); // 协议类型 const protocolOptions = ref(['HTTP']); @@ -323,6 +338,7 @@ const keyword = ref(''); const version = ref(''); + const projectList = ref([]); function getCaseLevelColumn() { if (!props.isHiddenCaseLevel) { @@ -576,6 +592,17 @@ } } + async function initProjectList(setDefault: boolean) { + try { + projectList.value = await getAssociatedProjectOptions(appStore.currentOrgId, caseType.value); + if (setDefault) { + innerProject.value = projectList.value[0].id; + } + } catch (error) { + console.log(error); + } + } + function searchCase() { getLoadListParams(); loadList(); @@ -631,10 +658,14 @@ () => props.visible, (val) => { if (val) { - resetSelector(); - initModules(); - searchCase(); - initFilter(); + if (!props.hideProjectSelect) { + initProjectList(true); + } else { + resetSelector(); + initModules(); + searchCase(); + initFilter(); + } } else { cancel(); } @@ -655,10 +686,12 @@ watch( () => innerProject.value, - () => { - if (innerVisible.value) { - searchCase(); + (val) => { + if (val) { + resetSelector(); initModules(); + searchCase(); + initFilter(); } } ); diff --git a/frontend/src/components/business/ms-common-script/utils.ts b/frontend/src/components/business/ms-common-script/utils.ts index 5186ffbd5a..90457ac2c7 100644 --- a/frontend/src/components/business/ms-common-script/utils.ts +++ b/frontend/src/components/business/ms-common-script/utils.ts @@ -128,7 +128,7 @@ function replaceRestParams(path: string, restMap: Record) { } // 返回最终groovyCode 代码模板片段 -function _groovyCodeTemplate(obj: Record) { +export function _groovyCodeTemplate(obj: Record) { const { requestUrl, requestMethod, headers, body } = obj; const params = `[ 'url': '${requestUrl}', diff --git a/frontend/src/components/business/ms-user-selector/index.vue b/frontend/src/components/business/ms-user-selector/index.vue index 0bd72397e6..f778c1ea41 100644 --- a/frontend/src/components/business/ms-user-selector/index.vue +++ b/frontend/src/components/business/ms-user-selector/index.vue @@ -26,8 +26,12 @@ import MsSelect from '@/components/business/ms-select/index'; + import { useUserStore } from '@/store'; + import initOptionsFunc, { UserRequestTypeEnum } from './utils'; + const userStore = useUserStore(); + defineOptions({ name: 'MsUserSelector' }); export interface MsUserSelectorOption { diff --git a/frontend/src/directive/index.ts b/frontend/src/directive/index.ts index 1cc1089e68..52593cc4bb 100644 --- a/frontend/src/directive/index.ts +++ b/frontend/src/directive/index.ts @@ -2,12 +2,14 @@ import { App } from 'vue'; import outerClick from './outerClick'; import permission from './permission'; +import validateExpiration from './validateExpiration'; import validateLicense from './validateLicense'; export default { install(Vue: App) { Vue.directive('permission', permission); Vue.directive('xpack', validateLicense); + Vue.directive('expire', validateExpiration); Vue.directive('outer', outerClick); }, }; diff --git a/frontend/src/directive/validateExpiration/index.ts b/frontend/src/directive/validateExpiration/index.ts new file mode 100644 index 0000000000..a782051f44 --- /dev/null +++ b/frontend/src/directive/validateExpiration/index.ts @@ -0,0 +1,26 @@ +import { useAppStore } from '@/store'; +import useLicenseStore from '@/store/modules/setting/license'; + +/** + * 权限指令,TODO:校验license + * @param el dom 节点 + */ + +function checkHasLicenseExpiration(el: HTMLElement) { + const licenseStore = useLicenseStore(); + const appStore = useAppStore(); + const isValid = licenseStore.expiredDuring && appStore.packageType === 'enterprise'; + + if (!isValid && el.parentNode) { + el.parentNode.removeChild(el); + } +} + +export default { + mounted(el: HTMLElement) { + checkHasLicenseExpiration(el); + }, + updated(el: HTMLElement) { + checkHasLicenseExpiration(el); + }, +}; diff --git a/frontend/src/enums/caseEnum.ts b/frontend/src/enums/caseEnum.ts index 8a091ab6ca..d2c29652f6 100644 --- a/frontend/src/enums/caseEnum.ts +++ b/frontend/src/enums/caseEnum.ts @@ -20,4 +20,12 @@ export enum LastExecuteResults { FAILED = 'FAILED', } +export enum CaseLinkEnum { + API = 'API', + SCENARIO = 'SCENARIO', + UI = 'UI', + PERFORMANCE = 'PERFORMANCE', + FUNCTIONAL = 'FUNCTIONAL', +} + export default {}; diff --git a/frontend/src/store/modules/setting/license.ts b/frontend/src/store/modules/setting/license.ts index 2de494d5d8..02c7319033 100644 --- a/frontend/src/store/modules/setting/license.ts +++ b/frontend/src/store/modules/setting/license.ts @@ -1,11 +1,14 @@ import { defineStore } from 'pinia'; +import dayjs from 'dayjs'; import { getLicenseInfo } from '@/api/modules/setting/authorizedManagement'; const useLicenseStore = defineStore('license', { persist: true, - state: (): { status: string | null } => ({ + state: (): { status: string | null; expiredDuring: boolean; expiredDays: number } => ({ status: '', + expiredDuring: false, + expiredDays: 0, }), actions: { setLicenseStatus(status: string) { @@ -17,6 +20,21 @@ const useLicenseStore = defineStore('license', { hasLicense() { return this.status && this.status === 'valid'; }, + getExpirationTime(resTime: string) { + const today = Date.now(); + const startDate = dayjs(today).format('YYYY-MM-DD'); + const endDate = dayjs(resTime); + + const daysDifference = endDate.diff(startDate, 'day'); + this.expiredDays = daysDifference; + if (daysDifference <= 30 && daysDifference >= 0) { + this.expiredDuring = true; + } else if (daysDifference <= 0 && daysDifference >= -30) { + this.expiredDuring = true; + } else { + this.expiredDuring = false; + } + }, // license校验 async getValidateLicense() { try { @@ -25,6 +43,8 @@ const useLicenseStore = defineStore('license', { return; } this.setLicenseStatus(result.status); + // 计算license时间 + this.getExpirationTime(result.license.expired); } catch (error) { console.log(error); } diff --git a/frontend/src/views/api-test/components/requestComposition/response/result/tiledDisplay.vue b/frontend/src/views/api-test/components/requestComposition/response/result/tiledDisplay.vue index cd83e36a67..ac4b62f5ee 100644 --- a/frontend/src/views/api-test/components/requestComposition/response/result/tiledDisplay.vue +++ b/frontend/src/views/api-test/components/requestComposition/response/result/tiledDisplay.vue @@ -30,7 +30,7 @@
- +
@@ -92,9 +92,12 @@ } } const { copy, isSupported } = useClipboard({ legacy: true }); + + const resBodyRef = ref(); function copyScript() { + const encodingFormatValue = resBodyRef.value.responseEditorRef.getEncodingCode(); if (isSupported) { - copy(props.requestResult?.responseResult.body || ''); + copy(encodingFormatValue || ''); Message.success(t('common.copySuccess')); } else { Message.warning(t('apiTestDebug.copyNotSupport')); diff --git a/frontend/src/views/bug-management/components/bug-detail-drawer.vue b/frontend/src/views/bug-management/components/bug-detail-drawer.vue index 3eb7c54e65..d979d8f64d 100644 --- a/frontend/src/views/bug-management/components/bug-detail-drawer.vue +++ b/frontend/src/views/bug-management/components/bug-detail-drawer.vue @@ -70,7 +70,7 @@ /> {{ t('caseManagement.featureCase.follow') }} - +
diff --git a/frontend/src/views/bug-management/components/bugCaseTab.vue b/frontend/src/views/bug-management/components/bugCaseTab.vue index 39ae02c103..f17d684b03 100644 --- a/frontend/src/views/bug-management/components/bugCaseTab.vue +++ b/frontend/src/views/bug-management/components/bugCaseTab.vue @@ -111,6 +111,7 @@ import { hasAnyPermission } from '@/utils/permission'; import type { TableQueryParams } from '@/models/common'; + import { CaseLinkEnum } from '@/enums/caseEnum'; import { CaseManagementRouteEnum } from '@/enums/routeEnum'; import Message from '@arco-design/web-vue/es/message'; @@ -201,7 +202,7 @@ const associatedIds = ref([]); - const currentSelectCase = ref(''); + const currentSelectCase = ref('FUNCTIONAL'); const modulesTreeParams = ref({}); @@ -233,7 +234,12 @@ } } - const caseTypeOptions = ref<{ label: string; value: string }[]>([]); + const caseTypeOptions = ref<{ label: string; value: string }[]>([ + { + label: 'menu.caseManagement.featureCase', + value: 'FUNCTIONAL', + }, + ]); const modulesCount = ref>({}); @@ -255,25 +261,6 @@ } } - const moduleMaps: Record = { - caseManagement: [ - { - value: 'FUNCTIONAL', - label: t('menu.caseManagement.featureCase'), - }, - ], - }; - - async function getEnabledModules() { - const result = await postTabletList({ projectId: currentProjectId.value }); - const caseArr = result.filter((item) => Object.keys(moduleMaps).includes(item.module)); - caseArr.forEach((item: any) => { - const currentModule = moduleMaps[item.module]; - caseTypeOptions.value.push(...currentModule); - }); - currentSelectCase.value = caseTypeOptions.value[0].value; - } - async function searchCase() { setKeyword(keyword.value); setLoadListParams({ @@ -300,14 +287,12 @@ } onMounted(async () => { - getEnabledModules(); getFetch(); }); watch( () => props.bugId, () => { - getEnabledModules(); getFetch(); } ); diff --git a/frontend/src/views/bug-management/edit.vue b/frontend/src/views/bug-management/edit.vue index 00af559add..a568ecfd71 100644 --- a/frontend/src/views/bug-management/edit.vue +++ b/frontend/src/views/bug-management/edit.vue @@ -803,7 +803,10 @@ function renameCopyBug() { if (isCopy.value) { - form.value.title = `copy_${form.value.title}`; + const copyName = `copy_${form.value.title}`; + if (copyName.length > 255) { + form.value.title = copyName.slice(0, 255); + } } } diff --git a/frontend/src/views/case-management/caseManagementFeature/components/caseDetailDrawer.vue b/frontend/src/views/case-management/caseManagementFeature/components/caseDetailDrawer.vue index 4977d90318..41e7c8d3f0 100644 --- a/frontend/src/views/case-management/caseManagementFeature/components/caseDetailDrawer.vue +++ b/frontend/src/views/case-management/caseManagementFeature/components/caseDetailDrawer.vue @@ -63,7 +63,7 @@ /> {{ t('caseManagement.featureCase.follow') }} - +
@@ -238,7 +238,7 @@ diff --git a/frontend/src/views/case-management/caseReview/components/create/associateDrawer.vue b/frontend/src/views/case-management/caseReview/components/create/associateDrawer.vue index da0365fa17..33c24266fc 100644 --- a/frontend/src/views/case-management/caseReview/components/create/associateDrawer.vue +++ b/frontend/src/views/case-management/caseReview/components/create/associateDrawer.vue @@ -88,6 +88,7 @@ import useAppStore from '@/store/modules/app'; import { BaseAssociateCaseRequest } from '@/models/caseManagement/caseReview'; + import { CaseLinkEnum } from '@/enums/caseEnum'; import { ProjectManagementRouteEnum } from '@/enums/routeEnum'; const props = defineProps<{ @@ -142,7 +143,7 @@ } } - const currentSelectCase = ref | undefined>(''); + const currentSelectCase = ref('FUNCTIONAL'); // const associatedIds = useVModel(props, 'associatedIds', emit); const confirmLoading = ref(false); diff --git a/frontend/src/views/project-management/commonScript/utils.ts b/frontend/src/views/project-management/commonScript/utils.ts deleted file mode 100644 index ac08896072..0000000000 --- a/frontend/src/views/project-management/commonScript/utils.ts +++ /dev/null @@ -1,527 +0,0 @@ -import { Language, LanguageEnum } from '@/components/pure/ms-code-editor/types'; - -import { useI18n } from '@/hooks/useI18n'; - -import type { CommonScriptMenu } from '@/models/projectManagement/commonScript'; - -const { t } = useI18n(); - -export const SCRIPT_MENU: CommonScriptMenu[] = [ - { - title: t('project.code_segment.importApiTest'), - value: 'api_definition', - command: 'api_definition', - }, - { - title: t('project.code_segment.newApiTest'), - value: 'new_api_request', - command: 'new_api_request', - }, - { - title: t('project.processor.codeTemplateGetVariable'), - value: 'vars.get("variable_name")', - }, - { - title: t('project.processor.codeTemplateSetVariable'), - value: 'vars.put("variable_name", "variable_value")', - }, - { - title: t('project.processor.codeTemplateGetResponseHeader'), - value: 'prev.getResponseHeaders()', - }, - { - title: t('project.processor.codeTemplateGetResponseCode'), - value: 'prev.getResponseCode()', - }, - { - title: t('project.processor.codeTemplateGetResponseResult'), - value: 'prev.getResponseDataAsString()', - }, - { - title: t('project.processor.paramEnvironmentSetGlobalVariable'), - value: `vars.put(\${__metersphere_env_id}+"key","value");\nvars.put("key","value");`, - }, - { - title: t('project.processor.insertPublicScript'), - value: 'custom_function', - command: 'custom_function', - }, - { - title: t('project.processor.terminationTest'), - value: 'api_stop', - command: 'api_stop', - }, -]; - -// 处理groovyCode 请求头 -function getGroovyHeaders(requestHeaders: Record) { - let headers = '['; - let index = 1; - // for (const [k, v] of requestHeaders) { - // if (index !== 1) { - // headers += ','; - // } - // // 拼装 - // headers += `'${k}':'${v}'`; - // index++; - // } - requestHeaders.forEach(([k, v]: any[]) => { - if (index !== 1) { - headers += ','; - } - headers += `'${k}':'${v}'`; - index++; - }); - headers += ']'; - return headers; -} -// 解析请求url -function getRequestPath(requestArgs: any, requestPath: string) { - if (requestArgs.size > 0) { - requestPath += '?'; - let index = 1; - requestArgs.forEach(([k, v]: any[]) => { - if (index !== 1) { - requestPath += '&'; - } - requestPath = `${requestPath + k}=${v}`; - index++; - }); - } - return requestPath; -} -// 处理mockPath -function getMockPath(domain: string, port: string, socket: string) { - if (domain === socket || !port) { - return ''; - } - const str = `${domain}:${port}`; - // 获取socket之后的路径 - return socket.substring(str.length); -} - -// 处理请求参数 -function replaceRestParams(path: string, restMap: Map) { - if (!path) { - return path; - } - let arr: any[] | null = path.match(/{([\w]+)}/g); - if (Array.isArray(arr) && arr.length > 0) { - arr = Array.from(new Set(arr)); - arr.forEach((str) => { - try { - const temp = str.substr(1); - const param = temp.substring(0, temp.length - 1); - if (str && restMap.has(param)) { - path = path.replace(new RegExp(str, 'g'), restMap.get(param) || ''); - } - } catch (e) { - // nothing - } - }); - } - return path; -} - -// 返回最终groovyCode 代码模板片段 -function _groovyCodeTemplate(obj: Record) { - const { requestUrl, requestMethod, headers, body } = obj; - const params = `[ - 'url': '${requestUrl}', - 'method': '${requestMethod}', // POST/GET - 'headers': ${headers}, // 请求headers 例:{'Content-type':'application/json'} - 'data': ${body} // 参数 - ]`; - return `import groovy.json.JsonOutput -import groovy.json.JsonSlurper - -def params = ${params} -def headers = params['headers'] -// json数据 -def data = params['data'] -def conn = new URL(params['url']).openConnection() -conn.setRequestMethod(params['method']) -if (headers) { - headers.each { - k,v -> conn.setRequestProperty(k, v); - } -} -if (data) { - // 输出请求参数 - log.info(data) - conn.doOutput = true - def writer = new OutputStreamWriter(conn.outputStream) - writer.write(data) - writer.flush() - writer.close() -} -log.info(conn.content.text) -`; -} - -// 处理groovyCode语言 -function groovyCode(requestObj: Record) { - const { - requestHeaders = new Map(), - requestBody = '', - domain = '', - port = '', - requestMethod = '', - host = '', - protocol = '', - requestArguments = new Map(), - requestRest = new Map(), - requestBodyKvs = new Map(), - bodyType, - } = requestObj; - - let { requestPath = '' } = requestObj; - let requestUrl = ''; - if (requestMethod.toLowerCase() === 'get' && requestBodyKvs) { - // 如果是get方法要将kv值加入argument中 - requestBodyKvs.forEach(([k, v]: any[]) => { - requestArguments.set(k, v); - }); - } - requestPath = getRequestPath(requestArguments, requestPath); - const path = getMockPath(domain, port, host); - requestPath = path + replaceRestParams(requestPath, requestRest); - if (protocol && host && requestPath) { - requestUrl = `${protocol}://${domain}${port ? `:${port}` : ''}${requestPath}`; - } - let body = JSON.stringify(requestBody); - if (requestMethod === 'POST' && bodyType === 'kvs') { - body = '"'; - - requestBodyKvs.forEach(([k, v]: any[]) => { - if (body !== '"') { - body += '&'; - } - body += `${k}=${v}`; - }); - body += '"'; - } - - if (bodyType && bodyType.toUpperCase() === 'RAW') { - requestHeaders.set('Content-type', 'text/plain'); - } - const headers = getGroovyHeaders(requestHeaders); - const obj = { requestUrl, requestMethod, headers, body }; - return _groovyCodeTemplate(obj); -} - -// 获取请求头 -function getHeaders(requestHeaders: Map) { - let headers = '{'; - let index = 1; - requestHeaders.forEach(([k, v]) => { - if (index !== 1) { - headers += ','; - } - // 拼装 - headers += `'${k}':'${v}'`; - index++; - }); - headers += '}'; - return headers; -} -// 获取pythonCode 模板 -function _pythonCodeTemplate(obj: Record) { - const { requestBodyKvs, requestPath, requestMethod, connType, domain, port } = obj; - let { headers } = obj; - let reqBody = obj.requestBody; - if (requestMethod.toLowerCase() === 'post' && obj.bodyType === 'kvs' && obj.requestBodyKvs) { - reqBody = 'urllib.urlencode({'; - requestBodyKvs.forEach(([k, v]: any[]) => { - reqBody += `'${k}':'${v}'`; - }); - reqBody += `})`; - if (headers === '{}') { - headers = "{'Content-type': 'application/x-www-form-urlencoded', 'Accept': 'text/plain'}"; - } - } - - const host = domain + (port ? `:${port}` : ''); - - return `import httplib,urllib -params = ${reqBody} #例 {'username':'test'} -headers = ${headers} #例 {'Content-Type':'application/json'} 或 {'Content-type': 'application/x-www-form-urlencoded', 'Accept': 'text/plain'} -host = '${host}' -path = '${requestPath}' -method = '${requestMethod}' # POST/GET - -conn = httplib.${connType}(host) -conn.request(method, path, params, headers) -res = conn.getresponse() -data = unicode(res.read(), 'utf-8') -log.info(data) -`; -} - -// 处理pythonCode语言 -function pythonCode(requestObj: Record) { - const { - requestHeaders = new Map(), - requestMethod = '', - host = '', - domain = '', - port = '', - protocol = 'http', - requestArguments = new Map(), - requestBodyKvs = new Map(), - bodyType, - requestRest = new Map(), - } = requestObj; - let { requestBody = '', requestPath = '/' } = requestObj; - let connType = 'HTTPConnection'; - if (protocol === 'https') { - connType = 'HTTPSConnection'; - } - const headers = getHeaders(requestHeaders); - requestBody = requestBody ? JSON.stringify(requestBody) : '{}'; - if (requestMethod.toLowerCase() === 'get' && requestBodyKvs) { - requestBodyKvs.forEach(([k, v]: any[]) => { - requestArguments.set(k, v); - }); - } - requestPath = getRequestPath(requestArguments, requestPath); - const path = getMockPath(domain, port, host); - requestPath = path + replaceRestParams(requestPath, requestRest); - const obj = { requestBody, headers, requestPath, requestMethod, requestBodyKvs, bodyType, connType, domain, port }; - return _pythonCodeTemplate(obj); -} - -// 获取javaBeanshell代码模板 -function _beanshellTemplate(obj: Record) { - const { - requestHeaders = new Map(), - requestBodyKvs = new Map(), - bodyType = '', - requestMethod = 'GET', - protocol = 'http', - requestArguments = new Map(), - domain = '', - host = '', - port = '', - requestRest = new Map(), - } = obj; - let { requestPath = '/', requestBody = '' } = obj; - - const path = getMockPath(domain, port, host); - requestPath = path + replaceRestParams(requestPath, requestRest); - let uri = `new URIBuilder() - .setScheme("${protocol}") - .setHost("${domain}") - .setPath("${requestPath}") - `; - // http 请求类型 - const method = requestMethod.toLowerCase().replace(/^\S/, (s: string) => s.toUpperCase()); - const httpMethodCode = `Http${method} request = new Http${method}(uri);`; - // 设置参数 - requestArguments.forEach(([k, v]: any[]) => { - uri += `.setParameter("${k}", "${v}")`; - }); - if (method === 'Get' && requestBodyKvs) { - requestBodyKvs.forEach(([k, v]: any[]) => { - uri += `.setParameter("${k}", "${v}")`; - }); - } - - let postKvsParam = ''; - if (method === 'Post') { - // 设置post参数 - requestBodyKvs.forEach(([k, v]: any[]) => { - postKvsParam += `nameValueList.add(new BasicNameValuePair("${k}", "${v}"));\r\n`; - }); - if (postKvsParam !== '') { - postKvsParam = `List nameValueList = new ArrayList();\r\n${postKvsParam}`; - } - } - - if (port) { - uri += `.setPort(${port}) // int类型端口 - `; - uri += ` .build();`; - } else { - uri += `// .setPort(${port}) // int类型端口 - `; - uri += ` .build();`; - } - // 设置请求头 - let setHeader = ''; - requestHeaders.forEach(([k, v]: any[]) => { - setHeader = `${setHeader}request.setHeader("${k}", "${v}");\n`; - }); - try { - requestBody = JSON.stringify(requestBody); - if (!requestBody || requestBody === 'null') { - requestBody = ''; - } - } catch (e) { - requestBody = ''; - } - let postMethodCode = ''; - if (requestMethod === 'POST') { - if (bodyType === 'kvs') { - postMethodCode = `${postKvsParam}\r\n request.setEntity(new UrlEncodedFormEntity(nameValueList, "UTF-8"));`; - } else { - postMethodCode = `request.setEntity(new StringEntity(StringEscapeUtils.unescapeJava(payload)));`; - } - } - - return `import java.net.URI; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.*; -import org.apache.commons.text.StringEscapeUtils; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.util.EntityUtils; -import org.apache.http.entity.StringEntity; - -import java.util.*; -import org.apache.http.NameValuePair; -import org.apache.http.message.BasicNameValuePair; -import org.apache.http.client.entity.UrlEncodedFormEntity; - -// 创建Httpclient对象 -CloseableHttpClient httpclient = HttpClients.createDefault(); -// 参数 -String payload = ${requestBody}; -// 定义请求的参数 -URI uri = ${uri} -// 创建http请求 -${httpMethodCode} -${setHeader} -${postMethodCode} -log.info(uri.toString()); -//response 对象 -CloseableHttpResponse response = null; - -response = httpclient.execute(request); -// 判断返回状态是否为200 -if (response.getStatusLine().getStatusCode() == 200) { - String content = EntityUtils.toString(response.getEntity(), "UTF-8"); - log.info(content); -}`; -} - -// 处理java语言 -function javaCode(requestObj: Record) { - return _beanshellTemplate(requestObj); -} - -// 获取js语言代码模板 -function _jsTemplate(obj: Record) { - const { - requestHeaders = new Map(), - requestMethod = 'GET', - protocol = 'http', - requestArguments = new Map(), - host = '', - domain = '', - port = '', - requestBodyKvs = new Map(), - bodyType = '', - requestRest = new Map(), - } = obj; - let url = ''; - let { requestBody = '', requestPath = '/' } = obj; - requestPath = replaceRestParams(requestPath, requestRest); - if (protocol && domain && port) { - const path = getMockPath(domain, port, host); - requestPath = path + requestPath; - url = `${protocol}://${domain}${port ? `:${port}` : ''}${requestPath}`; - } else if (protocol && domain) { - url = `${protocol}://${domain}${requestPath}`; - } - if (requestMethod.toLowerCase() === 'get' && requestBodyKvs) { - // 如果是get方法要将kv值加入argument中 - requestBodyKvs.forEach(([k, v]: any[]) => { - requestArguments.set(k, v); - }); - } - url = getRequestPath(requestArguments, url); - try { - requestBody = JSON.stringify(requestBody); - } catch (e) { - requestBody = ''; - } - - let connStr = ''; - if (bodyType && bodyType.toUpperCase() === 'RAW') { - requestHeaders.set('Content-type', 'text/plain'); - } - requestHeaders.forEach(([k, v]: any[]) => { - connStr += `conn.setRequestProperty("${k}","${v}");\n`; - }); - - if (requestMethod === 'POST' && bodyType === 'kvs') { - requestBody = '"'; - requestBodyKvs.forEach(([k, v]: any[]) => { - if (requestBody !== '"') { - requestBody += '&'; - } - requestBody += `${k}=${v}`; - }); - requestBody += '"'; - } - let postParamExecCode = ''; - if (requestBody && requestBody !== '' && requestBody !== '""') { - postParamExecCode = ` -var opt = new java.io.DataOutputStream(conn.getOutputStream()); -var t = (new java.lang.String(parameterData)).getBytes("utf-8"); -opt.write(t); -opt.flush(); -opt.close(); - `; - } - - return `var urlStr = "${url}"; // 请求地址 -var requestMethod = "${requestMethod}"; // 请求类型 -var parameterData = ${requestBody}; // 请求参数 -var url = new java.net.URL(urlStr); -var conn = url.openConnection(); -conn.setRequestMethod(requestMethod); -conn.setDoOutput(true); -${connStr}conn.connect(); -${postParamExecCode} -var res = ""; -var rspCode = conn.getResponseCode(); -if (rspCode == 200) { -var ipt = conn.getInputStream(); -var reader = new java.io.BufferedReader(new java.io.InputStreamReader(ipt, "UTF-8")); -var lines; -while((lines = reader.readLine()) !== null) { - res += lines; -} -} -log.info(res); - `; -} - -// 处理js语言 -function jsCode(requestObj: Record) { - return _jsTemplate(requestObj); -} - -export function getCodeTemplate(language: Language, requestObj: any) { - switch (language) { - case LanguageEnum.GROOVY: - return groovyCode(requestObj); - case LanguageEnum.PYTHON: - return pythonCode(requestObj); - case LanguageEnum.BEANSHELL: - return javaCode(requestObj); - case LanguageEnum.NASHORNSCRIPT: - return jsCode(requestObj); - case LanguageEnum.RHINOSCRIPT: - return jsCode(requestObj); - case LanguageEnum.JAVASCRIPT: - return jsCode(requestObj); - default: - return ''; - } -} - -export default {}; diff --git a/frontend/src/views/project-management/environmental/components/RenamePop.vue b/frontend/src/views/project-management/environmental/components/RenamePop.vue index fdfee0e0f8..6e4d2b7dd7 100644 --- a/frontend/src/views/project-management/environmental/components/RenamePop.vue +++ b/frontend/src/views/project-management/environmental/components/RenamePop.vue @@ -8,6 +8,7 @@ :on-before-ok="beforeConfirm" :cancel-button-props="{ disabled: loading }" @popup-visible-change="reset" + @cancel="handleCancel()" >