feat(接口场景): 场景步骤查看步骤详情
This commit is contained in:
parent
d608df0e93
commit
adb640ec13
|
@ -83,6 +83,6 @@ export const apiSocket = (url: string, host?: string) => {
|
|||
return new WebSocket(uri);
|
||||
};
|
||||
|
||||
export function getSocket(reportId: string, socketUrl?: string, host?: string) {
|
||||
export function getSocket(reportId: string | number, socketUrl?: string, host?: string) {
|
||||
return apiSocket(`${socketUrl || ConnectionWebsocketUrl}/${reportId}`, host);
|
||||
}
|
||||
|
|
|
@ -263,7 +263,7 @@
|
|||
border: 1px solid var(--color-text-input-border);
|
||||
background-color: var(--color-text-fff);
|
||||
&:not(:disabled):hover {
|
||||
border-color: rgb(var(--primary-5));
|
||||
border-color: rgb(var(--primary-5)) !important;
|
||||
background-color: white;
|
||||
}
|
||||
input::placeholder {
|
||||
|
@ -363,8 +363,20 @@
|
|||
background: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
.arco-form-item-status-success .arco-input-wrapper:not(.arco-input-disabled) {
|
||||
border-color: var(--color-text-input-border);
|
||||
.arco-form-item-status-success {
|
||||
&:hover {
|
||||
.arco-input-wrapper:not(.arco-input-disabled),
|
||||
.arco-select-view:not(.arco-select-view-disabled),
|
||||
.arco-textarea-wrapper:not(.arco-textarea-disabled) {
|
||||
background: white;
|
||||
}
|
||||
}
|
||||
.arco-input-wrapper:not(.arco-input-disabled),
|
||||
.arco-select-view:not(.arco-select-view-disabled),
|
||||
.arco-textarea-wrapper:not(.arco-textarea-disabled) {
|
||||
border-color: var(--color-text-input-border);
|
||||
background: white;
|
||||
}
|
||||
}
|
||||
.arco-form-item-message {
|
||||
width: 100%;
|
||||
|
|
|
@ -331,6 +331,7 @@ export interface ScenarioStepItem {
|
|||
projectId?: string;
|
||||
versionId?: string;
|
||||
children?: ScenarioStepItem[];
|
||||
isNew: boolean; // 是否新建的步骤,引用复制类型以此区分调用步骤详情还是资源详情
|
||||
// 页面渲染以及交互需要字段
|
||||
checked?: boolean; // 是否选中
|
||||
expanded?: boolean; // 是否展开
|
||||
|
|
|
@ -283,7 +283,6 @@
|
|||
import { cloneDeep, debounce } from 'lodash-es';
|
||||
|
||||
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||
import { TabItem } from '@/components/pure/ms-editable-tab/types';
|
||||
import MsFormCreate from '@/components/pure/ms-form-create/formCreate.vue';
|
||||
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||
import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
|
||||
|
@ -322,7 +321,6 @@
|
|||
RequestConditionProcessor,
|
||||
RequestMethods,
|
||||
ResponseComposition,
|
||||
ScenarioStepRefType,
|
||||
ScenarioStepType,
|
||||
} from '@/enums/apiEnum';
|
||||
|
||||
|
@ -349,20 +347,25 @@
|
|||
|
||||
export interface RequestCustomAttr {
|
||||
type: 'api';
|
||||
name: string;
|
||||
stepId: string | number; // 所属步骤 id
|
||||
resourceId: string | number; // 引用、复制的资源 id
|
||||
isNew: boolean;
|
||||
protocol: string;
|
||||
activeTab: RequestComposition;
|
||||
executeLoading: boolean; // 执行中loading
|
||||
isCopy?: boolean; // 是否是复制
|
||||
isExecute?: boolean; // 是否是执行
|
||||
responseActiveTab: ResponseComposition;
|
||||
unSaved: boolean;
|
||||
uploadFileIds: string[];
|
||||
linkFileIds: string[];
|
||||
}
|
||||
|
||||
export type RequestParam = ExecuteApiRequestFullParams & {
|
||||
response?: RequestTaskResult;
|
||||
customizeRequestEnvEnable: boolean;
|
||||
request?: ExecuteApiRequestFullParams; // 请求参数集合
|
||||
} & RequestCustomAttr &
|
||||
TabItem;
|
||||
} & RequestCustomAttr;
|
||||
|
||||
const props = defineProps<{
|
||||
request?: RequestParam; // 请求参数集合
|
||||
|
@ -398,8 +401,10 @@
|
|||
const loading = defineModel<boolean>('detailLoading', { default: false });
|
||||
|
||||
const defaultDebugParams: RequestParam = {
|
||||
name: '',
|
||||
type: 'api',
|
||||
id: '',
|
||||
stepId: '',
|
||||
resourceId: '',
|
||||
customizeRequestEnvEnable: false,
|
||||
protocol: 'HTTP',
|
||||
url: '',
|
||||
|
@ -607,7 +612,8 @@
|
|||
const currentPluginScript = computed<Record<string, any>[]>(
|
||||
() => pluginScriptMap.value[requestVModel.value.protocol]?.script || []
|
||||
);
|
||||
const isCopyApiNeedInit = computed(() => _stepType.value.isCopyApi && props.request?.request === null);
|
||||
// 复制 api 只要加载过一次后就会保存,所以 props.request 是不为空的
|
||||
const isCopyApiNeedInit = computed(() => _stepType.value.isCopyApi && props.request === undefined);
|
||||
const isEditableApi = computed(
|
||||
() => _stepType.value.isCopyApi || props.step?.stepType === ScenarioStepType.CUSTOM_REQUEST || !props.step
|
||||
);
|
||||
|
@ -616,7 +622,7 @@
|
|||
const handlePluginFormChange = debounce(() => {
|
||||
if (isEditableApi.value) {
|
||||
// 复制或者新建的时候需要缓存表单数据,引用的不能更改
|
||||
temporaryPluginFormMap[requestVModel.value.id] = fApi.value?.formData();
|
||||
temporaryPluginFormMap[requestVModel.value.stepId] = fApi.value?.formData();
|
||||
}
|
||||
handleActiveDebugChange();
|
||||
}, 300);
|
||||
|
@ -636,7 +642,6 @@
|
|||
if (currentFormFields && currentFormFields.length < fields.length) {
|
||||
fApi.value?.hidden(false, fields);
|
||||
fApi.value?.hidden(true, currentFormFields?.filter((e) => !fields.includes(e)) || []);
|
||||
fApi.value?.refresh();
|
||||
} else {
|
||||
// 隐藏多余的字段
|
||||
fApi.value?.hidden(true, currentFormFields?.filter((e) => !fields.includes(e)) || []);
|
||||
|
@ -648,27 +653,30 @@
|
|||
* 设置插件表单数据
|
||||
*/
|
||||
function setPluginFormData() {
|
||||
const tempForm = temporaryPluginFormMap[requestVModel.value.id];
|
||||
const tempForm = temporaryPluginFormMap[requestVModel.value.stepId];
|
||||
console.log('setPluginFormData', temporaryPluginFormMap, requestVModel.value.stepId);
|
||||
if (tempForm || !requestVModel.value.isNew) {
|
||||
// 如果缓存的表单数据存在或者是编辑状态,则需要将之前的输入数据填充
|
||||
const formData = isEditableApi.value ? tempForm || requestVModel.value : requestVModel.value;
|
||||
if (fApi.value) {
|
||||
fApi.value.nextRefresh(() => {
|
||||
const form = {};
|
||||
controlPluginFormFields().forEach((key) => {
|
||||
form[key] = formData[key];
|
||||
nextTick(() => {
|
||||
if (fApi.value) {
|
||||
fApi.value.nextRefresh(() => {
|
||||
const form = {};
|
||||
controlPluginFormFields().forEach((key) => {
|
||||
form[key] = formData[key];
|
||||
});
|
||||
fApi.value?.setValue(cloneDeep(form));
|
||||
setTimeout(() => {
|
||||
// 初始化时赋值会触发表单数据变更,300ms 是为了与 handlePluginFormChange的防抖时间保持一致
|
||||
isInitPluginForm.value = true;
|
||||
}, 300);
|
||||
});
|
||||
fApi.value?.setValue(cloneDeep(form));
|
||||
fApi.value?.clearValidateState();
|
||||
setTimeout(() => {
|
||||
// 初始化时赋值会触发表单数据变更,300ms 是为了与 handlePluginFormChange的防抖时间保持一致
|
||||
isInitPluginForm.value = true;
|
||||
}, 300);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
fApi.value?.nextTick(() => {
|
||||
nextTick(() => {
|
||||
controlPluginFormFields();
|
||||
fApi.value?.clearValidateState();
|
||||
fApi.value?.resetFields();
|
||||
isInitPluginForm.value = true;
|
||||
});
|
||||
|
@ -831,7 +839,6 @@
|
|||
return conditionCopy;
|
||||
}
|
||||
|
||||
const reportId = ref('');
|
||||
const websocket = ref<WebSocket>();
|
||||
|
||||
/**
|
||||
|
@ -839,14 +846,14 @@
|
|||
*/
|
||||
function debugSocket(executeType?: 'localExec' | 'serverExec') {
|
||||
websocket.value = getSocket(
|
||||
reportId.value,
|
||||
requestVModel.value.stepId,
|
||||
executeType === 'localExec' ? '/ws/debug' : '',
|
||||
executeType === 'localExec' ? localExecuteUrl.value : ''
|
||||
);
|
||||
websocket.value.addEventListener('message', (event) => {
|
||||
const data = JSON.parse(event.data);
|
||||
if (data.msgType === 'EXEC_RESULT') {
|
||||
if (requestVModel.value.reportId === data.reportId) {
|
||||
if (requestVModel.value.stepId === data.reportId) {
|
||||
// 判断当前查看的tab是否是当前返回的报告的tab,是的话直接赋值
|
||||
requestVModel.value.response = data.taskResult;
|
||||
requestVModel.value.executeLoading = false;
|
||||
|
@ -922,7 +929,8 @@
|
|||
}
|
||||
return {
|
||||
...requestParams,
|
||||
id: requestVModel.value.id,
|
||||
resourceId: requestVModel.value.resourceId,
|
||||
stepId: requestVModel.value.stepId,
|
||||
activeTab: requestVModel.value.protocol === 'HTTP' ? RequestComposition.HEADER : RequestComposition.PLUGIN,
|
||||
responseActiveTab: ResponseComposition.BODY,
|
||||
protocol: requestVModel.value.protocol,
|
||||
|
@ -1016,7 +1024,7 @@
|
|||
async function initQuoteApiDetail() {
|
||||
try {
|
||||
loading.value = true;
|
||||
const res = await getDefinitionDetail(requestVModel.value.id);
|
||||
const res = await getDefinitionDetail(props.step?.resourceId || '');
|
||||
let parseRequestBodyResult;
|
||||
if (res.protocol === 'HTTP') {
|
||||
parseRequestBodyResult = parseRequestBodyFiles(res.request.body); // 解析请求体中的文件,将详情中的文件 id 集合收集,更新时以判断文件是否删除以及是否新上传的文件
|
||||
|
@ -1032,9 +1040,10 @@
|
|||
response: cloneDeep(defaultResponse),
|
||||
url: res.path,
|
||||
name: res.name, // request里面还有个name但是是null
|
||||
id: res.id,
|
||||
resourceId: res.id,
|
||||
...parseRequestBodyResult,
|
||||
};
|
||||
console.log('initQuoteApiDetail', requestVModel.value);
|
||||
nextTick(() => {
|
||||
// 等待内容渲染出来再隐藏loading
|
||||
loading.value = false;
|
||||
|
@ -1054,53 +1063,26 @@
|
|||
await initProtocolList();
|
||||
}
|
||||
if (props.request) {
|
||||
// 查看自定义请求、引用 api、复制 api
|
||||
requestVModel.value = cloneDeep({
|
||||
...defaultDebugParams,
|
||||
...props.request,
|
||||
isNew: false,
|
||||
});
|
||||
if (
|
||||
_stepType.value.isQuoteApi ||
|
||||
isCopyApiNeedInit.value
|
||||
// 引用接口时,需要初始化引用接口的详情;复制只在第一次初始化的时候需要加载后台数据(request.request是复制请求时列表参数字段request会为 null,以此判断释放第一次初始化)
|
||||
) {
|
||||
if (_stepType.value.isQuoteApi) {
|
||||
// 引用接口时,每次都要获取源接口数据
|
||||
await initQuoteApiDetail();
|
||||
}
|
||||
if (
|
||||
props.step?.stepType === ScenarioStepType.API &&
|
||||
props.step?.refType === ScenarioStepRefType.REF &&
|
||||
props.request.request &&
|
||||
requestVModel.value.request
|
||||
) {
|
||||
// 初始化引用的详情后,需要要把外面传入的数据的请求头、请求体、query、rest里面的参数值写入
|
||||
['headers', 'query', 'rest'].forEach((type) => {
|
||||
props.request?.request?.[type]?.forEach((item) => {
|
||||
const index = requestVModel.value.request?.[type]?.findIndex((itemReq) => itemReq.key === item.key);
|
||||
if (index > -1 && requestVModel.value.request) {
|
||||
requestVModel.value.request[type][index].value = item.value;
|
||||
requestVModel.value[type] = requestVModel.value.request?.[type];
|
||||
}
|
||||
});
|
||||
});
|
||||
if (props.request.request.body.bodyType !== 'NONE') {
|
||||
['formDataBody', 'wwwFormBody'].forEach((type) => {
|
||||
props.request?.request?.body[type].formValues.forEach((item) => {
|
||||
const index = requestVModel.value.request?.body[type].formValues.findIndex(
|
||||
(itemReq) => itemReq.key === item.key
|
||||
);
|
||||
if (index > -1 && requestVModel.value.request?.body) {
|
||||
requestVModel.value.request.body[type].formValues[index].value = item.value;
|
||||
requestVModel.value.body = requestVModel.value.request?.body;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
handleActiveDebugProtocolChange(requestVModel.value.protocol);
|
||||
} else if (_stepType.value.isQuoteApi || isCopyApiNeedInit.value) {
|
||||
// 引用接口时,需要初始化引用接口的详情;复制只在第一次初始化的时候需要加载后台数据,复制 api 只要加载过一次后就会保存,所以 props.request 是不为空的
|
||||
await initQuoteApiDetail();
|
||||
handleActiveDebugProtocolChange(requestVModel.value.protocol);
|
||||
} else {
|
||||
// 新建自定义请求
|
||||
requestVModel.value = cloneDeep({
|
||||
...defaultDebugParams,
|
||||
id: getGenerateId(),
|
||||
stepId: getGenerateId(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,7 +121,6 @@ export default function useCreateActions() {
|
|||
}
|
||||
return {
|
||||
...cloneDeep(defaultStepItemCommon),
|
||||
...item,
|
||||
id,
|
||||
config: {
|
||||
...defaultStepItemCommon.config,
|
||||
|
|
|
@ -85,7 +85,7 @@
|
|||
@change="handleStepContentChange($event, step)"
|
||||
@click.stop
|
||||
/>
|
||||
<!-- API、CASE、场景步骤名称 -->
|
||||
<!-- 自定义请求、API、CASE、场景步骤名称 -->
|
||||
<template v-if="checkStepIsApi(step)">
|
||||
<apiMethodName v-if="checkStepShowMethod(step)" :method="step.config.method" />
|
||||
<div
|
||||
|
@ -329,6 +329,8 @@
|
|||
return quoteContent;
|
||||
}
|
||||
switch (step.stepType) {
|
||||
case ScenarioStepType.CUSTOM_REQUEST:
|
||||
return quoteContent;
|
||||
case ScenarioStepType.LOOP_CONTROLLER:
|
||||
return loopControlContent;
|
||||
case ScenarioStepType.IF_CONTROLLER:
|
||||
|
@ -595,8 +597,8 @@
|
|||
if (_stepType.isCopyApi || _stepType.isQuoteApi || step.stepType === ScenarioStepType.CUSTOM_REQUEST) {
|
||||
// 复制 api、引用 api、自定义 api打开抽屉
|
||||
activeStep.value = step;
|
||||
if (stepDetails.value[step.id] === undefined) {
|
||||
// 详情映射中没有加载过该 api 详情,说明是初次查看详情,引用的 api 不需要在这里加载详情
|
||||
if (stepDetails.value[step.id] === undefined && !step.isNew) {
|
||||
// 查看场景详情时,详情映射中没有对应数据,初始化步骤详情
|
||||
await getStepDetail(step);
|
||||
}
|
||||
customApiDrawerVisible.value = true;
|
||||
|
@ -700,14 +702,14 @@
|
|||
*/
|
||||
function addCustomApiStep(request: RequestParam) {
|
||||
request.isNew = false;
|
||||
stepDetails.value[request.id] = request;
|
||||
stepDetails.value[request.stepId] = request;
|
||||
if (activeStep.value && activeCreateAction.value) {
|
||||
handleCreateStep(
|
||||
{
|
||||
stepType: ScenarioStepType.CUSTOM_REQUEST,
|
||||
name: t('apiScenario.customApi'),
|
||||
method: request.method,
|
||||
id: request.id,
|
||||
id: request.stepId,
|
||||
projectId: appStore.currentProjectId,
|
||||
},
|
||||
activeStep.value,
|
||||
|
@ -724,7 +726,7 @@
|
|||
protocol: request.protocol,
|
||||
method: request.method,
|
||||
},
|
||||
id: request.id,
|
||||
id: request.stepId,
|
||||
sort: steps.value.length + 1,
|
||||
stepType: ScenarioStepType.CUSTOM_REQUEST,
|
||||
refType: ScenarioStepRefType.DIRECT,
|
||||
|
@ -732,6 +734,7 @@
|
|||
projectId: appStore.currentProjectId,
|
||||
});
|
||||
}
|
||||
console.log(steps.value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<MsSplitBox :size="0.7" :max="0.9" :min="0.7" direction="horizontal" expand-direction="right">
|
||||
<MsSplitBox ref="splitBoxRef" :size="0.7" :max="0.9" :min="0.7" direction="horizontal" expand-direction="right">
|
||||
<template #first>
|
||||
<a-tabs v-model:active-key="activeKey" class="h-full" animation lazy-load>
|
||||
<a-tab-pane :key="ScenarioCreateComposition.STEP" :title="t('apiScenario.step')" class="p-[16px]">
|
||||
|
@ -36,7 +36,7 @@
|
|||
<div class="p-[16px]">
|
||||
<!-- TODO:第一版没有模板 -->
|
||||
<!-- <MsFormCreate v-model:api="fApi" :rule="currentApiTemplateRules" :option="options" /> -->
|
||||
<a-form ref="activeApiTabFormRef" :model="scenario" layout="vertical">
|
||||
<a-form ref="createFormRef" :model="scenario" layout="vertical">
|
||||
<a-form-item
|
||||
field="name"
|
||||
:label="t('apiScenario.name')"
|
||||
|
@ -141,6 +141,8 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { FormInstance } from '@arco-design/web-vue';
|
||||
|
||||
import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
|
||||
import MsTagsInput from '@/components/pure/ms-tags-input/index.vue';
|
||||
import caseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
|
||||
|
@ -172,6 +174,23 @@
|
|||
const scenario = defineModel<Scenario>('scenario', {
|
||||
required: true,
|
||||
});
|
||||
|
||||
const splitBoxRef = ref<InstanceType<typeof MsSplitBox>>();
|
||||
const createFormRef = ref<FormInstance>();
|
||||
|
||||
function validScenarioForm(cb: () => Promise<void>) {
|
||||
createFormRef.value?.validate(async (errors) => {
|
||||
if (errors) {
|
||||
splitBoxRef.value?.expand();
|
||||
} else {
|
||||
cb();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
validScenarioForm,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
<div class="flex items-center justify-between p-[24px_24px_8px_24px]">
|
||||
<MsEditableTab
|
||||
v-model:active-tab="activeScenarioTab"
|
||||
v-model:tabs="apiTabs"
|
||||
v-model:tabs="scenarioTabs"
|
||||
class="flex-1 overflow-hidden"
|
||||
@add="() => newTab()"
|
||||
>
|
||||
<template #label="{ tab }">
|
||||
<a-tooltip :content="tab.label" :mouse-enter-delay="500">
|
||||
<a-tooltip :content="tab.name || tab.label" :mouse-enter-delay="500">
|
||||
<div class="one-line-text max-w-[144px]">
|
||||
{{ tab.label }}
|
||||
{{ tab.name || tab.label }}
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
|
@ -61,7 +61,7 @@
|
|||
</MsSplitBox>
|
||||
</div>
|
||||
<div v-else-if="activeScenarioTab.isNew" class="pageWrap">
|
||||
<create v-model:scenario="activeScenarioTab" :module-tree="folderTree"></create>
|
||||
<create ref="createRef" v-model:scenario="activeScenarioTab" :module-tree="folderTree"></create>
|
||||
</div>
|
||||
<div v-else class="pageWrap">
|
||||
<detail v-model:scenario="activeScenarioTab"></detail>
|
||||
|
@ -107,33 +107,33 @@
|
|||
|
||||
const { t } = useI18n();
|
||||
|
||||
const apiTabs = ref<ScenarioParams[]>([
|
||||
const scenarioTabs = ref<ScenarioParams[]>([
|
||||
{
|
||||
id: 'all',
|
||||
label: t('apiScenario.allScenario'),
|
||||
closable: false,
|
||||
} as ScenarioParams,
|
||||
]);
|
||||
const activeScenarioTab = ref<ScenarioParams>(apiTabs.value[0] as ScenarioParams);
|
||||
const activeScenarioTab = ref<ScenarioParams>(scenarioTabs.value[0] as ScenarioParams);
|
||||
|
||||
function newTab(defaultScenarioInfo?: Scenario, isCopy = false) {
|
||||
if (defaultScenarioInfo) {
|
||||
apiTabs.value.push({
|
||||
scenarioTabs.value.push({
|
||||
...defaultScenarioInfo,
|
||||
id: isCopy ? getGenerateId() : defaultScenarioInfo.id || '',
|
||||
label: isCopy ? `copy-${defaultScenarioInfo.name}` : defaultScenarioInfo.name,
|
||||
isNew: false,
|
||||
});
|
||||
} else {
|
||||
apiTabs.value.push({
|
||||
scenarioTabs.value.push({
|
||||
...cloneDeep(defaultScenario),
|
||||
id: `${t('apiScenario.createScenario')}${apiTabs.value.length}`,
|
||||
label: `${t('apiScenario.createScenario')}${apiTabs.value.length}`,
|
||||
id: getGenerateId(),
|
||||
label: `${t('apiScenario.createScenario')}${scenarioTabs.value.length}`,
|
||||
moduleId: 'root',
|
||||
priority: 'P0',
|
||||
});
|
||||
}
|
||||
activeScenarioTab.value = apiTabs.value[apiTabs.value.length - 1] as ScenarioParams;
|
||||
activeScenarioTab.value = scenarioTabs.value[scenarioTabs.value.length - 1] as ScenarioParams;
|
||||
}
|
||||
|
||||
const folderTree = ref<ModuleTreeNode[]>([]);
|
||||
|
@ -182,9 +182,10 @@
|
|||
|
||||
onBeforeMount(selectRecycleCount);
|
||||
|
||||
const createRef = ref<InstanceType<typeof create>>();
|
||||
const saveLoading = ref(false);
|
||||
|
||||
async function saveScenario() {
|
||||
async function realSaveScenario() {
|
||||
try {
|
||||
saveLoading.value = true;
|
||||
if (activeScenarioTab.value.isNew) {
|
||||
|
@ -195,7 +196,19 @@
|
|||
const scenarioDetail = await getScenarioDetail(res.id);
|
||||
scenarioDetail.stepDetails = {};
|
||||
scenarioDetail.isNew = false;
|
||||
activeScenarioTab.value = scenarioDetail as ScenarioParams;
|
||||
scenarioDetail.id = res.id;
|
||||
if (!scenarioDetail.steps) {
|
||||
scenarioDetail.steps = [];
|
||||
}
|
||||
const index = scenarioTabs.value.findIndex((e) => e.id === activeScenarioTab.value.id);
|
||||
if (index !== -1) {
|
||||
const newScenarioTab = {
|
||||
...cloneDeep(activeScenarioTab.value),
|
||||
...scenarioDetail,
|
||||
};
|
||||
scenarioTabs.value.splice(index, 1, newScenarioTab);
|
||||
activeScenarioTab.value = newScenarioTab;
|
||||
}
|
||||
} else {
|
||||
await updateScenario({
|
||||
...activeScenarioTab.value,
|
||||
|
@ -212,11 +225,22 @@
|
|||
}
|
||||
}
|
||||
|
||||
function saveScenario() {
|
||||
if (activeScenarioTab.value.isNew) {
|
||||
createRef.value?.validScenarioForm(realSaveScenario);
|
||||
} else {
|
||||
realSaveScenario();
|
||||
}
|
||||
}
|
||||
|
||||
async function openScenarioTab(record: ApiScenarioTableItem, isCopy?: boolean) {
|
||||
try {
|
||||
appStore.showLoading();
|
||||
const res = await getScenarioDetail(record.id);
|
||||
res.stepDetails = {};
|
||||
if (!res.steps) {
|
||||
res.steps = [];
|
||||
}
|
||||
newTab(res, isCopy);
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
|
|
Loading…
Reference in New Issue