feat(缺陷管理): 删除单个缺陷弹窗&批量编辑组件
This commit is contained in:
parent
403c2e0e1e
commit
444a0b8c14
|
@ -25,8 +25,8 @@ export function createBug(data: TableQueryParams) {
|
|||
return MSR.post({ url: bugURL.postCreateBugUrl, data });
|
||||
}
|
||||
|
||||
export function deleteBug(data: TableQueryParams) {
|
||||
return MSR.get({ url: bugURL.getDeleteBugUrl, data });
|
||||
export function deleteSingleBug(data: TableQueryParams) {
|
||||
return MSR.get({ url: `${bugURL.getDeleteBugUrl}${data.id}` });
|
||||
}
|
||||
|
||||
export function deleteBatchBug(data: TableQueryParams) {
|
||||
|
|
|
@ -7,8 +7,10 @@
|
|||
:indeterminate="indeterminate"
|
||||
@change="handleCheckChange"
|
||||
/>
|
||||
<a-dropdown v-if="showSelectAll" :disable="props.disabled" position="bl" @select="handleSelect">
|
||||
<MsIcon type="icon-icon_down_outlined" class="dropdown-icon" />
|
||||
<a-dropdown v-if="props.showSelectAll" :disable="props.disabled" position="bl" @select="handleSelect">
|
||||
<div>
|
||||
<MsIcon type="icon-icon_down_outlined" class="dropdown-icon" />
|
||||
</div>
|
||||
<template #content>
|
||||
<a-doption :value="SelectAllEnum.CURRENT">{{ t('msTable.current') }}</a-doption>
|
||||
<a-doption :value="SelectAllEnum.ALL">{{ t('msTable.all') }}</a-doption>
|
||||
|
|
|
@ -27,6 +27,8 @@ export default {
|
|||
'common.updateSuccess': '更新成功',
|
||||
'common.updateFailed': '更新失败',
|
||||
'common.deleteConfirm': '确认删除?',
|
||||
'common.deleteConfirmTitle': '确认删除 {name} 吗',
|
||||
'common.deleteConfirmContent': '删除后,MeterSphere 创建的缺陷进入回收站;第三方平台同步的缺陷将不做回收',
|
||||
'common.deleteSuccess': '删除成功',
|
||||
'common.deleteFailed': '删除失败',
|
||||
'common.addSuccess': '添加成功',
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
<template>
|
||||
<a-modal
|
||||
v-model:visible="currentVisible"
|
||||
title-align="start"
|
||||
class="ms-modal-form ms-modal-small"
|
||||
unmount-on-close
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<template #title>
|
||||
<div class="flex flex-row items-center">
|
||||
<div class="ml-[8px]">{{ t('bugManagement.batchEdit') }}</div>
|
||||
<div v-if="props.selectCount" class="ml-[8px] text-[var(--color-text-4)]">
|
||||
{{ t('bugManagement.selectedCount', { count: props.selectCount }) }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="form">
|
||||
<a-form ref="formRef" class="rounded-[4px]" :model="form" layout="vertical">
|
||||
<a-form-item
|
||||
field="name"
|
||||
asterisk-position="end"
|
||||
:label="t('bugManagement.deleteLabel')"
|
||||
:rules="[{ required: true }]"
|
||||
>
|
||||
<a-input v-model:model-value="form.label" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
<template #footer>
|
||||
<a-button type="secondary" :loading="loading" @click="handleCancel">
|
||||
{{ t('common.cancel') }}
|
||||
</a-button>
|
||||
<a-button type="primary" :loading="loading" :disabled="!form.label" @click="handleConfirm">
|
||||
{{ t('common.update') }}
|
||||
</a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, reactive, ref } from 'vue';
|
||||
import { type FormInstance, Message, type ValidatedError } from '@arco-design/web-vue';
|
||||
|
||||
import { FilterFormItem } from '@/components/pure/ms-advance-filter/type';
|
||||
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
|
||||
const { t } = useI18n();
|
||||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
configList: FilterFormItem[];
|
||||
selectCount: number;
|
||||
remoteFunc(params: Record<string, any>): Promise<any>; // 远程模式下的请求函数,返回一个 Promise
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'submit'): void;
|
||||
(e: 'update:visible', value: boolean): void;
|
||||
}>();
|
||||
|
||||
const currentVisible = computed({
|
||||
get() {
|
||||
return props.visible;
|
||||
},
|
||||
set(value) {
|
||||
emit('update:visible', value);
|
||||
},
|
||||
});
|
||||
const loading = ref(false);
|
||||
|
||||
const form = reactive({
|
||||
label: '',
|
||||
value: '',
|
||||
append: false,
|
||||
});
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
|
||||
const handleCancel = () => {
|
||||
currentVisible.value = false;
|
||||
form.label = '';
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
const handleConfirm = () => {
|
||||
formRef.value?.validate(async (errors: undefined | Record<string, ValidatedError>) => {
|
||||
if (!errors) {
|
||||
try {
|
||||
loading.value = true;
|
||||
Message.success(t('common.deleteSuccess'));
|
||||
handleCancel();
|
||||
emit('submit');
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
|
@ -0,0 +1,118 @@
|
|||
<template>
|
||||
<a-modal
|
||||
v-model:visible="currentVisible"
|
||||
title-align="start"
|
||||
class="ms-modal-form ms-modal-small"
|
||||
unmount-on-close
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<template #title>
|
||||
<div class="flex flex-row items-center">
|
||||
<icon-exclamation-circle-fill class="text-[16px] text-[rgb(var(--danger-6))]" />
|
||||
<div class="ml-[8px]">{{ t('common.confirmDelete') }}</div>
|
||||
<a-tooltip :content="props.name">
|
||||
<div class="one-text-line max-w-[300px] px-[5px]">
|
||||
{{ props.name }}
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<div class="form">
|
||||
<a-form ref="formRef" class="rounded-[4px]" :model="form" layout="vertical">
|
||||
<a-form-item
|
||||
field="name"
|
||||
asterisk-position="end"
|
||||
:label="t('bugManagement.deleteLabel')"
|
||||
:rules="[
|
||||
{
|
||||
validator(value, callback) {
|
||||
if (value !== props.name) {
|
||||
callback(t('bugManagement.nameIsIncorrect'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
},
|
||||
]"
|
||||
>
|
||||
<a-input v-model:model-value="form.name" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
<template #footer>
|
||||
<a-button type="secondary" :loading="loading" @click="handleCancel">
|
||||
{{ t('common.cancel') }}
|
||||
</a-button>
|
||||
<a-button type="primary" status="danger" :loading="loading" :disabled="!form.name" @click="handleConfirm">
|
||||
{{ t('common.confirmDelete') }}
|
||||
</a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, reactive, ref } from 'vue';
|
||||
import { type FormInstance, Message, type ValidatedError } from '@arco-design/web-vue';
|
||||
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
|
||||
const { t } = useI18n();
|
||||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
name: string;
|
||||
id: string;
|
||||
remoteFunc(params: Record<string, any>): Promise<any>; // 远程模式下的请求函数,返回一个 Promise
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'submit'): void;
|
||||
(e: 'update:visible', value: boolean): void;
|
||||
}>();
|
||||
|
||||
const currentVisible = computed({
|
||||
get() {
|
||||
return props.visible;
|
||||
},
|
||||
set(value) {
|
||||
emit('update:visible', value);
|
||||
},
|
||||
});
|
||||
const loading = ref(false);
|
||||
|
||||
const form = reactive({
|
||||
name: '',
|
||||
});
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
|
||||
const handleCancel = () => {
|
||||
currentVisible.value = false;
|
||||
form.name = '';
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
const handleConfirm = () => {
|
||||
formRef.value?.validate(async (errors: undefined | Record<string, ValidatedError>) => {
|
||||
if (!errors) {
|
||||
try {
|
||||
loading.value = true;
|
||||
await props.remoteFunc({ id: props.id });
|
||||
Message.success(t('common.deleteSuccess'));
|
||||
handleCancel();
|
||||
emit('submit');
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
:deep(.arco-form-item-label) {
|
||||
color: var(--color-text-2) !important;
|
||||
}
|
||||
</style>
|
|
@ -86,10 +86,17 @@
|
|||
:page-change="propsEvent.pageChange"
|
||||
:pagination="propsRes.msPagination!"
|
||||
/>
|
||||
<DeleteModal
|
||||
:id="currentDeleteObj.name"
|
||||
v-model:visible="deleteVisible"
|
||||
:name="currentDeleteObj.name"
|
||||
:remote-func="deleteSingleBug"
|
||||
@submit="handleSingleDelete"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { Message, TableData } from '@arco-design/web-vue';
|
||||
|
||||
import { MsAdvanceFilter, timeSelectOptions } from '@/components/pure/ms-advance-filter';
|
||||
import { FilterFormItem, FilterType } from '@/components/pure/ms-advance-filter/type';
|
||||
|
@ -104,8 +111,9 @@
|
|||
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||
import MsEditComp from '@/components/business/ms-edit-comp';
|
||||
import BugDetailDrawer from './components/bug-detail-drawer.vue';
|
||||
import DeleteModal from './components/deleteModal.vue';
|
||||
|
||||
import { getBugList, getExportConfig } from '@/api/modules/bug-management';
|
||||
import { deleteSingleBug, getBugList, getExportConfig } from '@/api/modules/bug-management';
|
||||
import { updateOrAddProjectUserGroup } from '@/api/modules/project-management/usergroup';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import router from '@/router';
|
||||
|
@ -127,6 +135,8 @@
|
|||
const detailVisible = ref(false);
|
||||
const activeDetailId = ref<string>('');
|
||||
const activeCaseIndex = ref<number>(0);
|
||||
const currentDeleteObj = reactive<{ id: string; name: string }>({ id: '', name: '' });
|
||||
const deleteVisible = ref(false);
|
||||
|
||||
const syncObject = reactive({
|
||||
time: '',
|
||||
|
@ -332,6 +342,18 @@
|
|||
setProps({ data });
|
||||
};
|
||||
|
||||
const handleSingleDelete = (record?: TableData) => {
|
||||
if (record) {
|
||||
currentDeleteObj.id = record.id;
|
||||
currentDeleteObj.name = record.name;
|
||||
deleteVisible.value = true;
|
||||
} else {
|
||||
fetchData();
|
||||
currentDeleteObj.id = '';
|
||||
currentDeleteObj.name = '';
|
||||
}
|
||||
};
|
||||
|
||||
const handleCreate = () => {
|
||||
router.push({
|
||||
name: 'bugManagementBugEdit',
|
||||
|
@ -391,7 +413,7 @@
|
|||
|
||||
function handleMoreActionSelect(item: ActionsItem, record: BugListItem) {
|
||||
if (item.eventTag === 'delete') {
|
||||
handleDelete(record);
|
||||
handleSingleDelete(record);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,12 @@ export default {
|
|||
syncBugTipRowTwo: '新增缺陷和更新已有的缺陷?',
|
||||
bugAutoSync: '系统 {name} 自动同步',
|
||||
syncTime: '同步时间',
|
||||
deleteLabel: '删除后,MeterSphere 创建的缺陷进入回收站;第三方平台同步的缺陷将不做回收',
|
||||
nameIsIncorrect: '缺陷名称不正确',
|
||||
selectedCount: '(已选 {count} 条缺陷)',
|
||||
batchEdit: '批量编辑',
|
||||
selectProps: '选择属性',
|
||||
batchUpdate: '批量更新为',
|
||||
edit: {
|
||||
defaultSystemTemplate: '默认为系统模板',
|
||||
content: '缺陷内容',
|
||||
|
|
|
@ -2,10 +2,7 @@
|
|||
<MsCard simple>
|
||||
<MsAdvanceFilter :filter-config-list="filterConfigList" :row-count="filterRowCount">
|
||||
<template #left>
|
||||
<div class="flex gap-[12px]">
|
||||
<a-button type="primary" @click="handleCreate">{{ t('bugManagement.createBug') }} </a-button>
|
||||
<a-button type="primary" @click="handleSync">{{ t('bugManagement.syncBug') }} </a-button>
|
||||
</div>
|
||||
<div></div>
|
||||
</template>
|
||||
</MsAdvanceFilter>
|
||||
<MsBaseTable v-bind="propsRes" v-on="propsEvent">
|
||||
|
@ -19,8 +16,6 @@
|
|||
<MsButton class="!mr-0" @click="handleCopy(record)">{{ t('common.copy') }}</MsButton>
|
||||
<a-divider direction="vertical" />
|
||||
<MsButton class="!mr-0" @click="handleEdit(record)">{{ t('common.edit') }}</MsButton>
|
||||
<a-divider direction="vertical" />
|
||||
<MsButton class="!mr-0" status="danger" @click="handleDelete(record)">{{ t('common.delete') }}</MsButton>
|
||||
</div>
|
||||
</template>
|
||||
<template #empty> </template>
|
||||
|
|
Loading…
Reference in New Issue