feat(缺陷管理): 查看详情&批量编辑&高级搜索
This commit is contained in:
parent
a39739e373
commit
ca1955a99e
|
@ -70,7 +70,7 @@
|
||||||
"resize-observer-polyfill": "^1.5.1",
|
"resize-observer-polyfill": "^1.5.1",
|
||||||
"sortablejs": "^1.15.0",
|
"sortablejs": "^1.15.0",
|
||||||
"tippy.js": "^6.3.7",
|
"tippy.js": "^6.3.7",
|
||||||
"vue": "^3.3.4",
|
"vue": "^3.4.15",
|
||||||
"vue-dompurify-html": "^4.1.4",
|
"vue-dompurify-html": "^4.1.4",
|
||||||
"vue-draggable-plus": "^0.3.5",
|
"vue-draggable-plus": "^0.3.5",
|
||||||
"vue-echarts": "^6.6.1",
|
"vue-echarts": "^6.6.1",
|
||||||
|
@ -140,7 +140,7 @@
|
||||||
"stylelint-order": "^5.0.0",
|
"stylelint-order": "^5.0.0",
|
||||||
"tailwindcss": "^3.3.3",
|
"tailwindcss": "^3.3.3",
|
||||||
"typescript": "^4.9.5",
|
"typescript": "^4.9.5",
|
||||||
"unplugin-auto-import": "^0.16.6",
|
"unplugin-auto-import": "^0.16.7",
|
||||||
"unplugin-vue-components": "^0.24.1",
|
"unplugin-vue-components": "^0.24.1",
|
||||||
"vite": "^3.2.7",
|
"vite": "^3.2.7",
|
||||||
"vite-plugin-compression": "^0.5.1",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
|
|
|
@ -80,7 +80,7 @@
|
||||||
|
|
||||||
const handleResetFilter = () => {
|
const handleResetFilter = () => {
|
||||||
filterResult.value = { ...defaultFilterResult };
|
filterResult.value = { ...defaultFilterResult };
|
||||||
emit('keywordSearch', '', { ...defaultFilterResult });
|
emit('advSearch', { ...defaultFilterResult });
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFilter = (filter: FilterResult) => {
|
const handleFilter = (filter: FilterResult) => {
|
||||||
|
|
|
@ -46,7 +46,7 @@ export interface BugEditCustomFieldItem {
|
||||||
type: string;
|
type: string;
|
||||||
value: string;
|
value: string;
|
||||||
}
|
}
|
||||||
export type BugBatchUpdateFiledType = 'single_select' | 'multiple_select' | 'tag' | 'input' | 'user_selector' | 'date';
|
export type BugBatchUpdateFiledType = 'single_select' | 'multiple_select' | 'tags' | 'input' | 'user_selector' | 'date';
|
||||||
export interface BugBatchUpdateFiledForm {
|
export interface BugBatchUpdateFiledForm {
|
||||||
attribute: string;
|
attribute: string;
|
||||||
value: string[];
|
value: string[];
|
||||||
|
|
|
@ -24,19 +24,16 @@
|
||||||
>
|
>
|
||||||
<a-select v-model:model-value="form.attribute" @change="handleArrtibuteChange">
|
<a-select v-model:model-value="form.attribute" @change="handleArrtibuteChange">
|
||||||
<a-optgroup :label="t('bugManagement.batchUpdate.systemFiled')">
|
<a-optgroup :label="t('bugManagement.batchUpdate.systemFiled')">
|
||||||
<a-option
|
<a-option v-for="item in systemOptionList" :key="item.value" :value="item.value">{{
|
||||||
v-for="item in systemOptionList"
|
|
||||||
:key="item.value"
|
|
||||||
:disabled="form.attribute === 'status'"
|
|
||||||
:value="item.value"
|
|
||||||
>{{ item.label }}</a-option
|
|
||||||
>
|
|
||||||
</a-optgroup>
|
|
||||||
<a-optgroup :label="t('bugManagement.batchUpdate.customFiled')">
|
|
||||||
<a-option v-for="item in customOptionList" :key="item.value" :value="item.value">{{
|
|
||||||
item.label
|
item.label
|
||||||
}}</a-option>
|
}}</a-option>
|
||||||
</a-optgroup>
|
</a-optgroup>
|
||||||
|
<!-- V3.0 先不上自定义字段的批量更新 -->
|
||||||
|
<!-- <a-optgroup :label="t('bugManagement.batchUpdate.customFiled')">
|
||||||
|
<a-option v-for="item in customOptionList" :disabled="form.attribute === 'status'" :key="item.value" :value="item.value">{{
|
||||||
|
item.label
|
||||||
|
}}</a-option>
|
||||||
|
</a-optgroup> -->
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item
|
<a-form-item
|
||||||
|
@ -67,7 +64,7 @@
|
||||||
:label="t('bugManagement.batchUpdate.update')"
|
:label="t('bugManagement.batchUpdate.update')"
|
||||||
:rules="[{ required: true }]"
|
:rules="[{ required: true }]"
|
||||||
>
|
>
|
||||||
<template v-if="valueMode === 'tag'">
|
<template v-if="valueMode === 'tags'">
|
||||||
<MsTagsInput v-model:modelValue="form.value" :disabled="!form.attribute"></MsTagsInput>
|
<MsTagsInput v-model:modelValue="form.value" :disabled="!form.attribute"></MsTagsInput>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="valueMode === 'user_selector'">
|
<template v-else-if="valueMode === 'user_selector'">
|
||||||
|
@ -131,6 +128,7 @@
|
||||||
import { updateBatchBug } from '@/api/modules/bug-management';
|
import { updateBatchBug } from '@/api/modules/bug-management';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import { useAppStore } from '@/store';
|
import { useAppStore } from '@/store';
|
||||||
|
import { tableParamsToRequestParams } from '@/utils';
|
||||||
|
|
||||||
import type { BugBatchUpdateFiledType } from '@/models/bug-management';
|
import type { BugBatchUpdateFiledType } from '@/models/bug-management';
|
||||||
import { BugBatchUpdateFiledForm, BugEditCustomField } from '@/models/bug-management';
|
import { BugBatchUpdateFiledForm, BugEditCustomField } from '@/models/bug-management';
|
||||||
|
@ -149,21 +147,17 @@
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const selectCount = computed(() => props.selectParam.currentSelectCount);
|
const selectCount = computed(() => props.selectParam.currentSelectCount);
|
||||||
const systemOptionList = computed(() => [
|
const systemOptionList = computed(() => [
|
||||||
{
|
|
||||||
label: t('bugManagement.batchUpdate.handleUser'),
|
|
||||||
value: 'handleUser',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: t('bugManagement.batchUpdate.tag'),
|
label: t('bugManagement.batchUpdate.tag'),
|
||||||
value: 'tag',
|
value: 'tags',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
const customOptionList = computed(() => {
|
// const customOptionList = computed(() => {
|
||||||
return props.customFields.map((item) => ({
|
// return props.customFields.map((item) => ({
|
||||||
label: item.fieldName,
|
// label: item.fieldName,
|
||||||
value: item.fieldId,
|
// value: item.fieldId,
|
||||||
}));
|
// }));
|
||||||
});
|
// });
|
||||||
const currentVisible = computed({
|
const currentVisible = computed({
|
||||||
get() {
|
get() {
|
||||||
return props.visible;
|
return props.visible;
|
||||||
|
@ -189,7 +183,15 @@
|
||||||
|
|
||||||
const formRef = ref<FormInstance>();
|
const formRef = ref<FormInstance>();
|
||||||
|
|
||||||
|
const formReset = () => {
|
||||||
|
form.attribute = '';
|
||||||
|
form.value = [];
|
||||||
|
form.inputValue = '';
|
||||||
|
form.append = false;
|
||||||
|
};
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
|
formReset();
|
||||||
currentVisible.value = false;
|
currentVisible.value = false;
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
};
|
};
|
||||||
|
@ -198,8 +200,8 @@
|
||||||
const handleArrtibuteChange = (value: SelectValue) => {
|
const handleArrtibuteChange = (value: SelectValue) => {
|
||||||
form.value = [];
|
form.value = [];
|
||||||
form.inputValue = '';
|
form.inputValue = '';
|
||||||
if (value === 'tag') {
|
if (value === 'tags') {
|
||||||
valueMode.value = 'tag';
|
valueMode.value = 'tags';
|
||||||
showAppend.value = true;
|
showAppend.value = true;
|
||||||
} else if (value === 'handleUser') {
|
} else if (value === 'handleUser') {
|
||||||
valueMode.value = 'user_selector';
|
valueMode.value = 'user_selector';
|
||||||
|
@ -228,17 +230,13 @@
|
||||||
if (!errors) {
|
if (!errors) {
|
||||||
try {
|
try {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const params = {
|
const tmpObj = {
|
||||||
excludeIds: props.selectParam.excludeIds,
|
...tableParamsToRequestParams(props.selectParam),
|
||||||
selectIds: props.selectParam.selectedIds,
|
|
||||||
selectAll: props.selectParam.selectAll,
|
|
||||||
// 查询条件
|
|
||||||
condition: props.selectParam.condition,
|
|
||||||
projectId: appStore.currentProjectId,
|
projectId: appStore.currentProjectId,
|
||||||
[form.attribute]: form.value || form.inputValue,
|
[form.attribute]: form.value || form.inputValue,
|
||||||
append: form.append,
|
append: form.append,
|
||||||
};
|
};
|
||||||
await updateBatchBug(params);
|
await updateBatchBug(tmpObj);
|
||||||
Message.success(t('common.deleteSuccess'));
|
Message.success(t('common.deleteSuccess'));
|
||||||
handleCancel();
|
handleCancel();
|
||||||
emit('submit');
|
emit('submit');
|
||||||
|
|
|
@ -88,20 +88,20 @@
|
||||||
<template #title>
|
<template #title>
|
||||||
{{ t('bugManagement.detail.detail') }}
|
{{ t('bugManagement.detail.detail') }}
|
||||||
</template>
|
</template>
|
||||||
<BugDetailTab :detail-info="detailInfo" />
|
<BugDetailTab />
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="case">
|
<a-tab-pane key="case">
|
||||||
<template #title>
|
<template #title>
|
||||||
{{ t('bugManagement.detail.case') }}
|
{{ t('bugManagement.detail.case') }}
|
||||||
<a-badge class="relative top-1 ml-1" :count="1000" :max-count="99" />
|
<a-badge class="relative top-1 ml-1" :count="1000" :max-count="99" />
|
||||||
</template>
|
</template>
|
||||||
<BugCaseTab :detail-info="detailInfo" />
|
<BugCaseTab />
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="comment">
|
<a-tab-pane key="comment">
|
||||||
<template #title>
|
<template #title>
|
||||||
{{ t('bugManagement.detail.comment') }}
|
{{ t('bugManagement.detail.comment') }}
|
||||||
</template>
|
</template>
|
||||||
<CommentTab ref="commentRef" bug-id="1070838426116099" />
|
<CommentTab ref="commentRef" bug-id="detailInfo.id" />
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
</div>
|
</div>
|
||||||
|
@ -123,16 +123,17 @@
|
||||||
<!-- 自定义字段结束 -->
|
<!-- 自定义字段结束 -->
|
||||||
<div class="baseItem">
|
<div class="baseItem">
|
||||||
<span class="label"> {{ t('bugManagement.detail.tag') }}</span>
|
<span class="label"> {{ t('bugManagement.detail.tag') }}</span>
|
||||||
<!-- <MsTagsInput></MsTagsInput> -->
|
<MsTagsInput v-model:model-value="tags"></MsTagsInput>
|
||||||
</div>
|
</div>
|
||||||
<div class="baseItem">
|
<!-- 创建人 创建时间需求说先去掉 -->
|
||||||
|
<!-- <div class="baseItem">
|
||||||
<span class="label"> {{ t('bugManagement.detail.creator') }}</span>
|
<span class="label"> {{ t('bugManagement.detail.creator') }}</span>
|
||||||
<span>{{ detailInfo?.createUser }}</span>
|
<span>{{ detailInfo?.createUserName }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="baseItem">
|
<div class="baseItem">
|
||||||
<span class="label"> {{ t('bugManagement.detail.createTime') }}</span>
|
<span class="label"> {{ t('bugManagement.detail.createTime') }}</span>
|
||||||
<span>{{ dayjs(detailInfo?.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
|
<span>{{ dayjs(detailInfo?.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
|
||||||
</div>
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</MsSplitBox>
|
</MsSplitBox>
|
||||||
|
@ -153,7 +154,6 @@
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
import dayjs from 'dayjs';
|
|
||||||
|
|
||||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
import MsButton from '@/components/pure/ms-button/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';
|
||||||
|
@ -169,24 +169,29 @@
|
||||||
import BugDetailTab from './bugDetailTab.vue';
|
import BugDetailTab from './bugDetailTab.vue';
|
||||||
import CommentTab from './commentTab.vue';
|
import CommentTab from './commentTab.vue';
|
||||||
|
|
||||||
import { createOrUpdateComment, deleteSingleBug, followBug, getBugDetail } from '@/api/modules/bug-management/index';
|
import {
|
||||||
|
createOrUpdateComment,
|
||||||
|
deleteSingleBug,
|
||||||
|
followBug,
|
||||||
|
getBugDetail,
|
||||||
|
getTemplateById,
|
||||||
|
} from '@/api/modules/bug-management/index';
|
||||||
import useFullScreen from '@/hooks/useFullScreen';
|
import useFullScreen from '@/hooks/useFullScreen';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useModal from '@/hooks/useModal';
|
import useModal from '@/hooks/useModal';
|
||||||
import { useAppStore } from '@/store';
|
import { useAppStore } from '@/store';
|
||||||
import useFeatureCaseStore from '@/store/modules/case/featureCase';
|
|
||||||
import { characterLimit } from '@/utils';
|
import { characterLimit } from '@/utils';
|
||||||
|
|
||||||
import type { CaseManagementTable, CustomAttributes, TabItemType } from '@/models/caseManagement/featureCase';
|
import { BugEditCustomField, BugEditFormObject } from '@/models/bug-management';
|
||||||
|
import { SelectValue } from '@/models/projectManagement/menuManagement';
|
||||||
import { RouteEnum } from '@/enums/routeEnum';
|
import { RouteEnum } from '@/enums/routeEnum';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const detailDrawerRef = ref<InstanceType<typeof MsDetailDrawer>>();
|
const detailDrawerRef = ref<InstanceType<typeof MsDetailDrawer>>();
|
||||||
const wrapperRef = ref();
|
const wrapperRef = ref();
|
||||||
const { isFullScreen, toggleFullScreen } = useFullScreen(wrapperRef);
|
const { isFullScreen, toggleFullScreen } = useFullScreen(wrapperRef);
|
||||||
const featureCaseStore = useFeatureCaseStore();
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { openModal } = useModal();
|
const { openDeleteModal } = useModal();
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
|
@ -197,39 +202,68 @@
|
||||||
pageChange: (page: number) => Promise<void>; // 分页变更函数
|
pageChange: (page: number) => Promise<void>; // 分页变更函数
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits(['update:visible']);
|
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const commentContent = ref('');
|
const commentContent = ref('');
|
||||||
const commentRef = ref();
|
const commentRef = ref();
|
||||||
const noticeUserIds = ref<string[]>([]); // 通知人ids
|
const noticeUserIds = ref<string[]>([]); // 通知人ids
|
||||||
|
const fApi = ref();
|
||||||
|
const formRules = ref<FormItem[]>([]); // 表单规则
|
||||||
|
const formItem = ref<FormRuleItem[]>([]); // 表单项
|
||||||
const currentProjectId = computed(() => appStore.currentProjectId);
|
const currentProjectId = computed(() => appStore.currentProjectId);
|
||||||
|
const showDrawerVisible = defineModel<boolean>('visible', { default: false });
|
||||||
|
|
||||||
const showDrawerVisible = ref<boolean>(false);
|
|
||||||
|
|
||||||
const tabSettingList = computed(() => {
|
|
||||||
return featureCaseStore.tabSettingList;
|
|
||||||
});
|
|
||||||
|
|
||||||
const tabSetting = ref<TabItemType[]>([...tabSettingList.value]);
|
|
||||||
const activeTab = ref<string | number>('detail');
|
const activeTab = ref<string | number>('detail');
|
||||||
|
|
||||||
const detailInfo = ref<Record<string, any>>({
|
const detailInfo = ref<Record<string, any>>({}); // 存储当前详情信息,通过loadBug 获取
|
||||||
tags: [],
|
const tags = ref([]);
|
||||||
id: '',
|
|
||||||
createUser: '',
|
|
||||||
createTime: '',
|
|
||||||
description: '',
|
|
||||||
followFlag: false,
|
|
||||||
templateId: '',
|
|
||||||
title: '',
|
|
||||||
});
|
|
||||||
const customFields = ref<CustomAttributes[]>([]);
|
|
||||||
|
|
||||||
function loadedBug(detail: CaseManagementTable) {
|
// 处理表单格式
|
||||||
|
const getFormRules = (arr: BugEditCustomField[]) => {
|
||||||
|
formRules.value = [];
|
||||||
|
if (Array.isArray(arr) && arr.length) {
|
||||||
|
formRules.value = arr.map((item) => {
|
||||||
|
return {
|
||||||
|
type: item.type,
|
||||||
|
name: item.fieldId,
|
||||||
|
label: item.fieldName,
|
||||||
|
value: item.value,
|
||||||
|
options: item.platformOptionJson ? JSON.parse(item.platformOptionJson) : item.options,
|
||||||
|
required: item.required as boolean,
|
||||||
|
props: {
|
||||||
|
modelValue: item.value,
|
||||||
|
options: item.platformOptionJson ? JSON.parse(item.platformOptionJson) : item.options,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const templateChange = async (v: SelectValue) => {
|
||||||
|
if (v) {
|
||||||
|
try {
|
||||||
|
const res = await getTemplateById({ projectId: appStore.currentProjectId, id: v });
|
||||||
|
getFormRules(res.customFields);
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
async function loadedBug(detail: BugEditFormObject) {
|
||||||
detailInfo.value = { ...detail };
|
detailInfo.value = { ...detail };
|
||||||
customFields.value = detailInfo.value.customFields;
|
const { templateId } = detail;
|
||||||
|
// tag 赋值
|
||||||
|
tags.value = detail.tags || [];
|
||||||
|
// 初始化自定义字段
|
||||||
|
await templateChange(templateId);
|
||||||
|
const tmpObj = {};
|
||||||
|
if (detail.customFields && Array.isArray(detail.customFields)) {
|
||||||
|
detail.customFields.forEach((item) => {
|
||||||
|
tmpObj[item.id] = item.value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 自定义字段赋值
|
||||||
|
fApi.value.setValue(tmpObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
const editLoading = ref<boolean>(false);
|
const editLoading = ref<boolean>(false);
|
||||||
|
@ -276,15 +310,9 @@
|
||||||
// 删除用例
|
// 删除用例
|
||||||
function deleteHandler() {
|
function deleteHandler() {
|
||||||
const { id, name } = detailInfo.value;
|
const { id, name } = detailInfo.value;
|
||||||
openModal({
|
openDeleteModal({
|
||||||
type: 'error',
|
title: t('bugManagement.detail.deleteTitle', { name: characterLimit(name) }),
|
||||||
title: t('caseManagement.featureCase.deleteCaseTitle', { name: characterLimit(name) }),
|
content: t('bugManagement.detail.deleteContent'),
|
||||||
content: t('caseManagement.featureCase.beforeDeleteCase'),
|
|
||||||
okText: t('common.confirmDelete'),
|
|
||||||
cancelText: t('common.cancel'),
|
|
||||||
okButtonProps: {
|
|
||||||
status: 'danger',
|
|
||||||
},
|
|
||||||
onBeforeOk: async () => {
|
onBeforeOk: async () => {
|
||||||
try {
|
try {
|
||||||
const params = {
|
const params = {
|
||||||
|
@ -301,15 +329,9 @@
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hideCancel: false,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const formRules = ref<FormItem[]>([]);
|
|
||||||
const formItem = ref<FormRuleItem[]>([]);
|
|
||||||
|
|
||||||
const isDisabled = ref<boolean>(false);
|
|
||||||
|
|
||||||
// 表单配置项
|
// 表单配置项
|
||||||
const options = {
|
const options = {
|
||||||
resetBtn: false, // 不展示默认配置的重置和提交
|
resetBtn: false, // 不展示默认配置的重置和提交
|
||||||
|
@ -336,26 +358,6 @@
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const fApi = ref(null);
|
|
||||||
// 初始化表单
|
|
||||||
function initForm() {
|
|
||||||
formRules.value = customFields.value.map((item: any) => {
|
|
||||||
return {
|
|
||||||
type: item.type,
|
|
||||||
name: item.fieldId,
|
|
||||||
label: item.fieldName,
|
|
||||||
value: JSON.parse(item.defaultValue),
|
|
||||||
required: item.required,
|
|
||||||
options: item.options || [],
|
|
||||||
props: {
|
|
||||||
modelValue: JSON.parse(item.defaultValue),
|
|
||||||
disabled: isDisabled.value,
|
|
||||||
options: item.options || [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}) as FormItem[];
|
|
||||||
}
|
|
||||||
|
|
||||||
async function publishHandler(currentContent: string) {
|
async function publishHandler(currentContent: string) {
|
||||||
const regex = /data-id="([^"]*)"/g;
|
const regex = /data-id="([^"]*)"/g;
|
||||||
const matchesNotifier = currentContent.match(regex);
|
const matchesNotifier = currentContent.match(regex);
|
||||||
|
@ -365,7 +367,6 @@
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const params = {
|
const params = {
|
||||||
// TODO 本地测试
|
|
||||||
bugId: detailInfo.value.id,
|
bugId: detailInfo.value.id,
|
||||||
notifier: notifiers,
|
notifier: notifiers,
|
||||||
replyUser: '',
|
replyUser: '',
|
||||||
|
@ -381,36 +382,6 @@
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
|
||||||
() => customFields.value,
|
|
||||||
() => {
|
|
||||||
initForm();
|
|
||||||
},
|
|
||||||
{ deep: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.visible,
|
|
||||||
(val) => {
|
|
||||||
showDrawerVisible.value = val;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => showDrawerVisible.value,
|
|
||||||
(val) => {
|
|
||||||
emit('update:visible', val);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => tabSettingList.value,
|
|
||||||
() => {
|
|
||||||
tabSetting.value = featureCaseStore.getTab();
|
|
||||||
},
|
|
||||||
{ deep: true, immediate: true }
|
|
||||||
);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
|
|
|
@ -33,19 +33,6 @@
|
||||||
<template #num="{ record, rowIndex }">
|
<template #num="{ record, rowIndex }">
|
||||||
<a-button type="text" class="px-0" @click="handleShowDetail(record.id, rowIndex)">{{ record.num }}</a-button>
|
<a-button type="text" class="px-0" @click="handleShowDetail(record.id, rowIndex)">{{ record.num }}</a-button>
|
||||||
</template>
|
</template>
|
||||||
<!-- 严重程度 -->
|
|
||||||
<template #severity="{ record }">
|
|
||||||
<MsEditComp mode="select" :options="severityOption" :default-value="record.severity" />
|
|
||||||
</template>
|
|
||||||
<!-- 状态 -->
|
|
||||||
<template #status="{ record }">
|
|
||||||
<MsEditComp mode="select" :options="statusOption" :default-value="record.statusName" />
|
|
||||||
</template>
|
|
||||||
<template #numberOfCase="{ record }">
|
|
||||||
<span class="cursor-pointer text-[rgb(var(--primary-5))]" @click="jumpToTestPlan(record)">{{
|
|
||||||
record.memberCount
|
|
||||||
}}</span>
|
|
||||||
</template>
|
|
||||||
<template #operation="{ record }">
|
<template #operation="{ record }">
|
||||||
<div class="flex flex-row flex-nowrap">
|
<div class="flex flex-row flex-nowrap">
|
||||||
<span v-permission="['PROJECT_BUG:READ+ADD']" class="flex flex-row">
|
<span v-permission="['PROJECT_BUG:READ+ADD']" class="flex flex-row">
|
||||||
|
@ -150,7 +137,6 @@
|
||||||
import useTable from '@/components/pure/ms-table/useTable';
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
||||||
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
import { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||||
import MsEditComp from '@/components/business/ms-edit-comp';
|
|
||||||
import BatchEditModal from './components/batchEditModal.vue';
|
import BatchEditModal from './components/batchEditModal.vue';
|
||||||
import BugDetailDrawer from './components/bug-detail-drawer.vue';
|
import BugDetailDrawer from './components/bug-detail-drawer.vue';
|
||||||
import DeleteModal from './components/deleteModal.vue';
|
import DeleteModal from './components/deleteModal.vue';
|
||||||
|
@ -164,13 +150,12 @@
|
||||||
getExportConfig,
|
getExportConfig,
|
||||||
syncBugOpenSource,
|
syncBugOpenSource,
|
||||||
} from '@/api/modules/bug-management';
|
} from '@/api/modules/bug-management';
|
||||||
import { updateOrAddProjectUserGroup } from '@/api/modules/project-management/usergroup';
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useModal from '@/hooks/useModal';
|
import useModal from '@/hooks/useModal';
|
||||||
import router from '@/router';
|
import router from '@/router';
|
||||||
import { useAppStore, useTableStore } from '@/store';
|
import { useAppStore, useTableStore } from '@/store';
|
||||||
import useLicenseStore from '@/store/modules/setting/license';
|
import useLicenseStore from '@/store/modules/setting/license';
|
||||||
import { customFieldToColumns } from '@/utils';
|
import { customFieldToColumns, tableParamsToRequestParams } from '@/utils';
|
||||||
|
|
||||||
import { BugEditCustomField, BugListItem } from '@/models/bug-management';
|
import { BugEditCustomField, BugListItem } from '@/models/bug-management';
|
||||||
import { RouteEnum } from '@/enums/routeEnum';
|
import { RouteEnum } from '@/enums/routeEnum';
|
||||||
|
@ -230,29 +215,8 @@
|
||||||
{
|
{
|
||||||
title: 'bugManagement.bugName',
|
title: 'bugManagement.bugName',
|
||||||
dataIndex: 'title',
|
dataIndex: 'title',
|
||||||
type: FilterType.SELECT,
|
type: FilterType.INPUT,
|
||||||
selectProps: {
|
backendType: BackEndEnum.STRING,
|
||||||
mode: 'static',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
label: 'title',
|
|
||||||
value: 'title',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'name',
|
|
||||||
value: 'name',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'bugManagement.severity',
|
|
||||||
dataIndex: 'severity',
|
|
||||||
type: FilterType.SELECT,
|
|
||||||
selectProps: {
|
|
||||||
mode: 'static',
|
|
||||||
multiple: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'bugManagement.createTime',
|
title: 'bugManagement.createTime',
|
||||||
|
@ -280,16 +244,9 @@
|
||||||
{
|
{
|
||||||
title: 'bugManagement.bugName',
|
title: 'bugManagement.bugName',
|
||||||
dataIndex: 'title',
|
dataIndex: 'title',
|
||||||
width: 300,
|
width: 200,
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: 'bugManagement.severity',
|
|
||||||
slotName: 'severity',
|
|
||||||
width: 102,
|
|
||||||
showDrag: true,
|
|
||||||
dataIndex: 'severity',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: 'bugManagement.status',
|
title: 'bugManagement.status',
|
||||||
dataIndex: 'statusName',
|
dataIndex: 'statusName',
|
||||||
|
@ -361,16 +318,6 @@
|
||||||
const customColumns = await getCustomFieldColumns();
|
const customColumns = await getCustomFieldColumns();
|
||||||
await tableStore.initColumn(TableKeyEnum.BUG_MANAGEMENT, columns.concat(customColumns), 'drawer');
|
await tableStore.initColumn(TableKeyEnum.BUG_MANAGEMENT, columns.concat(customColumns), 'drawer');
|
||||||
|
|
||||||
const handleNameChange = async (record: BugListItem) => {
|
|
||||||
try {
|
|
||||||
await updateOrAddProjectUserGroup(record);
|
|
||||||
Message.success(t('common.updateSuccess'));
|
|
||||||
return true;
|
|
||||||
} catch (error) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const { propsRes, propsEvent, setKeyword, setAdvanceFilter, setLoadListParams, setProps, resetSelector, loadList } =
|
const { propsRes, propsEvent, setKeyword, setAdvanceFilter, setLoadListParams, setProps, resetSelector, loadList } =
|
||||||
useTable(
|
useTable(
|
||||||
getBugList,
|
getBugList,
|
||||||
|
@ -382,8 +329,7 @@
|
||||||
showSetting: true,
|
showSetting: true,
|
||||||
scroll: { x: '1800px' },
|
scroll: { x: '1800px' },
|
||||||
},
|
},
|
||||||
undefined,
|
(record: TableData) => ({ ...record, handleUser: record.handleUserName })
|
||||||
(record) => handleNameChange(record)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const tableBatchActions = {
|
const tableBatchActions = {
|
||||||
|
@ -503,30 +449,16 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleBatchDelete = (params: BatchActionQueryParams) => {
|
const handleBatchDelete = (params: BatchActionQueryParams) => {
|
||||||
// TODO: 等后端接口传给后端id,获取内部和第三方的数量
|
|
||||||
const internalCount = 2;
|
|
||||||
const externalCount = 0;
|
|
||||||
openDeleteModal({
|
openDeleteModal({
|
||||||
title: t('bugManagement.deleteCount', { count: params.selectedIds?.length }),
|
title: t('bugManagement.deleteCount', { count: params.selectedIds?.length }),
|
||||||
content: `${internalCount ? t('bugManagement.deleteTipInternal', { count: internalCount }) : ''}${
|
content: t('bugManagement.deleteTip'),
|
||||||
internalCount ? ';' : ''
|
|
||||||
} ${
|
|
||||||
externalCount
|
|
||||||
? t('bugManagement.deleteTipExternal', {
|
|
||||||
count: externalCount,
|
|
||||||
})
|
|
||||||
: ''
|
|
||||||
}`,
|
|
||||||
onBeforeOk: async () => {
|
onBeforeOk: async () => {
|
||||||
try {
|
try {
|
||||||
const { selectedIds, selectAll, excludeIds } = params;
|
const tmpObj = {
|
||||||
await deleteBatchBug({
|
...tableParamsToRequestParams(params),
|
||||||
selectIds: selectedIds || [],
|
|
||||||
selectAll,
|
|
||||||
excludeIds,
|
|
||||||
condition: { keyword: keyword.value },
|
|
||||||
projectId: projectId.value,
|
projectId: projectId.value,
|
||||||
});
|
};
|
||||||
|
await deleteBatchBug(tmpObj);
|
||||||
Message.success(t('common.deleteSuccess'));
|
Message.success(t('common.deleteSuccess'));
|
||||||
fetchData();
|
fetchData();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
@ -32,6 +32,7 @@ export default {
|
||||||
deleteCount: '确认删除 {count} 个缺陷吗?',
|
deleteCount: '确认删除 {count} 个缺陷吗?',
|
||||||
deleteTipInternal: '删除后,{count} 条 MeterSphere 创建的缺陷进入回收站',
|
deleteTipInternal: '删除后,{count} 条 MeterSphere 创建的缺陷进入回收站',
|
||||||
deleteTipExternal: '{count} 条第三方平台同步的缺陷将不做回收',
|
deleteTipExternal: '{count} 条第三方平台同步的缺陷将不做回收',
|
||||||
|
deleteTip: 'Metersphere进入回收站, 三方平台的不做回收',
|
||||||
edit: {
|
edit: {
|
||||||
defaultSystemTemplate: '默认为系统模板',
|
defaultSystemTemplate: '默认为系统模板',
|
||||||
content: '缺陷内容',
|
content: '缺陷内容',
|
||||||
|
@ -67,6 +68,8 @@ export default {
|
||||||
detail: '详情',
|
detail: '详情',
|
||||||
case: '用例',
|
case: '用例',
|
||||||
comment: '评论',
|
comment: '评论',
|
||||||
|
deleteTitle: '确认删除 {name} 吗?',
|
||||||
|
deleteContent: '删除后,MeterSphere 创建的缺陷进入回收站;第三方平台同步的缺陷将不做回收',
|
||||||
},
|
},
|
||||||
batchUpdate: {
|
batchUpdate: {
|
||||||
attribute: '选择属性',
|
attribute: '选择属性',
|
||||||
|
|
Loading…
Reference in New Issue