feat(项目管理): 公共脚本&用例详情微调
This commit is contained in:
parent
98ce08f1fb
commit
13a43240e1
|
@ -1,3 +1,5 @@
|
||||||
|
import { CommentItem } from '@/components/business/ms-comment/types';
|
||||||
|
|
||||||
import MSR from '@/api/http/index';
|
import MSR from '@/api/http/index';
|
||||||
import {
|
import {
|
||||||
AddDemandUrl,
|
AddDemandUrl,
|
||||||
|
@ -22,6 +24,7 @@ import {
|
||||||
DetailCaseUrl,
|
DetailCaseUrl,
|
||||||
DownloadFileUrl,
|
DownloadFileUrl,
|
||||||
FollowerCaseUrl,
|
FollowerCaseUrl,
|
||||||
|
GetAssociatedDrawerCaseUrl,
|
||||||
GetAssociatedFilePageUrl,
|
GetAssociatedFilePageUrl,
|
||||||
GetAssociationPublicCaseModuleCountUrl,
|
GetAssociationPublicCaseModuleCountUrl,
|
||||||
GetAssociationPublicCasePageUrl,
|
GetAssociationPublicCasePageUrl,
|
||||||
|
@ -44,6 +47,7 @@ import {
|
||||||
GetTrashCaseModuleTreeUrl,
|
GetTrashCaseModuleTreeUrl,
|
||||||
MoveCaseModuleTreeUrl,
|
MoveCaseModuleTreeUrl,
|
||||||
PreviewFileUrl,
|
PreviewFileUrl,
|
||||||
|
publicAssociatedCaseUrl,
|
||||||
RecoverRecycleCaseListUrl,
|
RecoverRecycleCaseListUrl,
|
||||||
RestoreCaseListUrl,
|
RestoreCaseListUrl,
|
||||||
TransferFileUrl,
|
TransferFileUrl,
|
||||||
|
@ -61,7 +65,6 @@ import type {
|
||||||
BatchMoveOrCopyType,
|
BatchMoveOrCopyType,
|
||||||
CaseManagementTable,
|
CaseManagementTable,
|
||||||
CaseModuleQueryParams,
|
CaseModuleQueryParams,
|
||||||
CommentItem,
|
|
||||||
CreateOrUpdate,
|
CreateOrUpdate,
|
||||||
CreateOrUpdateDemand,
|
CreateOrUpdateDemand,
|
||||||
CreateOrUpdateModule,
|
CreateOrUpdateModule,
|
||||||
|
@ -297,6 +300,10 @@ export function getPublicLinkCaseModulesCounts(data: TableQueryParams) {
|
||||||
export function getPublicLinkModuleTree(data: TableQueryParams) {
|
export function getPublicLinkModuleTree(data: TableQueryParams) {
|
||||||
return MSR.post<ModulesTreeType[]>({ url: `${GetAssociationPublicModuleTreeUrl}`, data });
|
return MSR.post<ModulesTreeType[]>({ url: `${GetAssociationPublicModuleTreeUrl}`, data });
|
||||||
}
|
}
|
||||||
|
// 关联用例
|
||||||
|
export function associationPublicCase(data: TableQueryParams) {
|
||||||
|
return MSR.post<ModulesTreeType[]>({ url: `${publicAssociatedCaseUrl}`, data });
|
||||||
|
}
|
||||||
|
|
||||||
// 获取前后置用例
|
// 获取前后置用例
|
||||||
export function getDependOnCase(data: TableQueryParams) {
|
export function getDependOnCase(data: TableQueryParams) {
|
||||||
|
@ -314,4 +321,8 @@ export function addPrepositionRelation(data: TableQueryParams) {
|
||||||
export function cancelPreOrPostCase(id: string) {
|
export function cancelPreOrPostCase(id: string) {
|
||||||
return MSR.get({ url: `${cancelPreAndPostCaseUrl}/${id}` });
|
return MSR.get({ url: `${cancelPreAndPostCaseUrl}/${id}` });
|
||||||
}
|
}
|
||||||
|
// 获取抽屉详情已关联用例列表
|
||||||
|
export function getAssociatedCasePage(data: TableQueryParams) {
|
||||||
|
return MSR.post<CommonList<CaseManagementTable>>({ url: `${GetAssociatedDrawerCaseUrl}`, data });
|
||||||
|
}
|
||||||
export default {};
|
export default {};
|
||||||
|
|
|
@ -116,3 +116,7 @@ export const GetDependOnRelationUrl = '/functional/case/relationship/relate/page
|
||||||
export const AddDependOnRelationUrl = '/functional/case/relationship/add';
|
export const AddDependOnRelationUrl = '/functional/case/relationship/add';
|
||||||
// 取消关联前后置关系
|
// 取消关联前后置关系
|
||||||
export const cancelPreAndPostCaseUrl = '/functional/case/relationship/delete';
|
export const cancelPreAndPostCaseUrl = '/functional/case/relationship/delete';
|
||||||
|
// 关联用例
|
||||||
|
export const publicAssociatedCaseUrl = '/functional/case/test/associate/case';
|
||||||
|
// 获取关联用例已关联列表
|
||||||
|
export const GetAssociatedDrawerCaseUrl = '/functional/case/test/has/associate/case/page';
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
let editor: monaco.editor.IStandaloneCodeEditor;
|
let editor: monaco.editor.IStandaloneCodeEditor;
|
||||||
|
|
||||||
const codeEditBox = ref();
|
const codeEditBox = ref();
|
||||||
const fullRef = ref<HTMLElement | null>();
|
const fullRef = ref<HTMLElement | null>();
|
||||||
const currentTheme = ref<Theme>(props.theme);
|
const currentTheme = ref<Theme>(props.theme);
|
||||||
|
@ -83,8 +84,6 @@
|
||||||
emit('update:modelValue', value);
|
emit('update:modelValue', value);
|
||||||
emit('change', value);
|
emit('change', value);
|
||||||
});
|
});
|
||||||
|
|
||||||
emit('editorMounted', editor);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const setEditBoxBg = () => {
|
const setEditBoxBg = () => {
|
||||||
|
@ -101,6 +100,26 @@
|
||||||
|
|
||||||
const { isFullscreen, toggle } = useFullscreen(fullRef);
|
const { isFullscreen, toggle } = useFullscreen(fullRef);
|
||||||
|
|
||||||
|
// 插入内容
|
||||||
|
const insertContent = (text: string) => {
|
||||||
|
if (editor) {
|
||||||
|
const position = editor.getPosition();
|
||||||
|
if (position) {
|
||||||
|
editor.executeEdits('', [
|
||||||
|
{
|
||||||
|
range: new monaco.Range(position?.lineNumber, position?.column, position?.lineNumber, position?.column),
|
||||||
|
text,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
editor.setPosition({
|
||||||
|
lineNumber: position?.lineNumber,
|
||||||
|
column: position.column + text.length,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
editor.focus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.modelValue,
|
() => props.modelValue,
|
||||||
(newValue) => {
|
(newValue) => {
|
||||||
|
@ -137,7 +156,17 @@
|
||||||
setEditBoxBg();
|
setEditBoxBg();
|
||||||
});
|
});
|
||||||
|
|
||||||
return { codeEditBox, fullRef, isFullscreen, currentTheme, themeOptions, toggle, t, handleThemeChange };
|
return {
|
||||||
|
codeEditBox,
|
||||||
|
fullRef,
|
||||||
|
isFullscreen,
|
||||||
|
currentTheme,
|
||||||
|
themeOptions,
|
||||||
|
toggle,
|
||||||
|
t,
|
||||||
|
handleThemeChange,
|
||||||
|
insertContent,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -29,12 +29,13 @@ export enum TableKeyEnum {
|
||||||
FILE_MANAGEMENT_CASE_RECYCLE = 'fileManagementCaseRecycle',
|
FILE_MANAGEMENT_CASE_RECYCLE = 'fileManagementCaseRecycle',
|
||||||
FILE_MANAGEMENT_VERSION = 'fileManagementVersion',
|
FILE_MANAGEMENT_VERSION = 'fileManagementVersion',
|
||||||
PROJECT_MANAGEMENT_MENU_FALSE_ALERT = 'projectManagementMenuFalseAlert',
|
PROJECT_MANAGEMENT_MENU_FALSE_ALERT = 'projectManagementMenuFalseAlert',
|
||||||
|
PROJECT_MANAGEMENT_COMMON_SCRIPT_DETAIL = 'projectManagementCommonScriptDetail',
|
||||||
|
PROJECT_MANAGEMENT_COMMON_SCRIPT_CHANGE_HISTORY = 'projectManagementCommonScriptChangeHistory',
|
||||||
ORGANIZATION_TEMPLATE_DEFECT_TABLE = 'organizationTemplateManagementDefect',
|
ORGANIZATION_TEMPLATE_DEFECT_TABLE = 'organizationTemplateManagementDefect',
|
||||||
CASE_MANAGEMENT_TABLE = 'caseManagement',
|
CASE_MANAGEMENT_TABLE = 'caseManagement',
|
||||||
CASE_MANAGEMENT_DETAIL_TABLE = 'caseManagementDetailTable',
|
CASE_MANAGEMENT_DETAIL_TABLE = 'caseManagementDetailTable',
|
||||||
CASE_MANAGEMENT_ASSOCIATED_TABLE = 'caseManagementAssociatedFileTable',
|
CASE_MANAGEMENT_ASSOCIATED_TABLE = 'caseManagementAssociatedFileTable',
|
||||||
BUG_MANAGEMENT = 'bugManagement',
|
BUG_MANAGEMENT = 'bugManagement',
|
||||||
CASE_MANAGEMENT_DEMAND = 'caseManagementDemand',
|
|
||||||
CASE_MANAGEMENT_REVIEW = 'caseManagementReview',
|
CASE_MANAGEMENT_REVIEW = 'caseManagementReview',
|
||||||
CASE_MANAGEMENT_REVIEW_CASE = 'caseManagementReviewCase',
|
CASE_MANAGEMENT_REVIEW_CASE = 'caseManagementReviewCase',
|
||||||
CASE_MANAGEMENT_TAB_DEFECT = 'caseManagementTabDefect',
|
CASE_MANAGEMENT_TAB_DEFECT = 'caseManagementTabDefect',
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
<a-button type="outline" @click="createDefect">{{ t('caseManagement.featureCase.createDefect') }} </a-button>
|
<a-button type="outline" @click="createDefect">{{ t('caseManagement.featureCase.createDefect') }} </a-button>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="font-medium">{{ t('caseManagement.featureCase.testPlanLinkList') }}</div>
|
<div v-else class="font-medium">{{ t('caseManagement.featureCase.testPlanLinkList') }}</div>
|
||||||
<div>
|
<div class="mb-4">
|
||||||
<a-radio-group v-model:model-value="showType" type="button" class="file-show-type ml-[4px]">
|
<a-radio-group v-model:model-value="showType" type="button" class="file-show-type ml-[4px]">
|
||||||
<a-radio value="link" class="show-type-icon p-[2px]">{{
|
<a-radio value="link" class="show-type-icon p-[2px]">{{
|
||||||
t('caseManagement.featureCase.directLink')
|
t('caseManagement.featureCase.directLink')
|
||||||
|
@ -117,7 +117,6 @@
|
||||||
width: 200,
|
width: 200,
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
ellipsis: true,
|
|
||||||
showDrag: false,
|
showDrag: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -167,7 +166,6 @@
|
||||||
setLoadListParams: setLinkListParams,
|
setLoadListParams: setLinkListParams,
|
||||||
} = useTable(getBugList, {
|
} = useTable(getBugList, {
|
||||||
columns,
|
columns,
|
||||||
tableKey: TableKeyEnum.CASE_MANAGEMENT_TAB_DEFECT,
|
|
||||||
scroll: { x: '100%' },
|
scroll: { x: '100%' },
|
||||||
heightUsed: 340,
|
heightUsed: 340,
|
||||||
enableDrag: true,
|
enableDrag: true,
|
||||||
|
@ -231,7 +229,6 @@
|
||||||
setLoadListParams: setTestPlanListParams,
|
setLoadListParams: setTestPlanListParams,
|
||||||
} = useTable(getBugList, {
|
} = useTable(getBugList, {
|
||||||
columns: testPlanColumns,
|
columns: testPlanColumns,
|
||||||
tableKey: TableKeyEnum.CASE_MANAGEMENT_TAB_DEFECT_TEST_PLAN,
|
|
||||||
scroll: { x: '100%' },
|
scroll: { x: '100%' },
|
||||||
heightUsed: 340,
|
heightUsed: 340,
|
||||||
enableDrag: true,
|
enableDrag: true,
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
:placeholder="t('caseManagement.featureCase.searchByNameAndId')"
|
:placeholder="t('caseManagement.featureCase.searchByNameAndId')"
|
||||||
allow-clear
|
allow-clear
|
||||||
class="mx-[8px] w-[240px]"
|
class="mx-[8px] w-[240px]"
|
||||||
|
@search="searchCase"
|
||||||
|
@press-enter="searchCase"
|
||||||
></a-input-search>
|
></a-input-search>
|
||||||
</div>
|
</div>
|
||||||
<ms-base-table v-bind="propsRes" v-on="propsEvent">
|
<ms-base-table v-bind="propsRes" v-on="propsEvent">
|
||||||
|
@ -56,12 +58,12 @@
|
||||||
import useTable from '@/components/pure/ms-table/useTable';
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
import MsCaseAssociate from '@/components/business/ms-case-associate/index.vue';
|
import MsCaseAssociate from '@/components/business/ms-case-associate/index.vue';
|
||||||
|
|
||||||
import { getAssociatedIds } from '@/api/modules/case-management/caseReview';
|
|
||||||
import {
|
import {
|
||||||
|
associationPublicCase,
|
||||||
|
getAssociatedCasePage,
|
||||||
getPublicLinkCaseList,
|
getPublicLinkCaseList,
|
||||||
getPublicLinkCaseModulesCounts,
|
getPublicLinkCaseModulesCounts,
|
||||||
getPublicLinkModuleTree,
|
getPublicLinkModuleTree,
|
||||||
getRecycleListRequest,
|
|
||||||
} from '@/api/modules/case-management/featureCase';
|
} from '@/api/modules/case-management/featureCase';
|
||||||
import { postTabletList } from '@/api/modules/project-management/menuManagement';
|
import { postTabletList } from '@/api/modules/project-management/menuManagement';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
@ -70,6 +72,8 @@
|
||||||
import type { TableQueryParams } from '@/models/common';
|
import type { TableQueryParams } from '@/models/common';
|
||||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||||
|
|
||||||
|
import Message from '@arco-design/web-vue/es/message';
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -149,7 +153,7 @@
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(getRecycleListRequest, {
|
const { propsRes, propsEvent, loadList, setLoadListParams, setKeyword } = useTable(getAssociatedCasePage, {
|
||||||
columns,
|
columns,
|
||||||
tableKey: TableKeyEnum.CASE_MANAGEMENT_TAB_DEPENDENCY_PRE_CASE,
|
tableKey: TableKeyEnum.CASE_MANAGEMENT_TAB_DEPENDENCY_PRE_CASE,
|
||||||
scroll: { x: '100%' },
|
scroll: { x: '100%' },
|
||||||
|
@ -166,14 +170,6 @@
|
||||||
|
|
||||||
const associatedIds = ref<string[]>([]);
|
const associatedIds = ref<string[]>([]);
|
||||||
|
|
||||||
async function getLinkedIds() {
|
|
||||||
// try {
|
|
||||||
// associatedIds.value = await getAssociatedIds('1111');
|
|
||||||
// } catch (error) {
|
|
||||||
// console.log(error);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentSelectCase = ref<string>('');
|
const currentSelectCase = ref<string>('');
|
||||||
|
|
||||||
const countParams = ref<TableQueryParams>({});
|
const countParams = ref<TableQueryParams>({});
|
||||||
|
@ -181,23 +177,10 @@
|
||||||
const modulesTreeParams = ref<TableQueryParams>({});
|
const modulesTreeParams = ref<TableQueryParams>({});
|
||||||
|
|
||||||
const getTableParams = ref<TableQueryParams>({});
|
const getTableParams = ref<TableQueryParams>({});
|
||||||
function getParams() {
|
|
||||||
switch (currentSelectCase.value) {
|
|
||||||
case 'API':
|
|
||||||
modulesTreeParams.value = { protocol: 'HTTP' };
|
|
||||||
countParams.value = { sourceId: props.caseId, protocol: 'HTTP' };
|
|
||||||
getTableParams.value = { sourceId: props.caseId, protocol: 'HTTP' };
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleSelect(value: string | number | Record<string, any> | undefined) {
|
function handleSelect(value: string | number | Record<string, any> | undefined) {
|
||||||
currentSelectCase.value = value as string;
|
currentSelectCase.value = value as string;
|
||||||
innerVisible.value = true;
|
innerVisible.value = true;
|
||||||
getLinkedIds();
|
|
||||||
// getParams();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function cancelLink(record: any) {}
|
function cancelLink(record: any) {}
|
||||||
|
@ -216,8 +199,17 @@
|
||||||
|
|
||||||
const confirmLoading = ref<boolean>(false);
|
const confirmLoading = ref<boolean>(false);
|
||||||
|
|
||||||
function saveHandler(params: TableQueryParams) {
|
async function saveHandler(params: TableQueryParams) {
|
||||||
console.log(params);
|
try {
|
||||||
|
confirmLoading.value = true;
|
||||||
|
await associationPublicCase(params);
|
||||||
|
Message.success(t('caseManagement.featureCase.AssociatedSuccess'));
|
||||||
|
innerVisible.value = false;
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
confirmLoading.value = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const moduleMaps: Record<string, { label: string; value: string }[]> = {
|
const moduleMaps: Record<string, { label: string; value: string }[]> = {
|
||||||
|
@ -245,7 +237,7 @@
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(async () => {
|
async function getEnabledModules() {
|
||||||
const result = await postTabletList({ projectId: currentProjectId.value });
|
const result = await postTabletList({ projectId: currentProjectId.value });
|
||||||
const caseArr = result.filter((item) => Object.keys(moduleMaps).includes(item.module));
|
const caseArr = result.filter((item) => Object.keys(moduleMaps).includes(item.module));
|
||||||
caseArr.forEach((item: any) => {
|
caseArr.forEach((item: any) => {
|
||||||
|
@ -253,7 +245,26 @@
|
||||||
caseTypeOptions.value.push(...currentModule);
|
caseTypeOptions.value.push(...currentModule);
|
||||||
});
|
});
|
||||||
currentSelectCase.value = caseTypeOptions.value[0].value;
|
currentSelectCase.value = caseTypeOptions.value[0].value;
|
||||||
getParams();
|
}
|
||||||
|
|
||||||
|
function getFetch() {
|
||||||
|
setLoadListParams({
|
||||||
|
keyword: keyword.value,
|
||||||
|
sourceId: props.caseId,
|
||||||
|
projectId: currentProjectId.value,
|
||||||
|
sourceType: currentSelectCase.value,
|
||||||
|
});
|
||||||
|
loadList();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function searchCase() {
|
||||||
|
setKeyword(keyword.value);
|
||||||
|
await loadList();
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
getEnabledModules();
|
||||||
|
getFetch();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -12,11 +12,19 @@
|
||||||
></a-input-search>
|
></a-input-search>
|
||||||
</div>
|
</div>
|
||||||
<ms-base-table v-bind="propsRes" v-on="propsEvent">
|
<ms-base-table v-bind="propsRes" v-on="propsEvent">
|
||||||
<template #name="{ record }">
|
<template #reviewName="{ record }">
|
||||||
<a-button type="text" class="px-0">{{ record.name }}</a-button>
|
<a-button type="text" class="px-0">{{ record.reviewName }}</a-button>
|
||||||
|
</template>
|
||||||
|
<template #reviewStatus="{ record }">
|
||||||
|
<statusTag :status="record.reviewStatus" />
|
||||||
</template>
|
</template>
|
||||||
<template #status="{ record }">
|
<template #status="{ record }">
|
||||||
<statusTag :status="record.status" />
|
<MsIcon
|
||||||
|
:type="getStatusText(record.status)?.iconType || ''"
|
||||||
|
class="mr-1"
|
||||||
|
:class="[getReviewStatusClass(record.status)]"
|
||||||
|
></MsIcon>
|
||||||
|
<span>{{ getStatusText(record.status)?.statusType || '' }} </span>
|
||||||
</template>
|
</template>
|
||||||
</ms-base-table>
|
</ms-base-table>
|
||||||
</div>
|
</div>
|
||||||
|
@ -35,6 +43,7 @@
|
||||||
|
|
||||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||||
|
|
||||||
|
import { getReviewStatusClass, getStatusText } from '../utils';
|
||||||
import debounce from 'lodash-es/debounce';
|
import debounce from 'lodash-es/debounce';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -48,36 +57,37 @@
|
||||||
const columns: MsTableColumn = [
|
const columns: MsTableColumn = [
|
||||||
{
|
{
|
||||||
title: 'ID',
|
title: 'ID',
|
||||||
dataIndex: 'id',
|
dataIndex: 'reviewId',
|
||||||
sortIndex: 1,
|
sortIndex: 1,
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
width: 90,
|
width: 300,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'caseManagement.caseReview.name',
|
title: 'caseManagement.caseReview.name',
|
||||||
slotName: 'name',
|
slotName: 'reviewName',
|
||||||
dataIndex: 'name',
|
dataIndex: 'reviewName',
|
||||||
sortable: {
|
sortable: {
|
||||||
sortDirections: ['ascend', 'descend'],
|
sortDirections: ['ascend', 'descend'],
|
||||||
},
|
},
|
||||||
width: 200,
|
showTooltip: true,
|
||||||
|
width: 300,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'caseManagement.caseReview.status',
|
title: 'caseManagement.caseReview.status',
|
||||||
dataIndex: 'status',
|
dataIndex: 'reviewStatus',
|
||||||
slotName: 'status',
|
slotName: 'reviewStatus',
|
||||||
width: 150,
|
width: 150,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'caseManagement.featureCase.reviewResult',
|
title: 'caseManagement.featureCase.reviewResult',
|
||||||
slotName: 'reviewResult',
|
slotName: 'status',
|
||||||
dataIndex: 'reviewResult',
|
dataIndex: 'status',
|
||||||
width: 200,
|
width: 200,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'caseManagement.featureCase.reviewTime',
|
title: 'caseManagement.featureCase.reviewTime',
|
||||||
slotName: 'reviewTime',
|
slotName: 'updateTime',
|
||||||
dataIndex: 'reviewTime',
|
dataIndex: 'updateTime',
|
||||||
width: 200,
|
width: 200,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -99,6 +109,15 @@
|
||||||
initData();
|
initData();
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
|
function getReviewStatus(status: string) {
|
||||||
|
switch (status) {
|
||||||
|
case 'UN_REVIEWED':
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
initData();
|
initData();
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,12 +11,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<!-- TODO -->
|
<!-- TODO -->
|
||||||
<!-- <MsComment
|
<MsComment :comment-list="commentList" @delete="handleDelete" @update-or-add="handleUpdate" />
|
||||||
:current-user-id="currentUserId"
|
|
||||||
:comment-list="commentList"
|
|
||||||
@update-or-add="handleUpdateOrAdd"
|
|
||||||
@delete="handleDelete"
|
|
||||||
/> -->
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -24,12 +19,11 @@
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
import MsComment from '@/components/business/ms-comment/comment';
|
import MsComment from '@/components/business/ms-comment/comment';
|
||||||
|
import { CommentItem, CommentParams } from '@/components/business/ms-comment/types';
|
||||||
|
|
||||||
import { getCommentList } from '@/api/modules/case-management/featureCase';
|
import { getCommentList } from '@/api/modules/case-management/featureCase';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
import type { CommentItem } from '@/models/caseManagement/featureCase';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
@ -59,6 +53,9 @@
|
||||||
// 删除评论
|
// 删除评论
|
||||||
function handleDelete() {}
|
function handleDelete() {}
|
||||||
|
|
||||||
|
// 更新评论
|
||||||
|
function handleUpdate() {}
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
initCommentList();
|
initCommentList();
|
||||||
});
|
});
|
||||||
|
|
|
@ -38,7 +38,6 @@
|
||||||
import { useAppStore } from '@/store';
|
import { useAppStore } from '@/store';
|
||||||
|
|
||||||
import type { DemandItem } from '@/models/caseManagement/featureCase';
|
import type { DemandItem } from '@/models/caseManagement/featureCase';
|
||||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const pageConfig = computed(() => appStore.pageConfig);
|
const pageConfig = computed(() => appStore.pageConfig);
|
||||||
|
@ -99,7 +98,6 @@
|
||||||
];
|
];
|
||||||
|
|
||||||
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(getDemandList, {
|
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(getDemandList, {
|
||||||
tableKey: TableKeyEnum.CASE_MANAGEMENT_DEMAND,
|
|
||||||
columns,
|
columns,
|
||||||
rowKey: 'id',
|
rowKey: 'id',
|
||||||
scroll: { x: '100%' },
|
scroll: { x: '100%' },
|
||||||
|
@ -120,6 +118,7 @@
|
||||||
defineExpose({
|
defineExpose({
|
||||||
initData,
|
initData,
|
||||||
});
|
});
|
||||||
|
|
||||||
const tableRef = ref<InstanceType<typeof MsBaseTable> | null>(null);
|
const tableRef = ref<InstanceType<typeof MsBaseTable> | null>(null);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|
|
@ -216,7 +216,7 @@
|
||||||
|
|
||||||
const initData = async () => {
|
const initData = async () => {
|
||||||
setLoadListParams({ keyword: platformKeyword.value });
|
setLoadListParams({ keyword: platformKeyword.value });
|
||||||
loadList();
|
// loadList();
|
||||||
};
|
};
|
||||||
|
|
||||||
const searchHandler = () => {
|
const searchHandler = () => {
|
||||||
|
@ -224,12 +224,9 @@
|
||||||
resetSelector();
|
resetSelector();
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
initData();
|
|
||||||
});
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
resetSelector();
|
resetSelector();
|
||||||
|
initData();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -43,8 +43,6 @@
|
||||||
import { getDemandList } from '@/api/modules/case-management/featureCase';
|
import { getDemandList } from '@/api/modules/case-management/featureCase';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const columns: MsTableColumn = [
|
const columns: MsTableColumn = [
|
||||||
|
@ -88,7 +86,6 @@
|
||||||
];
|
];
|
||||||
|
|
||||||
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(getDemandList, {
|
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(getDemandList, {
|
||||||
tableKey: TableKeyEnum.CASE_MANAGEMENT_DEMAND,
|
|
||||||
columns,
|
columns,
|
||||||
rowKey: 'id',
|
rowKey: 'id',
|
||||||
scroll: { x: '100%' },
|
scroll: { x: '100%' },
|
||||||
|
|
|
@ -138,7 +138,7 @@
|
||||||
selectable: false,
|
selectable: false,
|
||||||
noDisable: true,
|
noDisable: true,
|
||||||
showSetting: false,
|
showSetting: false,
|
||||||
enableDrag: true,
|
enableDrag: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const cancelLoading = ref<boolean>(false);
|
const cancelLoading = ref<boolean>(false);
|
||||||
|
|
|
@ -246,4 +246,5 @@ export default {
|
||||||
'caseManagement.featureCase.quicklyCreateDefectSuccess': 'Quick bug creation success',
|
'caseManagement.featureCase.quicklyCreateDefectSuccess': 'Quick bug creation success',
|
||||||
'caseManagement.featureCase.cancelDependencyTip': 'Confirm cancel dependencies?',
|
'caseManagement.featureCase.cancelDependencyTip': 'Confirm cancel dependencies?',
|
||||||
'caseManagement.featureCase.cancelDependencyContent': 'Cancel after impact test plan related statistics',
|
'caseManagement.featureCase.cancelDependencyContent': 'Cancel after impact test plan related statistics',
|
||||||
|
'caseManagement.featureCase.AssociatedSuccess': 'Associated with success',
|
||||||
};
|
};
|
||||||
|
|
|
@ -235,10 +235,11 @@ export default {
|
||||||
'caseManagement.featureCase.CheckFailure': '校验失败',
|
'caseManagement.featureCase.CheckFailure': '校验失败',
|
||||||
'caseManagement.featureCase.CheckSuccess': '校验成功',
|
'caseManagement.featureCase.CheckSuccess': '校验成功',
|
||||||
'caseManagement.featureCase.tableNoData': '暂无数据',
|
'caseManagement.featureCase.tableNoData': '暂无数据',
|
||||||
'caseManagement.featureCase.noAssociated': '暂无可关联缺陷,请',
|
'caseManagement.featureCase.noAssociatedDefect': '暂无可关联缺陷,请',
|
||||||
'caseManagement.featureCase.fileIsUpdated': '当前文件已更新',
|
'caseManagement.featureCase.fileIsUpdated': '当前文件已更新',
|
||||||
'caseManagement.featureCase.selectTransferDirectory': '请选择转存目录',
|
'caseManagement.featureCase.selectTransferDirectory': '请选择转存目录',
|
||||||
'caseManagement.featureCase.quicklyCreateDefectSuccess': '快速创建缺陷成功',
|
'caseManagement.featureCase.quicklyCreateDefectSuccess': '快速创建缺陷成功',
|
||||||
'caseManagement.featureCase.cancelDependencyTip': '确认取消依赖关系吗?',
|
'caseManagement.featureCase.cancelDependencyTip': '确认取消依赖关系吗?',
|
||||||
'caseManagement.featureCase.cancelDependencyContent': '取消后,影响测试计划相关统计',
|
'caseManagement.featureCase.cancelDependencyContent': '取消后,影响测试计划相关统计',
|
||||||
|
'caseManagement.featureCase.AssociatedSuccess': '关联成功',
|
||||||
};
|
};
|
||||||
|
|
|
@ -46,19 +46,7 @@
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
<a-button type="outline">{{ t('project.commonScript.scriptTest') }}</a-button>
|
<a-button type="outline">{{ t('project.commonScript.scriptTest') }}</a-button>
|
||||||
</div>
|
</div>
|
||||||
<ScriptDefined v-if="scriptType === 'commonScript'" />
|
<ScriptDefined :show-type="scriptType" />
|
||||||
<div v-else>
|
|
||||||
<MsCodeEditor
|
|
||||||
v-model:model-value="executionResultValue"
|
|
||||||
title=""
|
|
||||||
width="100%"
|
|
||||||
height="calc(100vh - 155px)"
|
|
||||||
theme="MS-text"
|
|
||||||
:read-only="false"
|
|
||||||
:show-full-screen="false"
|
|
||||||
:show-theme-change="false"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</a-form>
|
</a-form>
|
||||||
</MsDrawer>
|
</MsDrawer>
|
||||||
</template>
|
</template>
|
||||||
|
@ -66,7 +54,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
|
|
||||||
import MsCodeEditor from '@/components/pure/ms-code-editor/index.vue';
|
|
||||||
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||||
import type { MsTableColumn } from '@/components/pure/ms-table/type';
|
import type { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||||
|
@ -102,27 +89,27 @@
|
||||||
|
|
||||||
const columns: MsTableColumn = [
|
const columns: MsTableColumn = [
|
||||||
{
|
{
|
||||||
title: '参数名称',
|
title: 'project.commonScript.ParameterNames',
|
||||||
slotName: 'name',
|
slotName: 'name',
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '是否必填',
|
title: 'project.commonScript.isRequired',
|
||||||
slotName: 'required',
|
slotName: 'required',
|
||||||
dataIndex: 'required',
|
dataIndex: 'required',
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '参数值',
|
title: 'project.commonScript.ParameterValue',
|
||||||
dataIndex: 'tags',
|
dataIndex: 'tags',
|
||||||
slotName: 'tags',
|
slotName: 'tags',
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '描述',
|
title: 'project.commonScript.description',
|
||||||
slotName: 'desc',
|
slotName: 'desc',
|
||||||
dataIndex: 'desc',
|
dataIndex: 'desc',
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
|
@ -153,8 +140,6 @@
|
||||||
);
|
);
|
||||||
|
|
||||||
const scriptType = ref<'commonScript' | 'executionResult'>('commonScript');
|
const scriptType = ref<'commonScript' | 'executionResult'>('commonScript');
|
||||||
|
|
||||||
const executionResultValue = ref('');
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="w-full bg-[var(--color-bg-3)] p-4 pb-0">
|
<div v-if="props.showType === 'commonScript'" class="w-full bg-[var(--color-bg-3)] p-4 pb-0">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<MsTag class="!mr-2" theme="outline">
|
<MsTag class="!mr-2" theme="outline">
|
||||||
|
@ -14,23 +14,24 @@
|
||||||
{{ t('project.commonScript.clear') }}</MsTag
|
{{ t('project.commonScript.clear') }}</MsTag
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<MsTag theme="outline">{{ t('project.commonScript.formatting') }}</MsTag>
|
<MsTag theme="outline" @click="formatCoding">{{ t('project.commonScript.formatting') }}</MsTag>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex h-[calc(100vh-120px)] bg-[var(--color-bg-3)]">
|
<div v-if="props.showType === 'commonScript'" class="flex h-[calc(100vh-220px)] bg-[var(--color-bg-3)]">
|
||||||
<div class="leftCodeEditor w-[70%]">
|
<div class="leftCodeEditor w-[70%]">
|
||||||
<MsCodeEditor
|
<MsCodeEditor
|
||||||
|
ref="codeEditorRef"
|
||||||
v-model:model-value="commonScriptValue"
|
v-model:model-value="commonScriptValue"
|
||||||
title=""
|
title=""
|
||||||
width="100%"
|
width="100%"
|
||||||
height="calc(100vh - 155px)"
|
height="calc(100vh - 255px)"
|
||||||
theme="MS-text"
|
theme="MS-text"
|
||||||
:read-only="false"
|
:read-only="false"
|
||||||
:show-full-screen="false"
|
:show-full-screen="false"
|
||||||
:show-theme-change="false"
|
:show-theme-change="false"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="rightCodeEditor mt-[24px] h-[calc(100vh-155px)] w-[calc(30%-12px)] bg-white">
|
<div class="rightCodeEditor mt-[24px] h-[calc(100vh-255px)] w-[calc(30%-12px)] bg-white">
|
||||||
<div class="flex items-center justify-between p-3">
|
<div class="flex items-center justify-between p-3">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<span v-if="expanded" class="collapsebtn mr-1 flex items-center justify-center" @click="expandedHandler">
|
<span v-if="expanded" class="collapsebtn mr-1 flex items-center justify-center" @click="expandedHandler">
|
||||||
|
@ -47,16 +48,28 @@
|
||||||
</a-select>
|
</a-select>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!expanded" class="p-[12px] pt-0">
|
<div v-if="!expanded" class="p-[12px] pt-0">
|
||||||
<div v-for="item of SCRIPT_MENU" :key="item.value" class="menuItem px-1 text-[12px]" @click="handleClick(item)">
|
<div v-for="item of SCRIPT_MENU" :key="item.value" class="menuItem px-1" @click="handleClick(item)">
|
||||||
{{ item.title }}
|
{{ item.title }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<MsCodeEditor
|
||||||
|
v-else
|
||||||
|
v-model:model-value="executionResultValue"
|
||||||
|
title=""
|
||||||
|
width="100%"
|
||||||
|
height="calc(100vh - 155px)"
|
||||||
|
theme="MS-text"
|
||||||
|
:read-only="false"
|
||||||
|
:show-full-screen="false"
|
||||||
|
:show-theme-change="false"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
|
||||||
import MsCodeEditor from '@/components/pure/ms-code-editor/index.vue';
|
import MsCodeEditor from '@/components/pure/ms-code-editor/index.vue';
|
||||||
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||||
|
@ -65,12 +78,17 @@
|
||||||
|
|
||||||
import type { CommonScriptMenu } from '@/models/projectManagement/commonScript';
|
import type { CommonScriptMenu } from '@/models/projectManagement/commonScript';
|
||||||
|
|
||||||
import { SCRIPT_MENU } from '../utils';
|
import { getCodeTemplate, type Languages, SCRIPT_MENU } from '../utils';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
showType: 'commonScript' | 'executionResult'; // 执行类型
|
||||||
|
}>();
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
const executionResultValue = ref('');
|
||||||
|
|
||||||
const expanded = ref<boolean>(true);
|
const expanded = ref<boolean>(true);
|
||||||
const language = ref('beanshell');
|
const language = ref<Languages>('beanshell');
|
||||||
const commonScriptValue = ref('');
|
const commonScriptValue = ref('');
|
||||||
|
|
||||||
const languages = [
|
const languages = [
|
||||||
|
@ -84,7 +102,56 @@
|
||||||
expanded.value = !expanded.value;
|
expanded.value = !expanded.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleClick(menu: CommonScriptMenu) {}
|
function _handleCommand(command) {
|
||||||
|
switch (command) {
|
||||||
|
// 自定义代码片段
|
||||||
|
case 'custom_function':
|
||||||
|
return '';
|
||||||
|
// 从API定义导入
|
||||||
|
case 'api_definition':
|
||||||
|
// TODO 需要接口的页面导入
|
||||||
|
return '';
|
||||||
|
// 新API测试[JSON]
|
||||||
|
case 'new_api_request': {
|
||||||
|
// requestObj为空则生产默认模版
|
||||||
|
const headers = new Map();
|
||||||
|
headers.set('Content-type', 'application/json');
|
||||||
|
return getCodeTemplate(language.value, { requestHeaders: headers });
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const codeEditorRef = ref();
|
||||||
|
|
||||||
|
function formatCoding() {}
|
||||||
|
|
||||||
|
function handleCodeTemplate(code: string) {
|
||||||
|
codeEditorRef.value.insertContent(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleClick(obj: CommonScriptMenu) {
|
||||||
|
let code = '';
|
||||||
|
if (obj.command) {
|
||||||
|
code = _handleCommand(obj.command);
|
||||||
|
if (!code) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (language.value !== 'beanshell' && language.value !== 'groovy') {
|
||||||
|
if (
|
||||||
|
obj.title === t('api_test.request.processor.code_add_report_length') ||
|
||||||
|
obj.title === t('api_test.request.processor.code_hide_report_length')
|
||||||
|
) {
|
||||||
|
Message.warning(`${t('commons.no_corresponding')} ${language.value} ${t('commons.code_template')}!`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
code = obj.value;
|
||||||
|
}
|
||||||
|
handleCodeTemplate(code);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
|
|
|
@ -0,0 +1,234 @@
|
||||||
|
<template>
|
||||||
|
<MsDrawer
|
||||||
|
v-model:visible="scriptDetailDrawer"
|
||||||
|
:title="t('project.commonScript.publicScriptName')"
|
||||||
|
:width="768"
|
||||||
|
:footer="false"
|
||||||
|
unmount-on-close
|
||||||
|
>
|
||||||
|
<template #headerLeft>
|
||||||
|
<MsTag type="success" theme="light">{{ t('project.commonScript.testSuccess') }}</MsTag>
|
||||||
|
</template>
|
||||||
|
<a-radio-group v-model:model-value="showType" type="button" size="small">
|
||||||
|
<a-radio value="detail">{{ t('project.commonScript.detail') }}</a-radio>
|
||||||
|
<a-radio value="changeHistory">{{ t('project.commonScript.changeHistory') }}</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
<!-- 详情开始 -->
|
||||||
|
<div v-if="showType === 'detail'">
|
||||||
|
<div class="detailField mt-4">
|
||||||
|
<div class="item">
|
||||||
|
<span class="label">{{ t('project.commonScript.description') }}</span>
|
||||||
|
<span class="content">内容内容内容内容内容内容内容内容</span>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<span class="label">{{ t('project.commonScript.tags') }}</span>
|
||||||
|
<span class="content">
|
||||||
|
<MsTag theme="outline">标签</MsTag>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span>{{ t('project.commonScript.inputParams') }}</span>
|
||||||
|
<ms-base-table v-bind="propsRes" ref="tableRef" class="mb-4" no-disable v-on="propsEvent"> </ms-base-table>
|
||||||
|
|
||||||
|
<a-radio-group v-model:model-value="scriptType" type="button" size="small">
|
||||||
|
<a-radio value="commonScript">{{ t('project.commonScript.commonScript') }}</a-radio>
|
||||||
|
<a-radio value="executionResult">{{ t('project.commonScript.executionResult') }}</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
<MsCodeEditor
|
||||||
|
v-model:model-value="detailValue"
|
||||||
|
class="mt-2"
|
||||||
|
title=""
|
||||||
|
width="100%"
|
||||||
|
height="calc(100vh - 155px)"
|
||||||
|
theme="MS-text"
|
||||||
|
:read-only="false"
|
||||||
|
:show-full-screen="false"
|
||||||
|
:show-theme-change="false"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<ms-base-table
|
||||||
|
v-else
|
||||||
|
v-bind="changeHistoryPropsRes"
|
||||||
|
ref="tableRef"
|
||||||
|
class="mb-4"
|
||||||
|
no-disable
|
||||||
|
v-on="changeHistoryPropsEvent"
|
||||||
|
>
|
||||||
|
<template #changeSerialNumber="{ record }"
|
||||||
|
><div class="flex items-center"> {{ record.changeSerialNumber }} <MsTag>当前</MsTag> </div>
|
||||||
|
</template>
|
||||||
|
<template #operation="{ record }">
|
||||||
|
<MsButton status="primary" @click="recoverHandler(record)">
|
||||||
|
{{ t('project.commonScript.recover') }}
|
||||||
|
</MsButton>
|
||||||
|
</template>
|
||||||
|
</ms-base-table>
|
||||||
|
</MsDrawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
|
import MsCodeEditor from '@/components/pure/ms-code-editor/index.vue';
|
||||||
|
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||||
|
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||||
|
import type { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||||
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
|
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||||
|
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
visible: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:visible']);
|
||||||
|
|
||||||
|
const showType = ref('detail');
|
||||||
|
|
||||||
|
const scriptDetailDrawer = computed({
|
||||||
|
get() {
|
||||||
|
return props.visible;
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
emit('update:visible', val);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const columns: MsTableColumn = [
|
||||||
|
{
|
||||||
|
title: 'project.commonScript.ParameterNames',
|
||||||
|
slotName: 'name',
|
||||||
|
dataIndex: 'name',
|
||||||
|
showTooltip: true,
|
||||||
|
showInTable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'project.commonScript.isRequired',
|
||||||
|
slotName: 'required',
|
||||||
|
dataIndex: 'required',
|
||||||
|
showInTable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'project.commonScript.ParameterValue',
|
||||||
|
dataIndex: 'tags',
|
||||||
|
slotName: 'tags',
|
||||||
|
showTooltip: true,
|
||||||
|
showInTable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'project.commonScript.description',
|
||||||
|
slotName: 'desc',
|
||||||
|
dataIndex: 'desc',
|
||||||
|
showTooltip: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable(
|
||||||
|
() =>
|
||||||
|
Promise.resolve({
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
ParameterNames: 'xxxx',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
current: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 2,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
columns,
|
||||||
|
selectable: false,
|
||||||
|
showSetting: false,
|
||||||
|
scroll: { x: '100%' },
|
||||||
|
heightUsed: 300,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const scriptType = ref<'commonScript' | 'executionResult'>('commonScript');
|
||||||
|
|
||||||
|
const detailValue = ref('');
|
||||||
|
|
||||||
|
const changeHistoryColumns: MsTableColumn = [
|
||||||
|
{
|
||||||
|
title: 'project.commonScript.changeSerialNumber',
|
||||||
|
slotName: 'changeSerialNumber',
|
||||||
|
dataIndex: 'changeSerialNumber',
|
||||||
|
showTooltip: true,
|
||||||
|
showInTable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'project.commonScript.actionType',
|
||||||
|
slotName: 'actionType',
|
||||||
|
dataIndex: 'actionType',
|
||||||
|
showInTable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'project.commonScript.actionUser',
|
||||||
|
dataIndex: 'actionUser',
|
||||||
|
slotName: 'actionUser',
|
||||||
|
showTooltip: true,
|
||||||
|
showInTable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'project.commonScript.updateTime',
|
||||||
|
dataIndex: 'updateTime',
|
||||||
|
slotName: 'updateTime',
|
||||||
|
showTooltip: true,
|
||||||
|
showInTable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'project.commonScript.tableColumnActions',
|
||||||
|
slotName: 'operation',
|
||||||
|
dataIndex: 'operation',
|
||||||
|
fixed: 'right',
|
||||||
|
width: 140,
|
||||||
|
showInTable: true,
|
||||||
|
showDrag: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const {
|
||||||
|
propsRes: changeHistoryPropsRes,
|
||||||
|
propsEvent: changeHistoryPropsEvent,
|
||||||
|
loadList: changeHistoryloadList,
|
||||||
|
setLoadListParams: changeHistorySetLoadListParams,
|
||||||
|
resetSelector: changeHistoryResetSelector,
|
||||||
|
} = useTable(
|
||||||
|
() =>
|
||||||
|
Promise.resolve({
|
||||||
|
list: [],
|
||||||
|
current: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 2,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
columns: changeHistoryColumns,
|
||||||
|
tableKey: TableKeyEnum.PROJECT_MANAGEMENT_COMMON_SCRIPT_CHANGE_HISTORY,
|
||||||
|
selectable: false,
|
||||||
|
showSetting: false,
|
||||||
|
scroll: { x: '100%' },
|
||||||
|
heightUsed: 300,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
function recoverHandler(record: any) {}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.detailField {
|
||||||
|
.item {
|
||||||
|
@apply mb-4 flex;
|
||||||
|
.label {
|
||||||
|
width: 56px;
|
||||||
|
color: var(--color-text-3);
|
||||||
|
@apply mr-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -12,7 +12,11 @@
|
||||||
<ms-base-table v-bind="propsRes" v-on="propsEvent">
|
<ms-base-table v-bind="propsRes" v-on="propsEvent">
|
||||||
<template #name="{ record }">
|
<template #name="{ record }">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="one-line-text max-w-[200px] text-[rgb(var(--primary-5))]">{{ record.name }}</div>
|
<div
|
||||||
|
class="one-line-text max-w-[200px] cursor-pointer text-[rgb(var(--primary-5))]"
|
||||||
|
@click="showDetail(record)"
|
||||||
|
>{{ record.name }}</div
|
||||||
|
>
|
||||||
<a-popover :title="t('project.commonScript.publicScriptName')" position="right">
|
<a-popover :title="t('project.commonScript.publicScriptName')" position="right">
|
||||||
<a-button type="text" class="ml-2 px-0">{{ t('project.commonScript.preview') }}</a-button>
|
<a-button type="text" class="ml-2 px-0">{{ t('project.commonScript.preview') }}</a-button>
|
||||||
<template #content>
|
<template #content>
|
||||||
|
@ -53,6 +57,7 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<AddScriptDrawer v-model:visible="showScriptDrawer" />
|
<AddScriptDrawer v-model:visible="showScriptDrawer" />
|
||||||
|
<ScriptDetailDrawer v-model:visible="showDetailDrawer" />
|
||||||
</MsCard>
|
</MsCard>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -70,6 +75,7 @@
|
||||||
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||||
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||||
import AddScriptDrawer from './components/addScriptDrawer.vue';
|
import AddScriptDrawer from './components/addScriptDrawer.vue';
|
||||||
|
import ScriptDetailDrawer from './components/scriptDetailDrawer.vue';
|
||||||
|
|
||||||
import { getDependOnCase } from '@/api/modules/case-management/featureCase';
|
import { getDependOnCase } from '@/api/modules/case-management/featureCase';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
@ -218,6 +224,12 @@
|
||||||
|
|
||||||
const showScriptDrawer = ref<boolean>(false);
|
const showScriptDrawer = ref<boolean>(false);
|
||||||
|
|
||||||
|
const showDetailDrawer = ref<boolean>(false);
|
||||||
|
// 脚本详情
|
||||||
|
function showDetail(record: any) {
|
||||||
|
showDetailDrawer.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
function addCommonScript() {
|
function addCommonScript() {
|
||||||
showScriptDrawer.value = true;
|
showScriptDrawer.value = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,16 @@ export default {
|
||||||
'project.commonScript.formatting': 'formatting',
|
'project.commonScript.formatting': 'formatting',
|
||||||
'project.commonScript.undo': 'cancel',
|
'project.commonScript.undo': 'cancel',
|
||||||
'project.commonScript.clear': 'clear',
|
'project.commonScript.clear': 'clear',
|
||||||
|
'project.commonScript.testSuccess': 'Test successfully',
|
||||||
|
'project.commonScript.ParameterNames': 'Parameter names',
|
||||||
|
'project.commonScript.isRequired': 'Required',
|
||||||
|
'project.commonScript.ParameterValue': 'Parameter Value',
|
||||||
|
'project.commonScript.changeSerialNumber': 'Change Number',
|
||||||
|
'project.commonScript.actionType': 'action Type',
|
||||||
|
'project.commonScript.actionUser': 'operator',
|
||||||
|
'project.commonScript.recover': 'recover',
|
||||||
|
'project.commonScript.detail': 'detail',
|
||||||
|
'project.commonScript.changeHistory': 'Change history',
|
||||||
'code_segment': {
|
'code_segment': {
|
||||||
importApiTest: 'Import from API definition',
|
importApiTest: 'Import from API definition',
|
||||||
newApiTest: 'New API test[JSON]',
|
newApiTest: 'New API test[JSON]',
|
||||||
|
|
|
@ -15,7 +15,7 @@ export default {
|
||||||
'project.commonScript.testsPass': '测试通过',
|
'project.commonScript.testsPass': '测试通过',
|
||||||
'project.commonScript.draft': '草稿',
|
'project.commonScript.draft': '草稿',
|
||||||
'project.commonScript.publicScriptName': '公共脚本名称',
|
'project.commonScript.publicScriptName': '公共脚本名称',
|
||||||
'project.commonScript.publicScriptNameNotEmpty': '公共脚本名称',
|
'project.commonScript.publicScriptNameNotEmpty': '公共脚本名称不能为空',
|
||||||
'project.commonScript.pleaseEnterScriptName': '请输入脚本名称',
|
'project.commonScript.pleaseEnterScriptName': '请输入脚本名称',
|
||||||
'project.commonScript.scriptEnabled': '脚本状态',
|
'project.commonScript.scriptEnabled': '脚本状态',
|
||||||
'project.commonScript.enterContentAddTags': '输入内容后回车可直接添加标签',
|
'project.commonScript.enterContentAddTags': '输入内容后回车可直接添加标签',
|
||||||
|
@ -28,6 +28,16 @@ export default {
|
||||||
'project.commonScript.formatting': '格式化',
|
'project.commonScript.formatting': '格式化',
|
||||||
'project.commonScript.undo': '撤销',
|
'project.commonScript.undo': '撤销',
|
||||||
'project.commonScript.clear': '清空',
|
'project.commonScript.clear': '清空',
|
||||||
|
'project.commonScript.testSuccess': '测试成功',
|
||||||
|
'project.commonScript.ParameterNames': '参数名称',
|
||||||
|
'project.commonScript.isRequired': '是否必填',
|
||||||
|
'project.commonScript.ParameterValue': '参数值',
|
||||||
|
'project.commonScript.changeSerialNumber': '变更序号',
|
||||||
|
'project.commonScript.actionType': '类型',
|
||||||
|
'project.commonScript.actionUser': '操作人',
|
||||||
|
'project.commonScript.recover': '恢复',
|
||||||
|
'project.commonScript.detail': '详情',
|
||||||
|
'project.commonScript.changeHistory': '变更历史',
|
||||||
'project': {
|
'project': {
|
||||||
code_segment: {
|
code_segment: {
|
||||||
importApiTest: '从API定义导入',
|
importApiTest: '从API定义导入',
|
||||||
|
|
|
@ -4,6 +4,8 @@ import type { CommonScriptMenu } from '@/models/projectManagement/commonScript';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
export type Languages = 'groovy' | 'python' | 'beanshell' | 'nashornScript' | 'rhinoScript' | 'javascript';
|
||||||
|
|
||||||
export const SCRIPT_MENU: CommonScriptMenu[] = [
|
export const SCRIPT_MENU: CommonScriptMenu[] = [
|
||||||
{
|
{
|
||||||
title: t('project.code_segment.importApiTest'),
|
title: t('project.code_segment.importApiTest'),
|
||||||
|
@ -47,9 +49,479 @@ export const SCRIPT_MENU: CommonScriptMenu[] = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('project.processor.terminationTest'),
|
title: t('project.processor.terminationTest'),
|
||||||
value: 'terminal_function',
|
value: 'ctx.getEngine().stopThreadNow(ctx.getThread().getThreadName());',
|
||||||
command: 'terminal_function',
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// 处理groovyCode 请求头
|
||||||
|
function getGroovyHeaders(requestHeaders) {
|
||||||
|
let headers = '[';
|
||||||
|
let index = 1;
|
||||||
|
// for (const [k, v] of requestHeaders) {
|
||||||
|
// if (index !== 1) {
|
||||||
|
// headers += ',';
|
||||||
|
// }
|
||||||
|
// // 拼装
|
||||||
|
// headers += `'${k}':'${v}'`;
|
||||||
|
// index++;
|
||||||
|
// }
|
||||||
|
requestHeaders.forEach(([k, v]) => {
|
||||||
|
if (index !== 1) {
|
||||||
|
headers += ',';
|
||||||
|
}
|
||||||
|
headers += `'${k}':'${v}'`;
|
||||||
|
index++;
|
||||||
|
});
|
||||||
|
headers += ']';
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
// 解析请求url
|
||||||
|
function getRequestPath(requestArgs, requestPath) {
|
||||||
|
if (requestArgs.size > 0) {
|
||||||
|
requestPath += '?';
|
||||||
|
let index = 1;
|
||||||
|
requestArgs.forEach(([k, v]) => {
|
||||||
|
if (index !== 1) {
|
||||||
|
requestPath += '&';
|
||||||
|
}
|
||||||
|
requestPath = `${requestPath + k}=${v}`;
|
||||||
|
index++;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return requestPath;
|
||||||
|
}
|
||||||
|
// 处理mockPath
|
||||||
|
function getMockPath(domain, port, socket) {
|
||||||
|
if (domain === socket || !port) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
const str = `${domain}:${port}`;
|
||||||
|
// 获取socket之后的路径
|
||||||
|
return socket.substring(str.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理请求参数
|
||||||
|
function replaceRestParams(path, restMap) {
|
||||||
|
if (!path) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
let arr = 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) {
|
||||||
|
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) {
|
||||||
|
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]) => {
|
||||||
|
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]) => {
|
||||||
|
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) {
|
||||||
|
let headers = '{';
|
||||||
|
let index = 1;
|
||||||
|
requestHeaders.forEach(([k, v]) => {
|
||||||
|
if (index !== 1) {
|
||||||
|
headers += ',';
|
||||||
|
}
|
||||||
|
// 拼装
|
||||||
|
headers += `'${k}':'${v}'`;
|
||||||
|
index++;
|
||||||
|
});
|
||||||
|
headers += '}';
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
// 获取pythonCode 模板
|
||||||
|
function _pythonCodeTemplate(obj) {
|
||||||
|
const { requestBody, requestBodyKvs, bodyType, 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]) => {
|
||||||
|
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) {
|
||||||
|
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]) => {
|
||||||
|
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) {
|
||||||
|
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) => s.toUpperCase());
|
||||||
|
const httpMethodCode = `Http${method} request = new Http${method}(uri);`;
|
||||||
|
// 设置参数
|
||||||
|
requestArguments.forEach(([k, v]) => {
|
||||||
|
uri += `.setParameter("${k}", "${v}")`;
|
||||||
|
});
|
||||||
|
if (method === 'Get' && requestBodyKvs) {
|
||||||
|
requestBodyKvs.forEach(([k, v]) => {
|
||||||
|
uri += `.setParameter("${k}", "${v}")`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let postKvsParam = '';
|
||||||
|
if (method === 'Post') {
|
||||||
|
// 设置post参数
|
||||||
|
requestBodyKvs.forEach(([k, v]) => {
|
||||||
|
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]) => {
|
||||||
|
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) {
|
||||||
|
return _beanshellTemplate(requestObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取js语言代码模版
|
||||||
|
function _jsTemplate(obj) {
|
||||||
|
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]) => {
|
||||||
|
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]) => {
|
||||||
|
connStr += `conn.setRequestProperty("${k}","${v}");\n`;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (requestMethod === 'POST' && bodyType === 'kvs') {
|
||||||
|
requestBody = '"';
|
||||||
|
requestBodyKvs.forEach(([k, v]) => {
|
||||||
|
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) {
|
||||||
|
return _jsTemplate(requestObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCodeTemplate(language: Languages, requestObj: any) {
|
||||||
|
switch (language) {
|
||||||
|
case 'groovy':
|
||||||
|
return groovyCode(requestObj);
|
||||||
|
case 'python':
|
||||||
|
return pythonCode(requestObj);
|
||||||
|
case 'beanshell':
|
||||||
|
return javaCode(requestObj);
|
||||||
|
case 'nashornScript':
|
||||||
|
return jsCode(requestObj);
|
||||||
|
case 'rhinoScript':
|
||||||
|
return jsCode(requestObj);
|
||||||
|
case 'javascript':
|
||||||
|
return jsCode(requestObj);
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default {};
|
export default {};
|
||||||
|
|
Loading…
Reference in New Issue