diff --git a/frontend/src/api/modules/api-test/scenario.ts b/frontend/src/api/modules/api-test/scenario.ts index 12ca3b29f7..c4c92d793a 100644 --- a/frontend/src/api/modules/api-test/scenario.ts +++ b/frontend/src/api/modules/api-test/scenario.ts @@ -21,6 +21,7 @@ import { GetModuleTreeUrl, GetScenarioStepUrl, GetScenarioUrl, + GetStepProjectInfoUrl, GetSystemRequestUrl, GetTrashModuleCountUrl, GetTrashModuleTreeUrl, @@ -223,7 +224,7 @@ export function addScenario(params: Scenario) { } // 获取场景详情 -export function getScenarioDetail(id: string) { +export function getScenarioDetail(id: string | number) { return MSR.get({ url: GetScenarioUrl, params: id }); } @@ -278,3 +279,8 @@ export function updateScenarioStatus(id: string | number, status: ApiScenarioSta export function updateScenarioPro(id: string | number, priority: CaseLevel | undefined) { return MSR.get({ url: `${UpdateScenarioPriorityUrl}/${id}/${priority}` }); } + +// 获取跨项目信息 +export function getStepProjectInfo(id: string | number) { + return MSR.get({ url: GetStepProjectInfoUrl, params: id }); +} diff --git a/frontend/src/api/requrls/api-test/scenario.ts b/frontend/src/api/requrls/api-test/scenario.ts index ae012050ec..eda68fecf6 100644 --- a/frontend/src/api/requrls/api-test/scenario.ts +++ b/frontend/src/api/requrls/api-test/scenario.ts @@ -19,6 +19,7 @@ export const GetSystemRequestUrl = '/api/scenario/get/system-request'; // 获取 export const FollowScenarioUrl = '/api/scenario/follow'; // 关注/取消关注接口场景 export const ScenarioScheduleConfigUrl = '/api/scenario/schedule-config'; // 场景定时任务 export const ScenarioScheduleConfigDeleteUrl = '/api/scenario/schedule-config-delete/'; // 场景定时任务 +export const GetStepProjectInfoUrl = '/api/scenario/step/project-ifo'; // 获取跨项目信息 export const BatchRecycleScenarioUrl = '/api/scenario/batch-operation/delete-gc'; // 批量删除接口场景 export const BatchMoveScenarioUrl = '/api/scenario/batch-operation/move'; // 批量移动接口场景 export const BatchCopyScenarioUrl = '/api/scenario/batch-operation/copy'; // 批量复制接口场景 diff --git a/frontend/src/assets/style/arco-reset.less b/frontend/src/assets/style/arco-reset.less index df2788a601..5ba8328d94 100644 --- a/frontend/src/assets/style/arco-reset.less +++ b/frontend/src/assets/style/arco-reset.less @@ -739,9 +739,12 @@ .arco-switch-type-circle { background-color: var(--color-text-brand) !important; } -.arco-switch-type-circle.arco-switch-checked { +.arco-switch-type-circle.arco-switch-checked:not(:disabled) { background-color: rgb(var(--primary-5)) !important; } +.arco-switch-disabled { + background-color: rgb(var(--primary-3)) !important; +} .arco-switch-type-line.arco-switch-small { .arco-switch-handle { width: 14px; diff --git a/frontend/src/hooks/useTableStore.ts b/frontend/src/hooks/useTableStore.ts index a4179808af..95fb3e9128 100644 --- a/frontend/src/hooks/useTableStore.ts +++ b/frontend/src/hooks/useTableStore.ts @@ -4,7 +4,7 @@ import localforage from 'localforage'; import { MsTableColumn, MsTableColumnData } from '@/components/pure/ms-table/type'; import { useAppStore } from '@/store'; -import { PageSizeMap, SelectorColumnMap, TableOpenDetailMode } from '@/store/modules/components/ms-table/types'; +import { MsTableSelectorItem, PageSizeMap, TableOpenDetailMode } from '@/store/modules/components/ms-table/types'; import { isArraysEqualWithOrder } from '@/utils/equal'; import { SpecialColumnEnum } from '@/enums/tableEnum'; @@ -15,19 +15,6 @@ export default function useTableStore() { operationBaseIndex: 100, }); - const getSelectorColumnMap = async () => { - try { - const selectorColumnMap = await localforage.getItem('selectorColumnMap'); - if (!selectorColumnMap) { - return {}; - } - return selectorColumnMap; - } catch (e) { - // eslint-disable-next-line no-console - console.log(e); - return {}; - } - }; const getPageSizeMap = async () => { try { const pageSizeMap = await localforage.getItem('pageSizeMap'); @@ -77,32 +64,30 @@ export default function useTableStore() { showSubdirectory?: boolean ) { try { - const selectorColumnMap = await getSelectorColumnMap(); - if (!selectorColumnMap[tableKey]) { + const tableColumnsMap = await localforage.getItem(tableKey); + if (!tableColumnsMap) { // 如果没有在indexDB里初始化 column = columnsTransform(column); - selectorColumnMap[tableKey] = { + localforage.setItem(tableKey, { mode, showSubdirectory, column, columnBackup: JSON.parse(JSON.stringify(column)), - }; - await localforage.setItem('selectorColumnMap', selectorColumnMap); + }); } else { // 初始化过了,但是可能有新变动,如列的顺序,列的显示隐藏,列的拖拽 column = columnsTransform(column); - const { columnBackup: oldColumn } = selectorColumnMap[tableKey]; + const { columnBackup: oldColumn } = tableColumnsMap; // 比较页面上定义的 column 和 浏览器备份的column 是否相同 - const isEqual = isArraysEqualWithOrder(oldColumn, column); + const isEqual = isArraysEqualWithOrder(oldColumn, column); if (!isEqual) { // 如果不相等,说明有变动将新的column存入indexDB - selectorColumnMap[tableKey] = { + localforage.setItem(tableKey, { mode, showSubdirectory, column, columnBackup: JSON.parse(JSON.stringify(column)), - }; - await localforage.setItem('selectorColumnMap', selectorColumnMap); + }); } } } catch (e) { @@ -112,13 +97,10 @@ export default function useTableStore() { } async function setMode(key: string, mode: TableOpenDetailMode) { try { - const selectorColumnMap = await getSelectorColumnMap(); - if (selectorColumnMap[key]) { - const item = selectorColumnMap[key]; - if (item) { - item.mode = mode; - } - await localforage.setItem('selectorColumnMap', selectorColumnMap); + const tableColumnsMap = await localforage.getItem(key); + if (tableColumnsMap) { + tableColumnsMap.mode = mode; + await localforage.setItem(key, tableColumnsMap); } } catch (e) { // eslint-disable-next-line no-console @@ -128,13 +110,10 @@ export default function useTableStore() { async function setSubdirectory(key: string, val: boolean) { try { - const selectorColumnMap = await getSelectorColumnMap(); - if (selectorColumnMap[key]) { - const item = selectorColumnMap[key]; - if (item) { - item.showSubdirectory = val; - } - await localforage.setItem('selectorColumnMap', selectorColumnMap); + const tableColumnsMap = await localforage.getItem(key); + if (tableColumnsMap) { + tableColumnsMap.showSubdirectory = val; + await localforage.setItem(key, tableColumnsMap); } } catch (e) { // eslint-disable-next-line no-console @@ -155,23 +134,22 @@ export default function useTableStore() { item.sortIndex = state.baseSortIndex + idx; } }); - const selectorColumnMap = await getSelectorColumnMap(); - if (!selectorColumnMap) { + const tableColumnsMap = await localforage.getItem(key); + if (!tableColumnsMap) { return; } if (isSimple) { - const oldColumns = selectorColumnMap[key].column; + const oldColumns = tableColumnsMap.column; const operationColumn = oldColumns.find((i) => i.dataIndex === SpecialColumnEnum.OPERATION); if (operationColumn) columns.push(operationColumn); } - selectorColumnMap[key] = { + await localforage.setItem(key, { mode, showSubdirectory, column: JSON.parse(JSON.stringify(columns)), - columnBackup: selectorColumnMap[key].columnBackup, - }; - await localforage.setItem('selectorColumnMap', selectorColumnMap); + columnBackup: tableColumnsMap.columnBackup, + }); } catch (e) { // eslint-disable-next-line no-console console.error('tableStore.setColumns', e); @@ -184,25 +162,25 @@ export default function useTableStore() { } async function getMode(key: string) { - const selectorColumnMap = await getSelectorColumnMap(); - if (selectorColumnMap[key]) { - return selectorColumnMap[key].mode; + const tableColumnsMap = await localforage.getItem(key); + if (tableColumnsMap) { + return tableColumnsMap.mode; } return 'drawer'; } async function getSubShow(key: string) { - const selectorColumnMap = await getSelectorColumnMap(); - if (selectorColumnMap[key]) { - return selectorColumnMap[key].showSubdirectory; + const tableColumnsMap = await localforage.getItem(key); + if (tableColumnsMap) { + return tableColumnsMap.showSubdirectory; } return true as boolean; } async function getColumns(key: string, isSimple?: boolean) { - const selectorColumnMap = await getSelectorColumnMap(); - if (selectorColumnMap[key]) { - const tmpArr = selectorColumnMap[key].column; + const tableColumnsMap = await localforage.getItem(key); + if (tableColumnsMap) { + const tmpArr = tableColumnsMap.column; const { nonSortableColumns, couldSortableColumns } = tmpArr.reduce( (result: { nonSortableColumns: MsTableColumnData[]; couldSortableColumns: MsTableColumnData[] }, item) => { if (isSimple && item.dataIndex === SpecialColumnEnum.OPERATION) { @@ -222,9 +200,9 @@ export default function useTableStore() { return { nonSort: [], couldSort: [] }; } async function getShowInTableColumns(key: string) { - const selectorColumnMap = await getSelectorColumnMap(); - if (selectorColumnMap[key]) { - const tmpArr: MsTableColumn = selectorColumnMap[key].column; + const tableColumnsMap = await localforage.getItem(key); + if (tableColumnsMap) { + const tmpArr: MsTableColumn = tableColumnsMap.column; return orderBy( filter(tmpArr, (i) => i.showInTable), ['sortIndex'], diff --git a/frontend/src/models/apiTest/scenario.ts b/frontend/src/models/apiTest/scenario.ts index 1136c3cdff..9c74d81d0a 100644 --- a/frontend/src/models/apiTest/scenario.ts +++ b/frontend/src/models/apiTest/scenario.ts @@ -360,6 +360,7 @@ export interface ScenarioStepItem { executeStatus?: ScenarioExecuteStatus; isExecuting?: boolean; // 是否正在执行 reportId?: string | number; // 步骤单个调试时的报告id + uniqueId: string | number; // 获取报告时的步骤唯一标识(用来区分重复引用的步骤) isQuoteScenarioStep?: boolean; // 是否是引用场景下的步骤(不分是不是完全引用,只要是引用类型就是),不可修改引用 api 的参数值 isRefScenarioStep?: boolean; // 是否是完全引用的场景下的步骤,是的话不允许启用禁用 } @@ -401,7 +402,7 @@ export interface Scenario { executeTime?: string | number; // 执行时间 executeSuccessCount: number; // 执行成功数量 executeFailCount: number; // 执行失败数量 - reportId?: string | number; // 场景报告 id + reportId: string | number; // 场景报告 id stepResponses: Record>; // 步骤响应集合,key 为步骤 id,value 为步骤响应内容 isExecute?: boolean; // 是否从列表执行进去场景详情 isDebug?: boolean; // 是否调试,区分执行场景和批量调试步骤 diff --git a/frontend/src/utils/index.ts b/frontend/src/utils/index.ts index 7bfaea9b18..9ad406100d 100644 --- a/frontend/src/utils/index.ts +++ b/frontend/src/utils/index.ts @@ -198,8 +198,8 @@ export interface TreeNode { */ export function traverseTree( tree: TreeNode | TreeNode[] | T | T[], + customNodeFn: (node: TreeNode) => void, continueCondition?: (node: TreeNode) => boolean, - customNodeFn: (node: TreeNode) => TreeNode | null = (node) => node, customChildrenKey = 'children' ) { if (!Array.isArray(tree)) { @@ -215,7 +215,7 @@ export function traverseTree( // 如果有继续递归的条件,则判断是否继续递归 break; } - traverseTree(node[customChildrenKey], continueCondition, customNodeFn, customChildrenKey); + traverseTree(node[customChildrenKey], customNodeFn, continueCondition, customChildrenKey); } } } @@ -488,6 +488,7 @@ export function handleTreeDragDrop( return false; } const index = parentChildren.findIndex((node: TreeNode) => node[customKey] === dragNode[customKey]); + console.log('index', parentChildren, dragNode, index); if (index !== -1) { parentChildren.splice(index, 1); diff --git a/frontend/src/views/api-test/management/components/management/api/apiTable.vue b/frontend/src/views/api-test/management/components/management/api/apiTable.vue index 9fa1a54991..cf60baa08a 100644 --- a/frontend/src/views/api-test/management/components/management/api/apiTable.vue +++ b/frontend/src/views/api-test/management/components/management/api/apiTable.vue @@ -346,6 +346,7 @@ offspringIds: string[]; protocol: string; // 查看的协议类型 readOnly?: boolean; // 是否是只读模式 + refreshTimeStamp?: number; }>(); const emit = defineEmits<{ (e: 'openApiTab', record: ApiDefinitionDetail, isExecute?: boolean): void; @@ -358,6 +359,7 @@ const appStore = useAppStore(); const { t } = useI18n(); const { openModal } = useModal(); + const tableStore = useTableStore(); const folderTreePathMap = inject('folderTreePathMap'); const refreshModuleTree: (() => Promise) | undefined = inject('refreshModuleTree'); @@ -459,6 +461,14 @@ width: hasOperationPermission.value ? 220 : 50, }, ]; + + await tableStore.initColumn(TableKeyEnum.API_TEST, columns, 'drawer', true); + if (props.readOnly) { + columns = columns.filter( + (item) => !['version', 'createTime', 'updateTime', 'operation'].includes(item.dataIndex as string) + ); + } + const { propsRes, propsEvent, loadList, setLoadListParams, resetSelector } = useTable( getDefinitionPage, { @@ -523,7 +533,6 @@ const statusFilterVisible = ref(false); const statusFilters = ref([]); - const tableStore = useTableStore(); async function getModuleIds() { let moduleIds: string[] = []; if (props.activeModule !== 'all') { @@ -552,6 +561,15 @@ loadList(); } + watch( + () => props.refreshTimeStamp, + (val) => { + if (val) { + loadApiList(); + } + } + ); + watch( () => props.activeModule, () => { @@ -915,18 +933,6 @@ console.log(error); } } - - defineExpose({ - loadApiList, - }); - - if (!props.readOnly) { - await tableStore.initColumn(TableKeyEnum.API_TEST, columns, 'drawer', true); - } else { - columns = columns.filter( - (item) => !['version', 'createTime', 'updateTime', 'operation'].includes(item.dataIndex as string) - ); - } diff --git a/frontend/src/views/api-test/scenario/components/step/stepNodeComposition/waitTimeContent.vue b/frontend/src/views/api-test/scenario/components/step/stepNodeComposition/waitTimeContent.vue index adfa534eb3..6b0c80ca62 100644 --- a/frontend/src/views/api-test/scenario/components/step/stepNodeComposition/waitTimeContent.vue +++ b/frontend/src/views/api-test/scenario/components/step/stepNodeComposition/waitTimeContent.vue @@ -10,6 +10,7 @@ hide-button :precision="0" model-event="input" + :disabled="props.disabled" @blur="handleInputChange" >