feat(接口场景): 场景步骤查看步骤详情

This commit is contained in:
baiqi 2024-03-25 14:46:37 +08:00 committed by Craftsman
parent d608df0e93
commit adb640ec13
8 changed files with 132 additions and 92 deletions

View File

@ -83,6 +83,6 @@ export const apiSocket = (url: string, host?: string) => {
return new WebSocket(uri); 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); return apiSocket(`${socketUrl || ConnectionWebsocketUrl}/${reportId}`, host);
} }

View File

@ -263,7 +263,7 @@
border: 1px solid var(--color-text-input-border); border: 1px solid var(--color-text-input-border);
background-color: var(--color-text-fff); background-color: var(--color-text-fff);
&:not(:disabled):hover { &:not(:disabled):hover {
border-color: rgb(var(--primary-5)); border-color: rgb(var(--primary-5)) !important;
background-color: white; background-color: white;
} }
input::placeholder { input::placeholder {
@ -363,8 +363,20 @@
background: none; background: none;
box-shadow: none; box-shadow: none;
} }
.arco-form-item-status-success .arco-input-wrapper:not(.arco-input-disabled) { .arco-form-item-status-success {
border-color: var(--color-text-input-border); &: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 { .arco-form-item-message {
width: 100%; width: 100%;

View File

@ -331,6 +331,7 @@ export interface ScenarioStepItem {
projectId?: string; projectId?: string;
versionId?: string; versionId?: string;
children?: ScenarioStepItem[]; children?: ScenarioStepItem[];
isNew: boolean; // 是否新建的步骤,引用复制类型以此区分调用步骤详情还是资源详情
// 页面渲染以及交互需要字段 // 页面渲染以及交互需要字段
checked?: boolean; // 是否选中 checked?: boolean; // 是否选中
expanded?: boolean; // 是否展开 expanded?: boolean; // 是否展开

View File

@ -283,7 +283,6 @@
import { cloneDeep, debounce } from 'lodash-es'; import { cloneDeep, debounce } from 'lodash-es';
import MsDrawer from '@/components/pure/ms-drawer/index.vue'; 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 MsFormCreate from '@/components/pure/ms-form-create/formCreate.vue';
import MsIcon from '@/components/pure/ms-icon-font/index.vue'; import MsIcon from '@/components/pure/ms-icon-font/index.vue';
import MsSplitBox from '@/components/pure/ms-split-box/index.vue'; import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
@ -322,7 +321,6 @@
RequestConditionProcessor, RequestConditionProcessor,
RequestMethods, RequestMethods,
ResponseComposition, ResponseComposition,
ScenarioStepRefType,
ScenarioStepType, ScenarioStepType,
} from '@/enums/apiEnum'; } from '@/enums/apiEnum';
@ -349,20 +347,25 @@
export interface RequestCustomAttr { export interface RequestCustomAttr {
type: 'api'; type: 'api';
name: string;
stepId: string | number; // id
resourceId: string | number; // id
isNew: boolean; isNew: boolean;
protocol: string; protocol: string;
activeTab: RequestComposition; activeTab: RequestComposition;
executeLoading: boolean; // loading executeLoading: boolean; // loading
isCopy?: boolean; // isCopy?: boolean; //
isExecute?: boolean; // isExecute?: boolean; //
responseActiveTab: ResponseComposition;
unSaved: boolean;
uploadFileIds: string[];
linkFileIds: string[];
} }
export type RequestParam = ExecuteApiRequestFullParams & { export type RequestParam = ExecuteApiRequestFullParams & {
response?: RequestTaskResult; response?: RequestTaskResult;
customizeRequestEnvEnable: boolean; customizeRequestEnvEnable: boolean;
request?: ExecuteApiRequestFullParams; // } & RequestCustomAttr;
} & RequestCustomAttr &
TabItem;
const props = defineProps<{ const props = defineProps<{
request?: RequestParam; // request?: RequestParam; //
@ -398,8 +401,10 @@
const loading = defineModel<boolean>('detailLoading', { default: false }); const loading = defineModel<boolean>('detailLoading', { default: false });
const defaultDebugParams: RequestParam = { const defaultDebugParams: RequestParam = {
name: '',
type: 'api', type: 'api',
id: '', stepId: '',
resourceId: '',
customizeRequestEnvEnable: false, customizeRequestEnvEnable: false,
protocol: 'HTTP', protocol: 'HTTP',
url: '', url: '',
@ -607,7 +612,8 @@
const currentPluginScript = computed<Record<string, any>[]>( const currentPluginScript = computed<Record<string, any>[]>(
() => pluginScriptMap.value[requestVModel.value.protocol]?.script || [] () => 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( const isEditableApi = computed(
() => _stepType.value.isCopyApi || props.step?.stepType === ScenarioStepType.CUSTOM_REQUEST || !props.step () => _stepType.value.isCopyApi || props.step?.stepType === ScenarioStepType.CUSTOM_REQUEST || !props.step
); );
@ -616,7 +622,7 @@
const handlePluginFormChange = debounce(() => { const handlePluginFormChange = debounce(() => {
if (isEditableApi.value) { if (isEditableApi.value) {
// //
temporaryPluginFormMap[requestVModel.value.id] = fApi.value?.formData(); temporaryPluginFormMap[requestVModel.value.stepId] = fApi.value?.formData();
} }
handleActiveDebugChange(); handleActiveDebugChange();
}, 300); }, 300);
@ -636,7 +642,6 @@
if (currentFormFields && currentFormFields.length < fields.length) { if (currentFormFields && currentFormFields.length < fields.length) {
fApi.value?.hidden(false, fields); fApi.value?.hidden(false, fields);
fApi.value?.hidden(true, currentFormFields?.filter((e) => !fields.includes(e)) || []); fApi.value?.hidden(true, currentFormFields?.filter((e) => !fields.includes(e)) || []);
fApi.value?.refresh();
} else { } else {
// //
fApi.value?.hidden(true, currentFormFields?.filter((e) => !fields.includes(e)) || []); fApi.value?.hidden(true, currentFormFields?.filter((e) => !fields.includes(e)) || []);
@ -648,27 +653,30 @@
* 设置插件表单数据 * 设置插件表单数据
*/ */
function setPluginFormData() { 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) { if (tempForm || !requestVModel.value.isNew) {
// //
const formData = isEditableApi.value ? tempForm || requestVModel.value : requestVModel.value; const formData = isEditableApi.value ? tempForm || requestVModel.value : requestVModel.value;
if (fApi.value) { nextTick(() => {
fApi.value.nextRefresh(() => { if (fApi.value) {
const form = {}; fApi.value.nextRefresh(() => {
controlPluginFormFields().forEach((key) => { const form = {};
form[key] = formData[key]; 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 { } else {
fApi.value?.nextTick(() => { nextTick(() => {
controlPluginFormFields(); controlPluginFormFields();
fApi.value?.clearValidateState();
fApi.value?.resetFields(); fApi.value?.resetFields();
isInitPluginForm.value = true; isInitPluginForm.value = true;
}); });
@ -831,7 +839,6 @@
return conditionCopy; return conditionCopy;
} }
const reportId = ref('');
const websocket = ref<WebSocket>(); const websocket = ref<WebSocket>();
/** /**
@ -839,14 +846,14 @@
*/ */
function debugSocket(executeType?: 'localExec' | 'serverExec') { function debugSocket(executeType?: 'localExec' | 'serverExec') {
websocket.value = getSocket( websocket.value = getSocket(
reportId.value, requestVModel.value.stepId,
executeType === 'localExec' ? '/ws/debug' : '', executeType === 'localExec' ? '/ws/debug' : '',
executeType === 'localExec' ? localExecuteUrl.value : '' executeType === 'localExec' ? localExecuteUrl.value : ''
); );
websocket.value.addEventListener('message', (event) => { websocket.value.addEventListener('message', (event) => {
const data = JSON.parse(event.data); const data = JSON.parse(event.data);
if (data.msgType === 'EXEC_RESULT') { if (data.msgType === 'EXEC_RESULT') {
if (requestVModel.value.reportId === data.reportId) { if (requestVModel.value.stepId === data.reportId) {
// tabtab // tabtab
requestVModel.value.response = data.taskResult; requestVModel.value.response = data.taskResult;
requestVModel.value.executeLoading = false; requestVModel.value.executeLoading = false;
@ -922,7 +929,8 @@
} }
return { return {
...requestParams, ...requestParams,
id: requestVModel.value.id, resourceId: requestVModel.value.resourceId,
stepId: requestVModel.value.stepId,
activeTab: requestVModel.value.protocol === 'HTTP' ? RequestComposition.HEADER : RequestComposition.PLUGIN, activeTab: requestVModel.value.protocol === 'HTTP' ? RequestComposition.HEADER : RequestComposition.PLUGIN,
responseActiveTab: ResponseComposition.BODY, responseActiveTab: ResponseComposition.BODY,
protocol: requestVModel.value.protocol, protocol: requestVModel.value.protocol,
@ -1016,7 +1024,7 @@
async function initQuoteApiDetail() { async function initQuoteApiDetail() {
try { try {
loading.value = true; loading.value = true;
const res = await getDefinitionDetail(requestVModel.value.id); const res = await getDefinitionDetail(props.step?.resourceId || '');
let parseRequestBodyResult; let parseRequestBodyResult;
if (res.protocol === 'HTTP') { if (res.protocol === 'HTTP') {
parseRequestBodyResult = parseRequestBodyFiles(res.request.body); // id parseRequestBodyResult = parseRequestBodyFiles(res.request.body); // id
@ -1032,9 +1040,10 @@
response: cloneDeep(defaultResponse), response: cloneDeep(defaultResponse),
url: res.path, url: res.path,
name: res.name, // requestnamenull name: res.name, // requestnamenull
id: res.id, resourceId: res.id,
...parseRequestBodyResult, ...parseRequestBodyResult,
}; };
console.log('initQuoteApiDetail', requestVModel.value);
nextTick(() => { nextTick(() => {
// loading // loading
loading.value = false; loading.value = false;
@ -1054,53 +1063,26 @@
await initProtocolList(); await initProtocolList();
} }
if (props.request) { if (props.request) {
// api api
requestVModel.value = cloneDeep({ requestVModel.value = cloneDeep({
...defaultDebugParams, ...defaultDebugParams,
...props.request, ...props.request,
isNew: false, isNew: false,
}); });
if ( if (_stepType.value.isQuoteApi) {
_stepType.value.isQuoteApi || //
isCopyApiNeedInit.value
// (request.requestrequest null)
) {
await initQuoteApiDetail(); await initQuoteApiDetail();
} }
if ( handleActiveDebugProtocolChange(requestVModel.value.protocol);
props.step?.stepType === ScenarioStepType.API && } else if (_stepType.value.isQuoteApi || isCopyApiNeedInit.value) {
props.step?.refType === ScenarioStepRefType.REF && // api props.request
props.request.request && await initQuoteApiDetail();
requestVModel.value.request
) {
// queryrest
['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); handleActiveDebugProtocolChange(requestVModel.value.protocol);
} else { } else {
//
requestVModel.value = cloneDeep({ requestVModel.value = cloneDeep({
...defaultDebugParams, ...defaultDebugParams,
id: getGenerateId(), stepId: getGenerateId(),
}); });
} }
} }

View File

@ -121,7 +121,6 @@ export default function useCreateActions() {
} }
return { return {
...cloneDeep(defaultStepItemCommon), ...cloneDeep(defaultStepItemCommon),
...item,
id, id,
config: { config: {
...defaultStepItemCommon.config, ...defaultStepItemCommon.config,

View File

@ -85,7 +85,7 @@
@change="handleStepContentChange($event, step)" @change="handleStepContentChange($event, step)"
@click.stop @click.stop
/> />
<!-- APICASE场景步骤名称 --> <!-- 自定义请求APICASE场景步骤名称 -->
<template v-if="checkStepIsApi(step)"> <template v-if="checkStepIsApi(step)">
<apiMethodName v-if="checkStepShowMethod(step)" :method="step.config.method" /> <apiMethodName v-if="checkStepShowMethod(step)" :method="step.config.method" />
<div <div
@ -329,6 +329,8 @@
return quoteContent; return quoteContent;
} }
switch (step.stepType) { switch (step.stepType) {
case ScenarioStepType.CUSTOM_REQUEST:
return quoteContent;
case ScenarioStepType.LOOP_CONTROLLER: case ScenarioStepType.LOOP_CONTROLLER:
return loopControlContent; return loopControlContent;
case ScenarioStepType.IF_CONTROLLER: case ScenarioStepType.IF_CONTROLLER:
@ -595,8 +597,8 @@
if (_stepType.isCopyApi || _stepType.isQuoteApi || step.stepType === ScenarioStepType.CUSTOM_REQUEST) { if (_stepType.isCopyApi || _stepType.isQuoteApi || step.stepType === ScenarioStepType.CUSTOM_REQUEST) {
// api api api // api api api
activeStep.value = step; activeStep.value = step;
if (stepDetails.value[step.id] === undefined) { if (stepDetails.value[step.id] === undefined && !step.isNew) {
// api api //
await getStepDetail(step); await getStepDetail(step);
} }
customApiDrawerVisible.value = true; customApiDrawerVisible.value = true;
@ -700,14 +702,14 @@
*/ */
function addCustomApiStep(request: RequestParam) { function addCustomApiStep(request: RequestParam) {
request.isNew = false; request.isNew = false;
stepDetails.value[request.id] = request; stepDetails.value[request.stepId] = request;
if (activeStep.value && activeCreateAction.value) { if (activeStep.value && activeCreateAction.value) {
handleCreateStep( handleCreateStep(
{ {
stepType: ScenarioStepType.CUSTOM_REQUEST, stepType: ScenarioStepType.CUSTOM_REQUEST,
name: t('apiScenario.customApi'), name: t('apiScenario.customApi'),
method: request.method, method: request.method,
id: request.id, id: request.stepId,
projectId: appStore.currentProjectId, projectId: appStore.currentProjectId,
}, },
activeStep.value, activeStep.value,
@ -724,7 +726,7 @@
protocol: request.protocol, protocol: request.protocol,
method: request.method, method: request.method,
}, },
id: request.id, id: request.stepId,
sort: steps.value.length + 1, sort: steps.value.length + 1,
stepType: ScenarioStepType.CUSTOM_REQUEST, stepType: ScenarioStepType.CUSTOM_REQUEST,
refType: ScenarioStepRefType.DIRECT, refType: ScenarioStepRefType.DIRECT,
@ -732,6 +734,7 @@
projectId: appStore.currentProjectId, projectId: appStore.currentProjectId,
}); });
} }
console.log(steps.value);
} }
/** /**

View File

@ -1,5 +1,5 @@
<template> <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> <template #first>
<a-tabs v-model:active-key="activeKey" class="h-full" animation lazy-load> <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]"> <a-tab-pane :key="ScenarioCreateComposition.STEP" :title="t('apiScenario.step')" class="p-[16px]">
@ -36,7 +36,7 @@
<div class="p-[16px]"> <div class="p-[16px]">
<!-- TODO:第一版没有模板 --> <!-- TODO:第一版没有模板 -->
<!-- <MsFormCreate v-model:api="fApi" :rule="currentApiTemplateRules" :option="options" /> --> <!-- <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 <a-form-item
field="name" field="name"
:label="t('apiScenario.name')" :label="t('apiScenario.name')"
@ -141,6 +141,8 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { FormInstance } from '@arco-design/web-vue';
import MsSplitBox from '@/components/pure/ms-split-box/index.vue'; import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
import MsTagsInput from '@/components/pure/ms-tags-input/index.vue'; import MsTagsInput from '@/components/pure/ms-tags-input/index.vue';
import caseLevel from '@/components/business/ms-case-associate/caseLevel.vue'; import caseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
@ -172,6 +174,23 @@
const scenario = defineModel<Scenario>('scenario', { const scenario = defineModel<Scenario>('scenario', {
required: true, 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> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@ -3,14 +3,14 @@
<div class="flex items-center justify-between p-[24px_24px_8px_24px]"> <div class="flex items-center justify-between p-[24px_24px_8px_24px]">
<MsEditableTab <MsEditableTab
v-model:active-tab="activeScenarioTab" v-model:active-tab="activeScenarioTab"
v-model:tabs="apiTabs" v-model:tabs="scenarioTabs"
class="flex-1 overflow-hidden" class="flex-1 overflow-hidden"
@add="() => newTab()" @add="() => newTab()"
> >
<template #label="{ tab }"> <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]"> <div class="one-line-text max-w-[144px]">
{{ tab.label }} {{ tab.name || tab.label }}
</div> </div>
</a-tooltip> </a-tooltip>
</template> </template>
@ -61,7 +61,7 @@
</MsSplitBox> </MsSplitBox>
</div> </div>
<div v-else-if="activeScenarioTab.isNew" class="pageWrap"> <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>
<div v-else class="pageWrap"> <div v-else class="pageWrap">
<detail v-model:scenario="activeScenarioTab"></detail> <detail v-model:scenario="activeScenarioTab"></detail>
@ -107,33 +107,33 @@
const { t } = useI18n(); const { t } = useI18n();
const apiTabs = ref<ScenarioParams[]>([ const scenarioTabs = ref<ScenarioParams[]>([
{ {
id: 'all', id: 'all',
label: t('apiScenario.allScenario'), label: t('apiScenario.allScenario'),
closable: false, closable: false,
} as ScenarioParams, } 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) { function newTab(defaultScenarioInfo?: Scenario, isCopy = false) {
if (defaultScenarioInfo) { if (defaultScenarioInfo) {
apiTabs.value.push({ scenarioTabs.value.push({
...defaultScenarioInfo, ...defaultScenarioInfo,
id: isCopy ? getGenerateId() : defaultScenarioInfo.id || '', id: isCopy ? getGenerateId() : defaultScenarioInfo.id || '',
label: isCopy ? `copy-${defaultScenarioInfo.name}` : defaultScenarioInfo.name, label: isCopy ? `copy-${defaultScenarioInfo.name}` : defaultScenarioInfo.name,
isNew: false, isNew: false,
}); });
} else { } else {
apiTabs.value.push({ scenarioTabs.value.push({
...cloneDeep(defaultScenario), ...cloneDeep(defaultScenario),
id: `${t('apiScenario.createScenario')}${apiTabs.value.length}`, id: getGenerateId(),
label: `${t('apiScenario.createScenario')}${apiTabs.value.length}`, label: `${t('apiScenario.createScenario')}${scenarioTabs.value.length}`,
moduleId: 'root', moduleId: 'root',
priority: 'P0', 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[]>([]); const folderTree = ref<ModuleTreeNode[]>([]);
@ -182,9 +182,10 @@
onBeforeMount(selectRecycleCount); onBeforeMount(selectRecycleCount);
const createRef = ref<InstanceType<typeof create>>();
const saveLoading = ref(false); const saveLoading = ref(false);
async function saveScenario() { async function realSaveScenario() {
try { try {
saveLoading.value = true; saveLoading.value = true;
if (activeScenarioTab.value.isNew) { if (activeScenarioTab.value.isNew) {
@ -195,7 +196,19 @@
const scenarioDetail = await getScenarioDetail(res.id); const scenarioDetail = await getScenarioDetail(res.id);
scenarioDetail.stepDetails = {}; scenarioDetail.stepDetails = {};
scenarioDetail.isNew = false; 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 { } else {
await updateScenario({ await updateScenario({
...activeScenarioTab.value, ...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) { async function openScenarioTab(record: ApiScenarioTableItem, isCopy?: boolean) {
try { try {
appStore.showLoading(); appStore.showLoading();
const res = await getScenarioDetail(record.id); const res = await getScenarioDetail(record.id);
res.stepDetails = {}; res.stepDetails = {};
if (!res.steps) {
res.steps = [];
}
newTab(res, isCopy); newTab(res, isCopy);
} catch (error) { } catch (error) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console