mirror of
https://gitee.com/fit2cloud-feizhiyun/MeterSphere.git
synced 2024-12-03 20:49:56 +08:00
feat(测试用例): excel和xmind导出
This commit is contained in:
parent
3c08ffeb9c
commit
455a85e98e
@ -17,6 +17,7 @@ import {
|
||||
CancelAssociationDemandUrl,
|
||||
cancelDisassociate,
|
||||
cancelPreAndPostCaseUrl,
|
||||
CheckCaseExportTaskUrl,
|
||||
checkFileIsUpdateUrl,
|
||||
CreateCaseModuleTreeUrl,
|
||||
CreateCaseUrl,
|
||||
@ -32,7 +33,9 @@ import {
|
||||
DownloadXMindTemplateUrl,
|
||||
dragSortUrl,
|
||||
EditorUploadFileUrl,
|
||||
ExportExcelCaseUrl,
|
||||
exportExcelCheckUrl,
|
||||
ExportXMindCaseUrl,
|
||||
exportXMindCheckUrl,
|
||||
FollowerCaseUrl,
|
||||
GetAssociatedCaseIdsUrl,
|
||||
@ -43,6 +46,8 @@ import {
|
||||
GetAssociationPublicCaseModuleCountUrl,
|
||||
GetAssociationPublicCasePageUrl,
|
||||
GetAssociationPublicModuleTreeUrl,
|
||||
GetCaseDownloadFileUrl,
|
||||
GetCaseExportConfigUrl,
|
||||
GetCaseListUrl,
|
||||
GetCaseMinderTreeUrl,
|
||||
GetCaseMinderUrl,
|
||||
@ -74,6 +79,7 @@ import {
|
||||
RecoverRecycleCaseListUrl,
|
||||
RestoreCaseListUrl,
|
||||
SaveCaseMinderUrl,
|
||||
StopCaseExportUrl,
|
||||
TransferFileUrl,
|
||||
UpdateCaseModuleTreeUrl,
|
||||
UpdateCaseUrl,
|
||||
@ -446,7 +452,30 @@ export function importExcelOrXMindCase(data: { request: ImportExcelType; fileLis
|
||||
''
|
||||
);
|
||||
}
|
||||
|
||||
// 导出excel
|
||||
export function exportExcelCase(data: TableQueryParams) {
|
||||
return MSR.post({ url: ExportExcelCaseUrl, data });
|
||||
}
|
||||
// 导出XMind
|
||||
export function exportXMindCase(data: TableQueryParams) {
|
||||
return MSR.post({ url: ExportXMindCaseUrl, data });
|
||||
}
|
||||
// 检查是否有导出任务
|
||||
export function checkCaseExportTask() {
|
||||
return MSR.get({ url: CheckCaseExportTaskUrl });
|
||||
}
|
||||
// 获取导出的文件
|
||||
export function getCaseDownloadFile(projectId: string, fileId: string) {
|
||||
return MSR.get({ url: `${GetCaseDownloadFileUrl}/${projectId}/${fileId}` });
|
||||
}
|
||||
// 停止导出
|
||||
export function stopCaseExport(taskId: string) {
|
||||
return MSR.get({ url: `${StopCaseExportUrl}/${taskId}` });
|
||||
}
|
||||
// 获取导出字段配置
|
||||
export function getCaseExportConfig(projectId: string) {
|
||||
return MSR.get({ url: `${GetCaseExportConfigUrl}/${projectId}` });
|
||||
}
|
||||
// 拖拽排序
|
||||
export function dragSort(data: DragCase) {
|
||||
return MSR.post({ url: dragSortUrl, data });
|
||||
|
@ -152,6 +152,18 @@ export const exportXMindCheckUrl = '/functional/case/pre-check/xmind';
|
||||
export const importExcelCaseUrl = '/functional/case/import/excel';
|
||||
// 导入xmind文件
|
||||
export const importXMindCaseUrl = '/functional/case/import/xmind';
|
||||
// 导出excel文件
|
||||
export const ExportExcelCaseUrl = '/functional/case/export/excel';
|
||||
// 导出XMind文件
|
||||
export const ExportXMindCaseUrl = '/functional/case/export/xmind';
|
||||
// 检查是否有导出任务
|
||||
export const CheckCaseExportTaskUrl = '/functional/case/check/export-task';
|
||||
// 导出字段配置
|
||||
export const GetCaseExportConfigUrl = '/functional/case/export/columns';
|
||||
// 下载导出的文件
|
||||
export const GetCaseDownloadFileUrl = '/functional/case/download/file';
|
||||
// 停止导出
|
||||
export const StopCaseExportUrl = '/functional/case/stop';
|
||||
// 用例拖拽排序
|
||||
export const dragSortUrl = '/functional/case/edit/pos';
|
||||
// 获取变更历史
|
||||
|
@ -14,7 +14,14 @@
|
||||
@cancel="handleDrawerCancel"
|
||||
>
|
||||
<template #title>
|
||||
<slot name="title"></slot>
|
||||
<slot name="title">
|
||||
<div v-if="props.drawerTitleProps">
|
||||
<span class="text-[var(--color-text-1)]">{{ props.drawerTitleProps.title }}</span>
|
||||
<span v-if="props.drawerTitleProps.count" class="ml-1 text-[var(--color-text-4)]">
|
||||
{{ t('common.selectedCount', { count: props.drawerTitleProps.count }) }}
|
||||
</span>
|
||||
</div>
|
||||
</slot>
|
||||
</template>
|
||||
<div class="panel-wrapper">
|
||||
<div class="inner-wrapper">
|
||||
@ -57,7 +64,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</a-checkbox-group>
|
||||
<div class="text-[var(--color-text-4)]">
|
||||
<div v-if="customList.length" class="text-[var(--color-text-4)]">
|
||||
<a-checkbox
|
||||
:model-value="isCheckedCustomAll"
|
||||
:indeterminate="customIndeterminate"
|
||||
@ -68,8 +75,12 @@
|
||||
</span>
|
||||
</a-checkbox>
|
||||
</div>
|
||||
<a-checkbox-group :model-value="selectedCustomIds" @change="(value) => handleGroupChange(value, 'custom')">
|
||||
<div v-if="customList.length" class="mb-[32px]">
|
||||
<a-checkbox-group
|
||||
v-if="customList.length"
|
||||
:model-value="selectedCustomIds"
|
||||
@change="(value) => handleGroupChange(value, 'custom')"
|
||||
>
|
||||
<div class="mb-[32px]">
|
||||
<div class="flex flex-row flex-wrap">
|
||||
<a-checkbox
|
||||
v-for="item in customList"
|
||||
@ -84,7 +95,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</a-checkbox-group>
|
||||
<div class="flex flex-row items-center gap-[4px]">
|
||||
<div v-if="otherList.length" class="flex flex-row items-center gap-[4px]">
|
||||
<div class="text-[var(--color-text-4)]">
|
||||
<a-checkbox
|
||||
:model-value="isCheckedOtherAll"
|
||||
@ -102,8 +113,12 @@
|
||||
</a-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
<a-checkbox-group :model-value="selectedOtherIds" @change="(value) => handleGroupChange(value, 'other')">
|
||||
<div v-if="otherList.length" class="mb-[32px]">
|
||||
<a-checkbox-group
|
||||
v-if="otherList.length"
|
||||
:model-value="selectedOtherIds"
|
||||
@change="(value) => handleGroupChange(value, 'other')"
|
||||
>
|
||||
<div class="mb-[32px]">
|
||||
<div class="flex flex-row flex-wrap">
|
||||
<a-checkbox
|
||||
v-for="item in otherList"
|
||||
@ -206,6 +221,10 @@
|
||||
systemTitle: string; // 已选字段| 环境
|
||||
selectedTitle: string; // 已选字段| 环境
|
||||
};
|
||||
drawerTitleProps?: {
|
||||
title: string;
|
||||
count?: number;
|
||||
};
|
||||
disabledCancelKeys?: string[]; // 禁止取消系统字段
|
||||
}
|
||||
|
||||
|
@ -84,6 +84,10 @@ export default {
|
||||
'common.quickAddMember': 'Quickly add members',
|
||||
'common.filter': 'Filter',
|
||||
'common.export': 'Export',
|
||||
'common.exporting': 'Exporting',
|
||||
'common.exportSuccessful': 'Export successful',
|
||||
'common.exportFailed': 'Export failed',
|
||||
'common.downloadFile': 'Download file',
|
||||
'common.import': 'Import',
|
||||
'common.collapseAll': 'Collapse all',
|
||||
'common.expandAll': 'Expand all',
|
||||
|
@ -84,6 +84,10 @@ export default {
|
||||
'common.pleaseSelect': '请选择',
|
||||
'common.quickAddMember': '快速添加成员',
|
||||
'common.export': '导出',
|
||||
'common.exporting': '正在导出',
|
||||
'common.exportSuccessful': '导出成功',
|
||||
'common.exportFailed': '导出失败',
|
||||
'common.downloadFile': '下载文件',
|
||||
'common.import': '导入',
|
||||
'common.collapseAll': '收起全部',
|
||||
'common.expandAll': '展开全部',
|
||||
|
@ -128,17 +128,12 @@
|
||||
:export-loading="exportLoading"
|
||||
:all-data="exportOptionData"
|
||||
:disabled-cancel-keys="['name']"
|
||||
:drawer-title-props="{
|
||||
title: t('bugManagement.exportBug'),
|
||||
count: currentSelectParams.currentSelectCount,
|
||||
}"
|
||||
@confirm="exportConfirm"
|
||||
>
|
||||
<template #title>
|
||||
<div>
|
||||
<span class="text-[var(--color-text-1)]">{{ t('bugManagement.exportBug') }}</span>
|
||||
<span v-if="currentSelectParams.currentSelectCount" class="text-[var(--color-text-4)]">
|
||||
({{ t('bugManagement.exportBugCount', { count: currentSelectParams.currentSelectCount }) }})
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</MsExportDrawer>
|
||||
/>
|
||||
<BugDetailDrawer
|
||||
v-model:visible="detailVisible"
|
||||
:detail-id="activeDetailId"
|
||||
|
@ -277,7 +277,50 @@
|
||||
@case-node-select="caseNodeSelect"
|
||||
></FeatureCaseTree>
|
||||
</a-modal>
|
||||
<ExportExcelDrawer v-model:visible="showExportExcelVisible" />
|
||||
<MsExportDrawer
|
||||
v-model:visible="showExportVisible"
|
||||
:export-loading="exportLoading"
|
||||
:all-data="
|
||||
exportType === 'exportExcel'
|
||||
? exportOptionData
|
||||
: { systemColumns: exportOptionData.systemColumns, customColumns: exportOptionData.customColumns }
|
||||
"
|
||||
:disabled-cancel-keys="['name']"
|
||||
:drawer-title-props="{
|
||||
title:
|
||||
exportType === 'exportExcel'
|
||||
? t('caseManagement.featureCase.exportExcel')
|
||||
: t('caseManagement.featureCase.exportXMindNoUnit'),
|
||||
count: batchParams.currentSelectCount,
|
||||
}"
|
||||
@confirm="exportConfirm"
|
||||
>
|
||||
<template v-if="exportType === 'exportExcel'" #footerLeft>
|
||||
<div class="flex items-center gap-[8px]">
|
||||
<div>{{ t('caseManagement.featureCase.exportExcel.exportFormat') }}</div>
|
||||
<a-radio-group v-model:model-value="isMerge">
|
||||
<a-radio :value="false">
|
||||
{{ t('common.default') }}
|
||||
<a-tooltip :content="t('caseManagement.featureCase.exportExcel.defaultTip')">
|
||||
<MsIcon
|
||||
class="ml-[4px] text-[var(--color-text-brand)] hover:text-[rgb(var(--primary-4))]"
|
||||
type="icon-icon-maybe_outlined"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</a-radio>
|
||||
<a-radio :value="true">
|
||||
{{ t('caseManagement.featureCase.exportExcel.cellSplitting') }}
|
||||
<a-tooltip :content="t('caseManagement.featureCase.exportExcel.cellSplittingTip')">
|
||||
<MsIcon
|
||||
class="ml-[4px] text-[var(--color-text-brand)] hover:text-[rgb(var(--primary-4))]"
|
||||
type="icon-icon-maybe_outlined"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</a-radio>
|
||||
</a-radio-group>
|
||||
</div>
|
||||
</template>
|
||||
</MsExportDrawer>
|
||||
<BatchEditModal
|
||||
v-model:visible="showEditModel"
|
||||
:batch-params="batchParams"
|
||||
@ -322,6 +365,7 @@
|
||||
import { FilterFormItem, FilterResult, FilterType } from '@/components/pure/ms-advance-filter/type';
|
||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||
import { MsExportDrawerMap, MsExportDrawerOption } from '@/components/pure/ms-export-drawer/types';
|
||||
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||
import type { BatchActionParams, BatchActionQueryParams, MsTableColumn } from '@/components/pure/ms-table/type';
|
||||
@ -335,7 +379,6 @@
|
||||
import BatchEditModal from './batchEditModal.vue';
|
||||
import CaseDetailDrawer from './caseDetailDrawer.vue';
|
||||
import FeatureCaseTree from './caseTree.vue';
|
||||
import ExportExcelDrawer from './exportExcelDrawer.vue';
|
||||
import AddDemandModal from './tabContent/tabDemand/addDemandModal.vue';
|
||||
import ThirdDemandDrawer from './tabContent/tabDemand/thirdDemandDrawer.vue';
|
||||
|
||||
@ -344,14 +387,21 @@
|
||||
batchCopyToModules,
|
||||
batchDeleteCase,
|
||||
batchMoveToModules,
|
||||
checkCaseExportTask,
|
||||
deleteCaseRequest,
|
||||
dragSort,
|
||||
exportExcelCase,
|
||||
exportXMindCase,
|
||||
getCaseDefaultFields,
|
||||
getCaseDetail,
|
||||
getCaseDownloadFile,
|
||||
getCaseExportConfig,
|
||||
getCaseList,
|
||||
getCustomFieldsTable,
|
||||
stopCaseExport,
|
||||
updateCaseRequest,
|
||||
} from '@/api/modules/case-management/featureCase';
|
||||
import { getSocket } from '@/api/modules/project-management/commonScript';
|
||||
import { getCaseRelatedInfo } from '@/api/modules/project-management/menuManagement';
|
||||
import { getProjectOptions } from '@/api/modules/project-management/projectMember';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
@ -359,7 +409,15 @@
|
||||
import { useAppStore, useTableStore } from '@/store';
|
||||
import useFeatureCaseStore from '@/store/modules/case/featureCase';
|
||||
import useMinderStore from '@/store/modules/components/minder-editor';
|
||||
import { characterLimit, filterTreeNode, findNodeByKey, findNodePathByKey, mapTree } from '@/utils';
|
||||
import {
|
||||
characterLimit,
|
||||
downloadByteFile,
|
||||
filterTreeNode,
|
||||
findNodeByKey,
|
||||
findNodePathByKey,
|
||||
getGenerateId,
|
||||
mapTree,
|
||||
} from '@/utils';
|
||||
import { hasAnyPermission } from '@/utils/permission';
|
||||
|
||||
import type {
|
||||
@ -378,6 +436,8 @@
|
||||
import { executionResultMap, getCaseLevels, getTableFields, statusIconMap } from './utils';
|
||||
import { LabelValue } from '@arco-design/web-vue/es/tree-select/interface';
|
||||
|
||||
const MsExportDrawer = defineAsyncComponent(() => import('@/components/pure/ms-export-drawer/index.vue'));
|
||||
|
||||
const { openModal } = useModal();
|
||||
const { t } = useI18n();
|
||||
const router = useRouter();
|
||||
@ -638,20 +698,21 @@
|
||||
const platformInfo = ref<Record<string, any>>({});
|
||||
const tableBatchActions = {
|
||||
baseAction: [
|
||||
// {
|
||||
// label: 'caseManagement.featureCase.export',
|
||||
// eventTag: 'export',
|
||||
// children: [
|
||||
// {
|
||||
// label: 'caseManagement.featureCase.exportExcel',
|
||||
// eventTag: 'exportExcel',
|
||||
// },
|
||||
// {
|
||||
// label: 'caseManagement.featureCase.exportXMind',
|
||||
// eventTag: 'exportXMind',
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
{
|
||||
label: 'caseManagement.featureCase.export',
|
||||
eventTag: 'export',
|
||||
permission: ['FUNCTIONAL_CASE:READ+EXPORT'],
|
||||
children: [
|
||||
{
|
||||
label: 'caseManagement.featureCase.exportExcelXlsx',
|
||||
eventTag: 'exportExcel',
|
||||
},
|
||||
{
|
||||
label: 'caseManagement.featureCase.exportXMind',
|
||||
eventTag: 'exportXMind',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'common.edit',
|
||||
eventTag: 'batchEdit',
|
||||
@ -1010,11 +1071,187 @@
|
||||
}
|
||||
}
|
||||
|
||||
const showExportExcelVisible = ref<boolean>(false);
|
||||
const exportType = ref<'exportExcel' | 'exportXMind'>('exportExcel');
|
||||
const showExportVisible = ref<boolean>(false);
|
||||
const exportLoading = ref(false);
|
||||
const exportOptionData = ref<MsExportDrawerMap>({});
|
||||
const isMerge = ref<boolean>(false);
|
||||
async function getCaseExportData() {
|
||||
try {
|
||||
const res = await getCaseExportConfig(currentProjectId.value);
|
||||
exportOptionData.value = res;
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
// 导出Excel
|
||||
function handleShowExportExcel() {
|
||||
showExportExcelVisible.value = true;
|
||||
const websocket = ref<WebSocket>();
|
||||
const reportId = ref('');
|
||||
const taskId = ref('');
|
||||
|
||||
// 下载文件
|
||||
async function downloadFile() {
|
||||
try {
|
||||
const response = await getCaseDownloadFile(currentProjectId.value, reportId.value);
|
||||
const fileName = response?.headers.get('content-disposition').split('filename=')[1];
|
||||
downloadByteFile(response.blob(), fileName);
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
// 提示:导出成功
|
||||
function showExportSuccessfulMessage(count: number) {
|
||||
Message.success({
|
||||
content: () =>
|
||||
h('div', { class: 'flex flex-col gap-[8px] items-start' }, [
|
||||
h('div', { class: 'font-medium' }, t('common.exportSuccessful')),
|
||||
h('div', { class: 'flex items-center gap-[12px]' }, [
|
||||
h('div', t('caseManagement.featureCase.exportCaseCount', { number: count })),
|
||||
h(
|
||||
MsButton,
|
||||
{
|
||||
type: 'text',
|
||||
onClick() {
|
||||
downloadFile();
|
||||
},
|
||||
},
|
||||
{ default: () => t('common.downloadFile') }
|
||||
),
|
||||
]),
|
||||
]),
|
||||
duration: 999999999, // 一直展示,除非手动关闭
|
||||
closable: true,
|
||||
});
|
||||
}
|
||||
|
||||
const isShowExportingMessage = ref(false); // 正在导出提示显示中
|
||||
const exportingMessage = ref();
|
||||
// 取消导出
|
||||
async function cancelExport() {
|
||||
try {
|
||||
await stopCaseExport(taskId.value);
|
||||
exportingMessage.value.close();
|
||||
websocket.value?.close();
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
// 提示:正在导出
|
||||
function showExportingMessage() {
|
||||
if (isShowExportingMessage.value) return;
|
||||
isShowExportingMessage.value = true;
|
||||
exportingMessage.value = Message.loading({
|
||||
content: () =>
|
||||
h('div', { class: 'flex items-center gap-[12px]' }, [
|
||||
h('div', t('common.exporting')),
|
||||
h(
|
||||
MsButton,
|
||||
{
|
||||
type: 'text',
|
||||
onClick() {
|
||||
cancelExport();
|
||||
},
|
||||
},
|
||||
{ default: () => t('common.cancel') }
|
||||
),
|
||||
]),
|
||||
duration: 999999999, // 一直展示,除非手动关闭
|
||||
closable: true,
|
||||
onClose() {
|
||||
isShowExportingMessage.value = false;
|
||||
},
|
||||
});
|
||||
}
|
||||
// 开启websocket监听,接收结果
|
||||
function startWebsocketGetExportResult() {
|
||||
websocket.value = getSocket(reportId.value, '/ws/export');
|
||||
websocket.value.addEventListener('message', (event) => {
|
||||
const data = JSON.parse(event.data);
|
||||
if (data.msgType === 'EXEC_RESULT') {
|
||||
exportingMessage.value.close();
|
||||
reportId.value = data.fileId;
|
||||
taskId.value = data.taskId;
|
||||
if (data.isSuccessful) {
|
||||
showExportSuccessfulMessage(data.count);
|
||||
} else {
|
||||
Message.error({
|
||||
content: t('common.exportFailed'),
|
||||
duration: 999999999, // 一直展示,除非手动关闭
|
||||
closable: true,
|
||||
});
|
||||
}
|
||||
websocket.value?.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getConfirmFields(option: MsExportDrawerOption[], columnType: string) {
|
||||
return option
|
||||
.filter((optionItem) => optionItem.columnType === columnType)
|
||||
.map((item) => ({ id: item.key, name: item.text }));
|
||||
}
|
||||
const exportConfirm = async (option: MsExportDrawerOption[]) => {
|
||||
try {
|
||||
exportLoading.value = true;
|
||||
const { selectedIds, selectAll, excludeIds } = batchParams.value;
|
||||
reportId.value = getGenerateId();
|
||||
const params = {
|
||||
projectId: currentProjectId.value,
|
||||
selectIds: selectAll ? [] : selectedIds,
|
||||
excludeIds: excludeIds || [],
|
||||
moduleIds: props.activeFolder === 'all' ? [] : [props.activeFolder, ...props.offspringIds],
|
||||
condition: {
|
||||
keyword: keyword.value,
|
||||
filter: propsRes.value.filter,
|
||||
combine: batchParams.value.condition,
|
||||
},
|
||||
selectAll,
|
||||
systemFields: getConfirmFields(option, 'system'),
|
||||
customFields: getConfirmFields(option, 'custom'),
|
||||
fileId: reportId.value,
|
||||
};
|
||||
let res;
|
||||
if (exportType.value === 'exportExcel') {
|
||||
res = await exportExcelCase({
|
||||
...params,
|
||||
otherFields: getConfirmFields(option, 'other'),
|
||||
isMerge: isMerge.value,
|
||||
});
|
||||
} else {
|
||||
res = await exportXMindCase(params);
|
||||
}
|
||||
taskId.value = res.taskId;
|
||||
startWebsocketGetExportResult();
|
||||
showExportingMessage();
|
||||
exportLoading.value = false;
|
||||
showExportVisible.value = false;
|
||||
resetSelector();
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
} finally {
|
||||
exportLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
async function batchExport() {
|
||||
try {
|
||||
const res = await checkCaseExportTask();
|
||||
if (!res.fileId.length) {
|
||||
showExportVisible.value = true;
|
||||
} else {
|
||||
reportId.value = res.fileId;
|
||||
taskId.value = res.taskId;
|
||||
startWebsocketGetExportResult();
|
||||
showExportingMessage();
|
||||
}
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
const showEditModel = ref<boolean>(false);
|
||||
@ -1166,11 +1403,13 @@
|
||||
showThirdDrawer.value = true;
|
||||
}
|
||||
|
||||
function handleTableBatch(event: BatchActionParams, params: BatchActionQueryParams) {
|
||||
async function handleTableBatch(event: BatchActionParams, params: BatchActionQueryParams) {
|
||||
batchParams.value = params;
|
||||
switch (event.eventTag) {
|
||||
case 'exportExcel':
|
||||
handleShowExportExcel();
|
||||
case 'exportXMind':
|
||||
exportType.value = event.eventTag;
|
||||
batchExport();
|
||||
break;
|
||||
case 'batchEdit':
|
||||
batchEdit();
|
||||
@ -1513,6 +1752,7 @@
|
||||
}
|
||||
await initFilter();
|
||||
initData();
|
||||
getCaseExportData();
|
||||
});
|
||||
|
||||
watch(
|
||||
@ -1589,4 +1829,7 @@
|
||||
padding: 4px 6px;
|
||||
}
|
||||
}
|
||||
:deep(.arco-radio-group) {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,208 +0,0 @@
|
||||
<template>
|
||||
<MsDrawer
|
||||
v-model:visible="showDrawer"
|
||||
:mask="false"
|
||||
:title="t('caseManagement.featureCase.associatedFile')"
|
||||
:ok-text="t('caseManagement.featureCase.associated')"
|
||||
:ok-loading="drawerLoading"
|
||||
:width="480"
|
||||
unmount-on-close
|
||||
:show-continue="false"
|
||||
@confirm="handleDrawerConfirm"
|
||||
@cancel="handleDrawerCancel"
|
||||
>
|
||||
<div class="header mb-6 flex justify-between">
|
||||
<span class="font-medium">{{ t('caseManagement.featureCase.SelectExportRange') }}</span>
|
||||
<span class="text-[rgb(var(--primary-5))]">{{ t('caseManagement.featureCase.clear') }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<a-checkbox class="mb-4" :model-value="checkedAll" :indeterminate="indeterminate" @change="handleChangeAll"
|
||||
><div class="flex items-center">
|
||||
<span class="mr-1">{{ t('caseManagement.featureCase.baseField') }}</span
|
||||
><span
|
||||
><icon-up
|
||||
v-if="foldBaseFields"
|
||||
class="text-[12px] text-[var(--color-text-brand)]"
|
||||
@click="toggle('base')" /><icon-right
|
||||
v-else
|
||||
class="text-[12px] text-[var(--color-text-brand)]"
|
||||
@click="toggle('base')"
|
||||
/></span>
|
||||
</div>
|
||||
</a-checkbox>
|
||||
</div>
|
||||
<a-checkbox-group v-if="foldBaseFields" v-model="baseFields" class="checkboxContainer" @change="handleChange">
|
||||
<div class="item checkbox">
|
||||
<a-checkbox value="1">Option 1</a-checkbox>
|
||||
</div>
|
||||
<div class="item checkbox">
|
||||
<a-checkbox value="1">Option 1</a-checkbox>
|
||||
</div>
|
||||
<div class="item checkbox">
|
||||
<a-checkbox value="1">Option 1</a-checkbox>
|
||||
</div>
|
||||
<div class="item checkbox">
|
||||
<a-checkbox value="1">Option 1</a-checkbox>
|
||||
</div>
|
||||
<div class="item checkbox">
|
||||
<a-checkbox value="1">Option 1</a-checkbox>
|
||||
</div>
|
||||
</a-checkbox-group>
|
||||
<!-- 自定义字段 -->
|
||||
<div>
|
||||
<a-checkbox class="mb-4" :model-value="checkedAll" :indeterminate="indeterminate" @change="handleChangeAll"
|
||||
><div class="flex items-center">
|
||||
<span class="mr-1">{{ t('caseManagement.featureCase.customField') }}</span
|
||||
><span
|
||||
><icon-up
|
||||
v-if="foldCustomFields"
|
||||
class="text-[12px] text-[var(--color-text-brand)]"
|
||||
@click="toggle('custom')" /><icon-right
|
||||
v-else
|
||||
class="text-[12px] text-[var(--color-text-brand)]"
|
||||
@click="toggle('custom')"
|
||||
/></span>
|
||||
</div>
|
||||
</a-checkbox>
|
||||
</div>
|
||||
<a-checkbox-group v-if="foldCustomFields" v-model="customFields" class="checkboxContainer" @change="handleChange">
|
||||
<div class="item checkbox">
|
||||
<a-checkbox value="1">Option 1</a-checkbox>
|
||||
</div>
|
||||
<div class="item checkbox">
|
||||
<a-checkbox value="1">Option 1</a-checkbox>
|
||||
</div>
|
||||
<div class="item checkbox">
|
||||
<a-checkbox value="1">Option 1</a-checkbox>
|
||||
</div>
|
||||
<div class="item checkbox">
|
||||
<a-checkbox value="1">Option 1</a-checkbox>
|
||||
</div>
|
||||
<div class="item checkbox">
|
||||
<a-checkbox value="1">Option 1</a-checkbox>
|
||||
</div>
|
||||
</a-checkbox-group>
|
||||
<!-- 其他字段 -->
|
||||
<div>
|
||||
<a-checkbox class="mb-4" :model-value="checkedAll" :indeterminate="indeterminate" @change="handleChangeAll"
|
||||
><div class="flex items-center">
|
||||
<span class="mr-1 flex items-center"
|
||||
>{{ t('caseManagement.featureCase.otherFields') }}<span></span>
|
||||
<a-tooltip
|
||||
:content="t('caseManagement.featureCase.otherFieldsToolTip')"
|
||||
position="top"
|
||||
:mouse-enter-delay="500"
|
||||
mini
|
||||
>
|
||||
<icon-question-circle
|
||||
class="mx-1 text-[16px] text-[var(--color-text-brand)] hover:text-[rgb(var(--primary-5))]" /></a-tooltip
|
||||
><icon-up
|
||||
v-if="foldCustomFields"
|
||||
class="text-[12px] text-[var(--color-text-brand)]"
|
||||
@click="toggle('other')" /><icon-right
|
||||
v-else
|
||||
class="text-[12px] text-[var(--color-text-brand)]"
|
||||
@click="toggle('other')"
|
||||
/></span>
|
||||
</div>
|
||||
</a-checkbox>
|
||||
</div>
|
||||
<a-checkbox-group v-if="foldOtherFields" v-model="otherFields" class="checkboxContainer" @change="handleChange">
|
||||
<div class="item checkbox">
|
||||
<a-checkbox value="1">Option 1</a-checkbox>
|
||||
</div>
|
||||
<div class="item checkbox">
|
||||
<a-checkbox value="1">Option 1</a-checkbox>
|
||||
</div>
|
||||
<div class="item checkbox">
|
||||
<a-checkbox value="1">Option 1</a-checkbox>
|
||||
</div>
|
||||
<div class="item checkbox">
|
||||
<a-checkbox value="1">Option 1</a-checkbox>
|
||||
</div>
|
||||
<div class="item checkbox">
|
||||
<a-checkbox value="1">Option 1</a-checkbox>
|
||||
</div>
|
||||
</a-checkbox-group>
|
||||
</MsDrawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
|
||||
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:visible', val: boolean): void;
|
||||
}>();
|
||||
|
||||
const showDrawer = ref<boolean>(false);
|
||||
const drawerLoading = ref<boolean>(false);
|
||||
|
||||
const checkedAll = ref<boolean>(false);
|
||||
const indeterminate = ref<boolean>(false);
|
||||
|
||||
function handleChangeAll() {}
|
||||
function handleChange() {}
|
||||
|
||||
function handleDrawerConfirm() {}
|
||||
|
||||
function handleDrawerCancel() {
|
||||
showDrawer.value = false;
|
||||
}
|
||||
|
||||
const foldBaseFields = ref<boolean>(true); // 默认展开
|
||||
const baseFields = ref<string[]>([]);
|
||||
|
||||
const foldCustomFields = ref<boolean>(true);
|
||||
const customFields = ref<string[]>([]);
|
||||
|
||||
const foldOtherFields = ref<boolean>(true);
|
||||
const otherFields = ref<string[]>([]);
|
||||
|
||||
function toggle(foldType: string) {
|
||||
if (foldType === 'base') {
|
||||
foldBaseFields.value = !foldBaseFields.value;
|
||||
} else if (foldType === 'custom') {
|
||||
foldCustomFields.value = !foldCustomFields.value;
|
||||
} else {
|
||||
foldOtherFields.value = !foldOtherFields.value;
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(val) => {
|
||||
showDrawer.value = val;
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => showDrawer.value,
|
||||
(val) => {
|
||||
emit('update:visible', val);
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.checkboxContainer {
|
||||
display: grid;
|
||||
margin-bottom: 16px;
|
||||
grid-template-columns: repeat(auto-fit, minmax(116px, 1fr));
|
||||
grid-gap: 16px;
|
||||
.checkbox {
|
||||
width: 90px;
|
||||
white-space: nowrap;
|
||||
@apply overflow-hidden text-ellipsis;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -54,8 +54,15 @@ export default {
|
||||
'The deleted content will be put into the recycle bin, where data can be recovered',
|
||||
'caseManagement.featureCase.deleteCaseTitle': 'Are you sure to delete the {name} use case?',
|
||||
'caseManagement.featureCase.export': 'Export',
|
||||
'caseManagement.featureCase.exportExcel': 'Export spreadsheet (xlsx)',
|
||||
'caseManagement.featureCase.exportExcelXlsx': 'Export to Excel format (xlsx)',
|
||||
'caseManagement.featureCase.exportExcel': 'Export as Excel',
|
||||
'caseManagement.featureCase.exportExcel.exportFormat': 'Export Format',
|
||||
'caseManagement.featureCase.exportExcel.cellSplitting': 'Cell Splitting',
|
||||
'caseManagement.featureCase.exportExcel.cellSplittingTip': '1 step per cell, 1 test case occupies multiple rows',
|
||||
'caseManagement.featureCase.exportExcel.defaultTip': '1 test case per row, multiple steps in one cell',
|
||||
'caseManagement.featureCase.exportCaseCount': '{ number } test cases successfully exported',
|
||||
'caseManagement.featureCase.exportXMind': 'Exporting Mind (xmind)',
|
||||
'caseManagement.featureCase.exportXMindNoUnit': 'Exporting XMind',
|
||||
'caseManagement.featureCase.moveTo': 'Move to',
|
||||
'caseManagement.featureCase.copyTo': 'Copy to',
|
||||
'caseManagement.featureCase.associatedDemand': 'Associated demand',
|
||||
|
@ -54,8 +54,15 @@ export default {
|
||||
'caseManagement.featureCase.deleteCaseTitle': '确认删除 {name} 用例吗?',
|
||||
'caseManagement.featureCase.completedDeleteCaseTitle': '确认彻底删除 {name} 用例吗?',
|
||||
'caseManagement.featureCase.export': '导出',
|
||||
'caseManagement.featureCase.exportExcel': '导出 Excel 表格 (xlsx)',
|
||||
'caseManagement.featureCase.exportExcel': '导出 Excel 格式',
|
||||
'caseManagement.featureCase.exportExcelXlsx': '导出 Excel 格式 (xlsx)',
|
||||
'caseManagement.featureCase.exportExcel.exportFormat': '导出格式',
|
||||
'caseManagement.featureCase.exportExcel.cellSplitting': '单元格拆分',
|
||||
'caseManagement.featureCase.exportExcel.cellSplittingTip': '1 个步骤占用 1 个单元格,1 条用例占用多行',
|
||||
'caseManagement.featureCase.exportExcel.defaultTip': '1 条用例占 1 行,多个步骤在 1 个单元格内',
|
||||
'caseManagement.featureCase.exportCaseCount': '{ number } 条用例已成功导出',
|
||||
'caseManagement.featureCase.exportXMind': '导出思维导图 (xmind)',
|
||||
'caseManagement.featureCase.exportXMindNoUnit': '导出思维导图',
|
||||
'caseManagement.featureCase.moveTo': '移动到',
|
||||
'caseManagement.featureCase.copyTo': '复制到',
|
||||
'caseManagement.featureCase.associatedDemand': '关联需求',
|
||||
|
Loading…
Reference in New Issue
Block a user