feat(环境管理): 断言-请求体-文档

This commit is contained in:
RubyLiu 2024-02-23 20:04:48 +08:00 committed by 刘瑞斌
parent 1ca47f0481
commit 18ac2c019d
9 changed files with 365 additions and 131 deletions

View File

@ -167,7 +167,7 @@
</template> </template>
</paramsTable> </paramsTable>
</div> </div>
<div v-if="activeTab === 'document'"> <div v-if="activeTab === 'document'" class="relative mt-[16px]">
<paramsTable <paramsTable
v-model:params="innerParams.document.data" v-model:params="innerParams.document.data"
:selectable="false" :selectable="false"
@ -175,7 +175,9 @@
:scroll="{ :scroll="{
minWidth: '700px', minWidth: '700px',
}" }"
:height-used="580"
:default-param-item="documentDefaultParamItem" :default-param-item="documentDefaultParamItem"
:span-method="documentSpanMethod"
@change="handleChange" @change="handleChange"
@more-action-select="(e,r)=> handleExtractParamMoreActionSelect(e,r as ExpressionConfig)" @more-action-select="(e,r)=> handleExtractParamMoreActionSelect(e,r as ExpressionConfig)"
> >
@ -183,17 +185,17 @@
<a-tooltip v-if="['object', 'array'].includes(record.paramType)" :content="t('ms.assertion.addChild')"> <a-tooltip v-if="['object', 'array'].includes(record.paramType)" :content="t('ms.assertion.addChild')">
<div <div
class="flex h-[24px] w-[24px] cursor-pointer items-center justify-center rounded text-[rgb(var(--primary-5))] hover:bg-[rgb(var(--primary-1))]" class="flex h-[24px] w-[24px] cursor-pointer items-center justify-center rounded text-[rgb(var(--primary-5))] hover:bg-[rgb(var(--primary-1))]"
@click="addChild" @click="addChild(record)"
> >
<icon-plus size="14" /> <icon-plus size="16" />
</div> </div>
</a-tooltip> </a-tooltip>
<a-tooltip v-else :content="t('ms.assertion.validateChild')"> <a-tooltip v-else :content="t('ms.assertion.validateChild')">
<div <div
class="flex h-[24px] w-[24px] cursor-pointer items-center justify-center rounded text-[rgb(var(--primary-5))] hover:bg-[rgb(var(--primary-1))]" class="flex h-[24px] w-[24px] cursor-pointer items-center justify-center rounded text-[rgb(var(--primary-5))] hover:bg-[rgb(var(--primary-1))]"
@click="addValidateChild" @click="addValidateChild(record)"
> >
<icon-bookmark size="14" /> <icon-bookmark size="16" />
</div> </div>
</a-tooltip> </a-tooltip>
</template> </template>
@ -288,14 +290,18 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { TableColumnData, TableData } from '@arco-design/web-vue';
import { statusCodeOptions } from '@/components/pure/ms-advance-filter'; import { statusCodeOptions } from '@/components/pure/ms-advance-filter';
import { ActionsItem } from '@/components/pure/ms-table-more-action/types'; import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
import { TableOperationColumn } from '../../ms-user-group-comp/authTable.vue';
import conditionContent from '@/views/api-test/components/condition/content.vue'; import conditionContent from '@/views/api-test/components/condition/content.vue';
import fastExtraction from '@/views/api-test/components/fastExtraction/index.vue'; import fastExtraction from '@/views/api-test/components/fastExtraction/index.vue';
import moreSetting from '@/views/api-test/components/fastExtraction/moreSetting.vue'; import moreSetting from '@/views/api-test/components/fastExtraction/moreSetting.vue';
import paramsTable, { type ParamTableColumn } from '@/views/api-test/components/paramTable.vue'; import paramsTable, { type ParamTableColumn } from '@/views/api-test/components/paramTable.vue';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import { findFirstByGroupId, insertTreeByCurrentId, insertTreeByGroupId } from '@/utils/tree';
import { import {
ExecuteConditionProcessor, ExecuteConditionProcessor,
@ -359,7 +365,7 @@
script: new Date().getTime().toString(), script: new Date().getTime().toString(),
}, },
}); });
const activeTab = ref('jsonPath'); const activeTab = ref('document');
const extractParamsTableRef = ref<InstanceType<typeof paramsTable>>(); const extractParamsTableRef = ref<InstanceType<typeof paramsTable>>();
const fastExtractionVisible = ref(false); const fastExtractionVisible = ref(false);
const disabledExpressionSuffix = ref(false); const disabledExpressionSuffix = ref(false);
@ -394,12 +400,14 @@
title: 'ms.assertion.expression', title: 'ms.assertion.expression',
dataIndex: 'expression', dataIndex: 'expression',
slotName: 'expression', slotName: 'expression',
width: 300,
}, },
{ {
title: 'ms.assertion.matchCondition', title: 'ms.assertion.matchCondition',
dataIndex: 'matchCondition', dataIndex: 'matchCondition',
slotName: 'matchCondition', slotName: 'matchCondition',
options: statusCodeOptions, options: statusCodeOptions,
width: 120,
}, },
{ {
title: 'ms.assertion.matchValue', title: 'ms.assertion.matchValue',
@ -473,6 +481,7 @@
title: 'ms.assertion.paramsName', title: 'ms.assertion.paramsName',
dataIndex: 'paramsName', dataIndex: 'paramsName',
slotName: 'key', slotName: 'key',
width: 300,
}, },
{ {
title: 'ms.assertion.mustInclude', title: 'ms.assertion.mustInclude',
@ -480,6 +489,7 @@
slotName: 'mustContain', slotName: 'mustContain',
titleSlotName: 'documentMustIncludeTitle', titleSlotName: 'documentMustIncludeTitle',
align: 'left', align: 'left',
width: 80,
}, },
{ {
title: 'ms.assertion.typeChecking', title: 'ms.assertion.typeChecking',
@ -487,6 +497,7 @@
slotName: 'typeChecking', slotName: 'typeChecking',
titleSlotName: 'documentTypeCheckingTitle', titleSlotName: 'documentTypeCheckingTitle',
align: 'left', align: 'left',
width: 100,
}, },
{ {
title: 'project.environmental.paramType', title: 'project.environmental.paramType',
@ -522,7 +533,8 @@
title: '', title: '',
slotName: 'operation', slotName: 'operation',
fixed: 'right', fixed: 'right',
width: 130, width: 60,
align: 'right',
}, },
]; ];
const documentDefaultParamItem = { const documentDefaultParamItem = {
@ -602,21 +614,71 @@
const addChild = (record: Record<string, any>) => { const addChild = (record: Record<string, any>) => {
const children = record.children || []; const children = record.children || [];
const newRecord = { const newRecord = {
...documentDefaultParamItem,
id: new Date().getTime(), id: new Date().getTime(),
parentId: record.id, parentId: record.id,
rowIndex: children.length,
}; };
record.children = [...children, newRecord]; record.children = [...children, newRecord];
}; };
// //
const addValidateChild = (record: Record<string, any>) => { const addValidateChild = (record: Record<string, any>) => {
const children = record.children || []; if (record.groupId) {
const newRecord = { //
id: new Date().getTime(), const parent = innerParams.value.document.data.find((item: any) => item.id === record.groupId);
parentId: record.id, insertTreeByCurrentId(innerParams.value.document.data, record.id, {
rowIndex: children.length, ...documentDefaultParamItem,
}; id: new Date().getTime(),
record.children = [...children, newRecord]; groupId: parent ? parent.id : record.groupId,
});
if (parent) {
parent.rowSpan = parent.rowSpan ? parent.rowSpan + 1 : 2;
} else {
//
const fisrtChildNode = findFirstByGroupId(innerParams.value.document.data, record.groupId);
if (fisrtChildNode) {
fisrtChildNode.rowSpan = fisrtChildNode.rowSpan ? fisrtChildNode.rowSpan + 1 : 2;
}
}
} else {
//
insertTreeByCurrentId(innerParams.value.document.data, record.id, {
...documentDefaultParamItem,
id: new Date().getTime(),
groupId: record.id,
});
}
};
const documentSpanMethod = (data: {
record: TableData;
column: TableColumnData | TableOperationColumn;
rowIndex: number;
columnIndex: number;
}): { rowspan?: number; colspan?: number } | void => {
// groupId idid
// groupId rowspan,
const { record, column } = data;
const currentColumn = column as TableColumnData;
if (record.rowSpan > 1) {
if (currentColumn.slotName === 'key') {
return {
rowspan: record.rowSpan,
colspan: 1,
};
}
if (currentColumn.slotName === 'operation') {
return {
rowspan: record.rowSpan,
colspan: 1,
};
}
if (currentColumn.slotName === 'mustContain') {
return {
rowspan: record.rowSpan,
colspan: 3,
};
}
}
return { rowspan: record.rowSpan, colspan: 1 };
}; };
</script> </script>

View File

@ -194,9 +194,11 @@
</slot> </slot>
</div> </div>
</template> </template>
<template #expand-icon="{ expanded }"> <template #expand-icon="{ expanded, record }">
<MsIcon v-if="!expanded" :size="8" type="icon-icon_right_outlined" class="text-[var(--color-text-4)]" /> <slot name="expand-icon" v-bind="{ expanded, record }">
<MsIcon v-else :size="8" class="text-[rgb(var(--primary-6))]" type="icon-icon_down_outlined" /> <MsIcon v-if="!expanded" :size="8" type="icon-icon_right_outlined" class="text-[var(--color-text-4)]" />
<MsIcon v-else :size="8" class="text-[rgb(var(--primary-6))]" type="icon-icon_down_outlined" />
</slot>
</template> </template>
</a-table> </a-table>
<div <div
@ -700,7 +702,7 @@
height: 16px; height: 16px;
border: none; border: none;
border-radius: 50%; border-radius: 50%;
background: var(--color-text-n8) !important; background: var(--color-text-n8);
} }
:deep(.arco-table .arco-table-expand-btn:hover) { :deep(.arco-table .arco-table-expand-btn:hover) {
border-color: transparent; border-color: transparent;

View File

@ -166,6 +166,14 @@
loadColumn(props.tableKey); loadColumn(props.tableKey);
} }
}); });
watch(
() => props.visible,
(value) => {
if (value) {
hasChange.value = false;
}
}
);
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@ -23,7 +23,7 @@ export default {
drawer: 'Drawer', drawer: 'Drawer',
newWindow: 'New Window', newWindow: 'New Window',
header: 'Header Settings', header: 'Header Settings',
resetDefault: 'Reset default', resetDefault: 'Undo Changes',
nonSort: 'The above properties cannot be sorted', nonSort: 'The above properties cannot be sorted',
tooltipContentDrawer: 'Drawer: open a new page as a drawer', tooltipContentDrawer: 'Drawer: open a new page as a drawer',
tooltipContentWindow: 'New Window: open a new page with a new page', tooltipContentWindow: 'New Window: open a new page with a new page',

View File

@ -23,7 +23,7 @@ export default {
drawer: '抽屉', drawer: '抽屉',
newWindow: '新窗口', newWindow: '新窗口',
header: '表头设置', header: '表头设置',
resetDefault: '恢复默认', resetDefault: '撤销修改',
nonSort: '以上属性不可排序', nonSort: '以上属性不可排序',
tooltipContentDrawer: '抽屉:以抽屉形式打开新页面', tooltipContentDrawer: '抽屉:以抽屉形式打开新页面',
tooltipContentWindow: '新窗口:以新开网页打开新页面', tooltipContentWindow: '新窗口:以新开网页打开新页面',

View File

@ -0,0 +1,72 @@
interface TreeData {
id: number;
groupId?: number;
children?: TreeData[];
[key: string]: any;
}
export function insertTreeByCurrentId(tree: TreeData[], currentId: number, newData: TreeData) {
const stack: Array<{ node: TreeData; parent: TreeData | null }> = tree.map((node) => ({ node, parent: null }));
while (stack.length > 0) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const { node, parent } = stack.pop()!;
if (parent && parent.children) {
const index = parent.children.findIndex((child) => child.id === currentId);
if (index !== -1) {
// 在目标节点后面插入新数据
parent.children.splice(index + 1, 0, newData);
return true;
}
}
if (node.children) {
node.children.forEach((child) => {
stack.push({ node: child, parent: node });
});
}
}
return false;
}
export function insertTreeByGroupId(tree: TreeData[], currentId: number, newData: TreeData) {
const stack: Array<{ node: TreeData; parent: TreeData | null }> = tree.map((node) => ({ node, parent: null }));
while (stack.length > 0) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const { node, parent } = stack.pop()!;
if (parent && parent.children) {
const index = parent.children.findIndex((child) => child.groupId === currentId);
if (index !== -1) {
// 在目标节点后面插入新数据
parent.children.splice(index + 1, 0, newData);
return true;
}
}
if (node.children) {
node.children.forEach((child) => {
stack.push({ node: child, parent: node });
});
}
}
return false;
}
export function findFirstByGroupId(tree: TreeData[], groupId: number): TreeData | null {
const queue: TreeData[] = [...tree];
while (queue.length > 0) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const node = queue.shift()!; // 取出队列的第一个元素
if (node.groupId === groupId) {
return node; // 如果匹配,返回当前节点
}
if (node.children) {
queue.push(...node.children);
}
}
return null;
}

View File

@ -1,5 +1,19 @@
<template> <template>
<MsBaseTable v-bind="propsRes" :hoverable="false" no-disable is-simple-setting v-on="propsEvent"> <MsBaseTable
v-bind="propsRes"
:hoverable="false"
no-disable
is-simple-setting
:span-method="props.spanMethod"
v-on="propsEvent"
>
<!-- 展开行-->
<template #expand-icon="{ record }">
<div class="flex flex-row items-center gap-[2px] text-[var(--color-text-4)]">
<icon-branch class="scale-y-[-1]" />
<span v-if="record.children">{{ record.children.length }}</span>
</div>
</template>
<!-- 表格头 slot --> <!-- 表格头 slot -->
<template #encodeTitle> <template #encodeTitle>
<div class="flex items-center text-[var(--color-text-3)]"> <div class="flex items-center text-[var(--color-text-3)]">
@ -224,42 +238,49 @@
@change="() => addTableLine(rowIndex)" @change="() => addTableLine(rowIndex)"
/> />
</template> </template>
<template #mustContain="{ record, columnConfig, rowIndex }"> <template #mustContain="{ record, columnConfig }">
<a-checkbox <a-checkbox
v-model:model-value="record[columnConfig.dataIndex as string]" v-model:model-value="record[columnConfig.dataIndex as string]"
@change="() => addTableLine(rowIndex)" @change="handleMustContainColChange(false)"
/>
</template>
<template #typeChecking="{ record, columnConfig }">
<a-checkbox
v-model:model-value="record[columnConfig.dataIndex as string]"
@change="handleTypeCheckingColChange(false)"
/> />
</template> </template>
<template #operation="{ record, rowIndex, columnConfig }"> <template #operation="{ record, rowIndex, columnConfig }">
<a-switch <div class="flex flex-row items-center">
v-if="columnConfig.hasDisable" <a-switch
v-model:model-value="record.disable" v-if="columnConfig.hasDisable"
size="small" v-model:model-value="record.disable"
type="line" size="small"
class="mr-[8px]" type="line"
@change="() => addTableLine(rowIndex)" class="mr-[8px]"
/> @change="(val) => addTableLine(val as number)"
<slot name="operationPre" :record="record" :row-index="rowIndex" :column-config="columnConfig"></slot> />
<MsTableMoreAction <slot name="operationPre" :record="record" :row-index="rowIndex" :column-config="columnConfig"></slot>
v-if="columnConfig.moreAction" <MsTableMoreAction
:list="getMoreActionList(columnConfig.moreAction, record)" v-if="columnConfig.moreAction"
@select="(e) => handleMoreActionSelect(e, record)" :list="getMoreActionList(columnConfig.moreAction, record)"
/> @select="(e) => handleMoreActionSelect(e, record)"
<a-trigger v-if="columnConfig.format === RequestBodyFormat.FORM_DATA" trigger="click" position="br"> />
<MsButton type="icon" class="mr-[8px]"><icon-more /></MsButton> <a-trigger v-if="columnConfig.format === RequestBodyFormat.FORM_DATA" trigger="click" position="br">
<template #content> <MsButton type="icon" class="mr-[8px]"><icon-more /></MsButton>
<div class="content-type-trigger-content"> <template #content>
<div class="mb-[8px] text-[var(--color-text-1)]">Content-Type</div> <div class="content-type-trigger-content">
<a-select <div class="mb-[8px] text-[var(--color-text-1)]">Content-Type</div>
v-model:model-value="record.contentType" <a-select
:options="Object.values(RequestContentTypeEnum).map((e) => ({ label: e, value: e }))" v-model:model-value="record.contentType"
allow-create :options="Object.values(RequestContentTypeEnum).map((e) => ({ label: e, value: e }))"
@change="() => addTableLine(rowIndex)" allow-create
/> @change="(val) => addTableLine(val as number)"
</div> />
</template> </div>
</a-trigger> </template>
<div> </a-trigger>
<icon-minus-circle <icon-minus-circle
v-if="paramsLength > 1 && rowIndex !== paramsLength - 1" v-if="paramsLength > 1 && rowIndex !== paramsLength - 1"
class="ml-[8px] cursor-pointer text-[var(--color-text-4)]" class="ml-[8px] cursor-pointer text-[var(--color-text-4)]"
@ -273,13 +294,28 @@
<a-option v-for="item in columnConfig.options" :key="item.value">{{ t(item.label) }}</a-option> <a-option v-for="item in columnConfig.options" :key="item.value">{{ t(item.label) }}</a-option>
</a-select> </a-select>
</template> </template>
<template #matchCondition="{ record, columnConfig, rowIndex }"> <template #matchCondition="{ record, columnConfig }">
<a-select v-model="record.condition" class="param-input" @change="() => addTableLine(rowIndex)"> <a-select v-model="record.condition" class="param-input">
<a-option v-for="item in columnConfig.options" :key="item.value">{{ t(item.label) }}</a-option> <a-option v-for="item in columnConfig.options" :key="item.value">{{ t(item.label) }}</a-option>
</a-select> </a-select>
</template> </template>
<template #matchValue="{ record, rowIndex }"> <template #matchValue="{ record, rowIndex, columnConfig }">
<a-input v-model="record.matchValue" class="param-input" @change="() => addTableLine(rowIndex)" /> <a-tooltip
v-if="columnConfig.hasRequired"
:content="t(record.required ? 'apiTestDebug.paramRequired' : 'apiTestDebug.paramNotRequired')"
>
<MsButton
type="icon"
:class="[
record.required ? '!text-[rgb(var(--danger-5))]' : '!text-[var(--color-text-brand)]',
'!mr-[4px] !p-[4px]',
]"
@click="toggleRequired(record, rowIndex)"
>
<div>*</div>
</MsButton>
</a-tooltip>
<a-input v-model="record.matchValue" class="param-input" />
</template> </template>
<template #project="{ record, columnConfig, rowIndex }"> <template #project="{ record, columnConfig, rowIndex }">
<a-select <a-select
@ -346,7 +382,8 @@
</template> </template>
<script async setup lang="ts"> <script async setup lang="ts">
import { cloneDeep } from 'lodash-es'; import { TableColumnData, TableData } from '@arco-design/web-vue';
import { cloneDeep, isEqual } from 'lodash-es';
import MsButton from '@/components/pure/ms-button/index.vue'; import MsButton from '@/components/pure/ms-button/index.vue';
import MsCodeEditor from '@/components/pure/ms-code-editor/index.vue'; import MsCodeEditor from '@/components/pure/ms-code-editor/index.vue';
@ -366,6 +403,8 @@
import { RequestBodyFormat, RequestContentTypeEnum, RequestParamsType } from '@/enums/apiEnum'; import { RequestBodyFormat, RequestContentTypeEnum, RequestParamsType } from '@/enums/apiEnum';
import { SelectAllEnum, TableKeyEnum } from '@/enums/tableEnum'; import { SelectAllEnum, TableKeyEnum } from '@/enums/tableEnum';
import { TableOperationColumn } from '@arco-design/web-vue/es/table/interface';
// //
const MsAddAttachment = defineAsyncComponent(() => import('@/components/business/ms-add-attachment/index.vue')); const MsAddAttachment = defineAsyncComponent(() => import('@/components/business/ms-add-attachment/index.vue'));
const MsParamsInput = defineAsyncComponent(() => import('@/components/business/ms-params-input/index.vue')); const MsParamsInput = defineAsyncComponent(() => import('@/components/business/ms-params-input/index.vue'));
@ -400,6 +439,12 @@
showSelectorAll?: boolean; // showSelectorAll?: boolean; //
isSimpleSetting?: boolean; // Column isSimpleSetting?: boolean; // Column
response?: string; // response?: string; //
spanMethod?: (data: {
record: TableData;
column: TableColumnData | TableOperationColumn;
rowIndex: number;
columnIndex: number;
}) => { rowspan?: number; colspan?: number } | void;
uploadTempFileApi?: (...args) => Promise<any>; // uploadTempFileApi?: (...args) => Promise<any>; //
}>(), }>(),
{ {
@ -496,6 +541,69 @@
emit('change', propsRes.value.data); emit('change', propsRes.value.data);
} }
/** 断言-文档-Begin */
// ---
const mustIncludeAllChecked = ref(false);
const mustIncludeIndeterminate = ref(false);
const handleMustIncludeChange = (val: boolean) => {
mustIncludeAllChecked.value = val;
mustIncludeIndeterminate.value = false;
const { data } = propsRes.value;
data.forEach((e: any) => {
e.mustInclude = val;
});
propsRes.value.data = data;
emit('change', propsRes.value.data);
};
const handleMustContainColChange = (notEmit?: boolean) => {
const { data } = propsRes.value;
const checkedList = data.filter((e: any) => e.mustInclude).map((e: any) => e.id);
if (checkedList.length === data.length) {
mustIncludeAllChecked.value = true;
mustIncludeIndeterminate.value = false;
} else if (checkedList.length === 0) {
mustIncludeAllChecked.value = false;
mustIncludeIndeterminate.value = false;
} else {
mustIncludeAllChecked.value = false;
mustIncludeIndeterminate.value = true;
}
if (!notEmit) {
emit('change', propsRes.value.data);
}
};
const typeCheckingAllChecked = ref(false);
const typeCheckingIndeterminate = ref(false);
const handleTypeCheckingChange = (val: boolean) => {
typeCheckingAllChecked.value = val;
typeCheckingIndeterminate.value = false;
const { data } = propsRes.value;
data.forEach((e: any) => {
e.typeChecking = val;
});
propsRes.value.data = data;
emit('change', propsRes.value.data);
};
const handleTypeCheckingColChange = (notEmit?: boolean) => {
const { data } = propsRes.value;
const checkedList = data.filter((e: any) => e.typeChecking).map((e: any) => e.id);
if (checkedList.length === data.length) {
typeCheckingAllChecked.value = true;
typeCheckingIndeterminate.value = false;
} else if (checkedList.length === 0) {
typeCheckingAllChecked.value = false;
typeCheckingIndeterminate.value = false;
} else {
typeCheckingAllChecked.value = false;
typeCheckingIndeterminate.value = true;
}
if (!notEmit) {
emit('change', propsRes.value.data);
}
};
/** 断言-文档-end */
/** /**
* 当表格输入框变化时给参数表格添加一行数据行 * 当表格输入框变化时给参数表格添加一行数据行
* @param val 输入值 * @param val 输入值
@ -513,6 +621,8 @@
} as any); } as any);
emit('change', propsRes.value.data); emit('change', propsRes.value.data);
} }
handleMustContainColChange(true);
handleTypeCheckingColChange(true);
} }
watch( watch(
@ -667,30 +777,6 @@
addTableLine(rowIndex); addTableLine(rowIndex);
} }
/** 断言-文档-Begin */
// ---
const mustIncludeList = ref([]);
const mustIncludeAllChecked = ref(false);
const mustIncludeIndeterminate = ref(false);
const handleMustIncludeChange = (val: boolean) => {
mustIncludeAllChecked.value = val;
mustIncludeIndeterminate.value = false;
const data = propsRes.value;
mustIncludeList.value = val ? data.map((e: any) => e.id) : [];
};
// ---id
const typeCheckingList = ref([]);
const typeCheckingAllChecked = ref(false);
const typeCheckingIndeterminate = ref(false);
const handleTypeCheckingChange = (val: boolean) => {
typeCheckingAllChecked.value = val;
typeCheckingIndeterminate.value = false;
const data = propsRes.value;
typeCheckingList.value = val ? data.map((e: any) => e.id) : [];
};
/** 断言-文档-end */
defineExpose({ defineExpose({
addTableLine, addTableLine,
}); });
@ -774,4 +860,7 @@
line-height: 16px; line-height: 16px;
color: var(--color-text-1); color: var(--color-text-1);
} }
:deep(.arco-table-expand-btn) {
background: transparent;
}
</style> </style>

View File

@ -188,57 +188,57 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {useRoute} from 'vue-router'; import { useRoute } from 'vue-router';
import {Message} from '@arco-design/web-vue'; import { Message } from '@arco-design/web-vue';
import MsButton from '@/components/pure/ms-button/index.vue'; import MsButton from '@/components/pure/ms-button/index.vue';
import MsCard from '@/components/pure/ms-card/index.vue'; import MsCard from '@/components/pure/ms-card/index.vue';
import MsFormCreate from '@/components/pure/ms-form-create/ms-form-create.vue'; import MsFormCreate from '@/components/pure/ms-form-create/ms-form-create.vue';
import {FormItem, FormRuleItem} from '@/components/pure/ms-form-create/types'; import { FormItem, FormRuleItem } from '@/components/pure/ms-form-create/types';
import MsRichText from '@/components/pure/ms-rich-text/MsRichText.vue'; import MsRichText from '@/components/pure/ms-rich-text/MsRichText.vue';
import MsTagsInput from '@/components/pure/ms-tags-input/index.vue'; import MsTagsInput from '@/components/pure/ms-tags-input/index.vue';
import MsFileList from "@/components/pure/ms-upload/fileList.vue"; import MsFileList from '@/components/pure/ms-upload/fileList.vue';
import MsUpload from '@/components/pure/ms-upload/index.vue'; import MsUpload from '@/components/pure/ms-upload/index.vue';
import {MsFileItem} from '@/components/pure/ms-upload/types'; import { MsFileItem } from '@/components/pure/ms-upload/types';
import RelateFileDrawer from '@/components/business/ms-link-file/associatedFileDrawer.vue'; import RelateFileDrawer from '@/components/business/ms-link-file/associatedFileDrawer.vue';
import TransferModal from '@/views/case-management/caseManagementFeature/components/tabContent/transferModal.vue'; import TransferModal from '@/views/case-management/caseManagementFeature/components/tabContent/transferModal.vue';
import { import {
checkFileIsUpdateRequest, checkFileIsUpdateRequest,
createOrUpdateBug, createOrUpdateBug,
downloadFileRequest, downloadFileRequest,
editorUploadFile, editorUploadFile,
getAssociatedFileList, getAssociatedFileList,
getBugDetail, getBugDetail,
getTemplateById, getTemplateById,
getTemplateOption, getTemplateOption,
previewFile, previewFile,
transferFileRequest, transferFileRequest,
updateFile, updateFile,
} from '@/api/modules/bug-management'; } from '@/api/modules/bug-management';
import {getModules, getModulesCount} from '@/api/modules/project-management/fileManagement'; import { getModules, getModulesCount } from '@/api/modules/project-management/fileManagement';
import {useI18n} from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import useVisit from '@/hooks/useVisit'; import useVisit from '@/hooks/useVisit';
import router from '@/router'; import router from '@/router';
import {useAppStore} from '@/store'; import { useAppStore } from '@/store';
import {downloadByteFile} from '@/utils'; import { downloadByteFile } from '@/utils';
import {scrollIntoView} from '@/utils/dom'; import { scrollIntoView } from '@/utils/dom';
import { import {
BugEditCustomField, BugEditCustomField,
BugEditCustomFieldItem, BugEditCustomFieldItem,
BugEditFormObject, BugEditFormObject,
BugTemplateRequest BugTemplateRequest,
} from '@/models/bug-management'; } from '@/models/bug-management';
import {AssociatedList, AttachFileInfo} from '@/models/caseManagement/featureCase'; import { AssociatedList, AttachFileInfo } from '@/models/caseManagement/featureCase';
import {TableQueryParams} from '@/models/common'; import { TableQueryParams } from '@/models/common';
import {SelectValue} from '@/models/projectManagement/menuManagement'; import { SelectValue } from '@/models/projectManagement/menuManagement';
import {BugManagementRouteEnum} from '@/enums/routeEnum'; import { BugManagementRouteEnum } from '@/enums/routeEnum';
import {convertToFile} from '../case-management/caseManagementFeature/components/utils'; import { convertToFile } from '../case-management/caseManagementFeature/components/utils';
import {convertToFileByBug} from './utils'; import { convertToFileByBug } from './utils';
defineOptions({ name: 'BugEditPage' }); defineOptions({ name: 'BugEditPage' });
const { t } = useI18n(); const { t } = useI18n();
@ -356,9 +356,9 @@ defineOptions({ name: 'BugEditPage' });
const templateChange = async (v: SelectValue, request?: BugTemplateRequest) => { const templateChange = async (v: SelectValue, request?: BugTemplateRequest) => {
if (v) { if (v) {
try { try {
let param = {projectId: appStore.currentProjectId, id: v} let param = { projectId: appStore.currentProjectId, id: v };
if (request) { if (request) {
param = {...param, ...request} param = { ...param, ...request };
} }
const res = await getTemplateById(param); const res = await getTemplateById(param);
getFormRules(res.customFields); getFormRules(res.customFields);
@ -555,7 +555,7 @@ defineOptions({ name: 'BugEditPage' });
// , // ,
await templateChange(templateId); await templateChange(templateId);
} else { } else {
await templateChange(templateId, {fromStatusId: res.status, platformBugKey: res.platformBugId}) await templateChange(templateId, { fromStatusId: res.status, platformBugKey: res.platformBugId });
} }
if (attachments && attachments.length) { if (attachments && attachments.length) {
attachmentsList.value = attachments; attachmentsList.value = attachments;

View File

@ -192,6 +192,7 @@
<style lang="less" scoped> <style lang="less" scoped>
.page { .page {
transform: scale3d(1, 1, 1); transform: scale3d(1, 1, 1);
padding-bottom: 180px;
.header { .header {
padding: 24px 24px 0; padding: 24px 24px 0;
} }