feat: 编辑组件封装
This commit is contained in:
parent
b44e170c90
commit
3f7b5f133a
|
@ -0,0 +1,146 @@
|
||||||
|
import { PropType } from 'vue';
|
||||||
|
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
import './style.less';
|
||||||
|
import { MsUserSelector } from '../ms-user-selector';
|
||||||
|
import { UserRequestTypeEnum } from '../ms-user-selector/utils';
|
||||||
|
import { ModelValueType } from './types';
|
||||||
|
import Message from '@arco-design/web-vue/es/message';
|
||||||
|
|
||||||
|
type EditStatus = 'null' | 'active' | 'hover';
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'MsEditComp',
|
||||||
|
props: {
|
||||||
|
// 具体绑定的值
|
||||||
|
modelValue: {
|
||||||
|
type: [String, Number, Boolean, Object, Array] as PropType<ModelValueType>,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
// 表格默认显示的值
|
||||||
|
defaultValue: {
|
||||||
|
type: [String, Number, Boolean, Object, Array] as PropType<ModelValueType>,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
// 组件类型
|
||||||
|
mode: {
|
||||||
|
type: String,
|
||||||
|
default: 'Input',
|
||||||
|
},
|
||||||
|
// 选择框的选项
|
||||||
|
options: {
|
||||||
|
type: Array as PropType<{ value: string; label: string }[]>,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
// 用户选择器的类型
|
||||||
|
userSelectorType: {
|
||||||
|
type: String as PropType<UserRequestTypeEnum>,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: {
|
||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
|
change: (value: ModelValueType, cb: (result: boolean, defaultValue: string) => void) => true,
|
||||||
|
},
|
||||||
|
setup(props, { emit }) {
|
||||||
|
const { mode, options, modelValue, defaultValue } = toRefs(props);
|
||||||
|
const oldModelValue = ref(modelValue.value);
|
||||||
|
const editStatus = ref<EditStatus>('null');
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const handleChange = (value: ModelValueType) => {
|
||||||
|
emit('change', value, (result: boolean, v: string) => {
|
||||||
|
if (result) {
|
||||||
|
defaultValue.value = v;
|
||||||
|
Message.success(t('common.updateSuccess'));
|
||||||
|
} else {
|
||||||
|
Message.error(t('common.updateFail'));
|
||||||
|
modelValue.value = oldModelValue.value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyDown = (e: KeyboardEvent) => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
handleChange(modelValue.value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClick = () => {
|
||||||
|
editStatus.value = 'active';
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleReset = () => {
|
||||||
|
editStatus.value = 'null';
|
||||||
|
modelValue.value = oldModelValue.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBlur = () => {
|
||||||
|
handleReset();
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderDiv = () => {
|
||||||
|
const _defaultValue = Array.isArray(defaultValue.value) ? defaultValue.value.join(',') : defaultValue.value;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div onClick={handleClick} class={'cursor-pointer'}>
|
||||||
|
{_defaultValue}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderPrivew = () => {
|
||||||
|
const _defaultValue = Array.isArray(defaultValue.value) ? defaultValue.value.join(',') : defaultValue.value;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
onClick={handleClick}
|
||||||
|
onMouseleave={() => {
|
||||||
|
if (editStatus.value === 'hover') editStatus.value = 'null';
|
||||||
|
}}
|
||||||
|
class="gap[8px] flex h-[32px] w-[112px] cursor-pointer flex-row items-center justify-between bg-[var(--color-text-n8)] p-[8px]"
|
||||||
|
>
|
||||||
|
<div class="grow">{_defaultValue}</div>
|
||||||
|
<div>
|
||||||
|
<icon-down size={16} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderChild = () => {
|
||||||
|
if (mode.value === 'input') {
|
||||||
|
return <a-input modelValue={modelValue} onKeyDown={handleKeyDown} onBlur={handleBlur} />;
|
||||||
|
}
|
||||||
|
if (mode.value === 'select') {
|
||||||
|
return <a-select modelValue={modelValue} options={options.value} onSelect={handleChange} />;
|
||||||
|
}
|
||||||
|
if (mode.value === 'tagInput') {
|
||||||
|
return <a-input-tag modelValue={modelValue} onKeyDown={handleKeyDown} onBlur={handleBlur} />;
|
||||||
|
}
|
||||||
|
if (mode.value === 'userSelect') {
|
||||||
|
return (
|
||||||
|
<MsUserSelector
|
||||||
|
modelValue={modelValue.value as string[]}
|
||||||
|
onSelect={handleChange}
|
||||||
|
type={props.userSelectorType}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return () => (
|
||||||
|
<div
|
||||||
|
class="ms-edit-comp"
|
||||||
|
onMouseenter={() => {
|
||||||
|
if (editStatus.value === 'null') editStatus.value = 'hover';
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{editStatus.value === 'null' && renderDiv()}
|
||||||
|
{editStatus.value === 'hover' && renderPrivew()}
|
||||||
|
{editStatus.value === 'active' && renderChild()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
|
@ -0,0 +1,12 @@
|
||||||
|
import EditComp from './edit-comp';
|
||||||
|
import type { App } from 'vue';
|
||||||
|
|
||||||
|
const MsEditComp = Object.assign(EditComp, {
|
||||||
|
install: (app: App) => {
|
||||||
|
app.component(EditComp.name, EditComp);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export type CommentInstance = InstanceType<typeof EditComp>;
|
||||||
|
|
||||||
|
export default MsEditComp;
|
|
@ -0,0 +1,3 @@
|
||||||
|
.child-bg > :first-child {
|
||||||
|
background-color: var(--color-text-8);
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
export type ModelValueType =
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| Record<string, any>
|
||||||
|
| (string | number | boolean | Record<string, any>)[];
|
|
@ -63,6 +63,7 @@
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'update:modelValue', value: string[]): void;
|
(e: 'update:modelValue', value: string[]): void;
|
||||||
|
(e: 'select', value: string[]): void;
|
||||||
}>();
|
}>();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
@ -135,6 +136,10 @@
|
||||||
'update:modelValue',
|
'update:modelValue',
|
||||||
tmpArr.map((item) => item[valueKey])
|
tmpArr.map((item) => item[valueKey])
|
||||||
);
|
);
|
||||||
|
emit(
|
||||||
|
'select',
|
||||||
|
tmpArr.map((item) => item[valueKey])
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
onBeforeMount(async () => {
|
||||||
|
|
|
@ -403,11 +403,15 @@
|
||||||
|
|
||||||
// 排序change事件
|
// 排序change事件
|
||||||
const handleSortChange = (dataIndex: string, direction: string) => {
|
const handleSortChange = (dataIndex: string, direction: string) => {
|
||||||
|
let firstIndex = 0;
|
||||||
|
if (attrs.selectable) {
|
||||||
|
firstIndex = 1;
|
||||||
|
}
|
||||||
const regex = /^__arco_data_index_(\d+)$/;
|
const regex = /^__arco_data_index_(\d+)$/;
|
||||||
const match = dataIndex.match(regex);
|
const match = dataIndex.match(regex);
|
||||||
const lastDigit = match && Number(match[1]);
|
const lastDigit = match && Number(match[1]);
|
||||||
if (lastDigit && !Number.isNaN(lastDigit)) {
|
if (lastDigit !== null && !Number.isNaN(lastDigit)) {
|
||||||
dataIndex = currentColumns.value[lastDigit].dataIndex as string;
|
dataIndex = currentColumns.value[lastDigit - firstIndex].dataIndex as string;
|
||||||
}
|
}
|
||||||
let sortOrder = '';
|
let sortOrder = '';
|
||||||
if (direction === 'ascend') {
|
if (direction === 'ascend') {
|
||||||
|
|
|
@ -7,11 +7,11 @@ export interface BugListItem {
|
||||||
handleUser: string; // 缺陷处理人
|
handleUser: string; // 缺陷处理人
|
||||||
relationCaseCount: number; // 关联用例数
|
relationCaseCount: number; // 关联用例数
|
||||||
platform: string; // 所属平台
|
platform: string; // 所属平台
|
||||||
tag: string; // 缺陷标签
|
tag: string[]; // 缺陷标签
|
||||||
createUser: string; // 创建人
|
createUser: string; // 创建人
|
||||||
updateUser: string; // 更新人
|
updateUser: string; // 更新人
|
||||||
createTime: string; // 创建时间
|
createTime: string; // 创建时间
|
||||||
updateTime: string; // 更新时间
|
updateTime: string; // 更新时间
|
||||||
deleted: string; // 删除标志
|
deleted: boolean; // 删除标志
|
||||||
}
|
}
|
||||||
export default {};
|
export default {};
|
||||||
|
|
|
@ -78,7 +78,7 @@
|
||||||
<template #left>
|
<template #left>
|
||||||
<div class="leftWrapper h-full">
|
<div class="leftWrapper h-full">
|
||||||
<div class="header h-[50px]">
|
<div class="header h-[50px]">
|
||||||
<a-tabs>
|
<a-tabs v-model:active-key="activeTab">
|
||||||
<a-tab-pane key="detail">
|
<a-tab-pane key="detail">
|
||||||
<BugDetailTab :detail-info="detailInfo" />
|
<BugDetailTab :detail-info="detailInfo" />
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
|
@ -88,9 +88,6 @@
|
||||||
<a-tab-pane key="comment">
|
<a-tab-pane key="comment">
|
||||||
<BugCommentTab :detail-info="detailInfo" />
|
<BugCommentTab :detail-info="detailInfo" />
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
<a-tab-pane key="history">
|
|
||||||
<BugHistoryTab :detail-info="detailInfo" />
|
|
||||||
</a-tab-pane>
|
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -126,7 +123,6 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</MsDetailDrawer>
|
</MsDetailDrawer>
|
||||||
<SettingDrawer v-model:visible="showSettingDrawer" />
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -142,6 +138,8 @@
|
||||||
import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
|
import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
|
||||||
import type { MsPaginationI } from '@/components/pure/ms-table/type';
|
import type { MsPaginationI } from '@/components/pure/ms-table/type';
|
||||||
import MsDetailDrawer from '@/components/business/ms-detail-drawer/index.vue';
|
import MsDetailDrawer from '@/components/business/ms-detail-drawer/index.vue';
|
||||||
|
import BugCaseTab from './bugCaseTab.vue';
|
||||||
|
import BugCommentTab from './bugCommentTab.vue';
|
||||||
import BugDetailTab from './bugDetailTab.vue';
|
import BugDetailTab from './bugDetailTab.vue';
|
||||||
|
|
||||||
import { deleteCaseRequest, followerCaseRequest, getCaseDetail } from '@/api/modules/case-management/featureCase';
|
import { deleteCaseRequest, followerCaseRequest, getCaseDetail } from '@/api/modules/case-management/featureCase';
|
||||||
|
@ -183,27 +181,12 @@
|
||||||
|
|
||||||
const showDrawerVisible = ref<boolean>(false);
|
const showDrawerVisible = ref<boolean>(false);
|
||||||
|
|
||||||
const showSettingDrawer = ref<boolean>(false);
|
|
||||||
function showMenuSetting() {
|
|
||||||
showSettingDrawer.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const tabSettingList = computed(() => {
|
const tabSettingList = computed(() => {
|
||||||
return featureCaseStore.tabSettingList;
|
return featureCaseStore.tabSettingList;
|
||||||
});
|
});
|
||||||
|
|
||||||
const tabSetting = ref<TabItemType[]>([...tabSettingList.value]);
|
const tabSetting = ref<TabItemType[]>([...tabSettingList.value]);
|
||||||
const activeTab = ref<string | number>('detail');
|
const activeTab = ref<string | number>('detail');
|
||||||
function changeTabs(key: string | number) {
|
|
||||||
activeTab.value = key;
|
|
||||||
switch (activeTab.value) {
|
|
||||||
case 'setting':
|
|
||||||
showMenuSetting();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const detailInfo = ref<Record<string, any>>({});
|
const detailInfo = ref<Record<string, any>>({});
|
||||||
const customFields = ref<CustomAttributes[]>([]);
|
const customFields = ref<CustomAttributes[]>([]);
|
||||||
|
@ -238,7 +221,9 @@
|
||||||
|
|
||||||
const shareLoading = ref<boolean>(false);
|
const shareLoading = ref<boolean>(false);
|
||||||
|
|
||||||
function shareHandler() {}
|
function shareHandler() {
|
||||||
|
Message.info(t('caseManagement.featureCase.share'));
|
||||||
|
}
|
||||||
|
|
||||||
const followLoading = ref<boolean>(false);
|
const followLoading = ref<boolean>(false);
|
||||||
// 关注
|
// 关注
|
||||||
|
@ -253,6 +238,7 @@
|
||||||
: t('caseManagement.featureCase.followSuccess')
|
: t('caseManagement.featureCase.followSuccess')
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.log(error);
|
console.log(error);
|
||||||
} finally {
|
} finally {
|
||||||
followLoading.value = false;
|
followLoading.value = false;
|
||||||
|
@ -283,6 +269,7 @@
|
||||||
updateSuccess();
|
updateSuccess();
|
||||||
detailDrawerRef.value?.openPrevDetail();
|
detailDrawerRef.value?.openPrevDetail();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,76 +1,64 @@
|
||||||
<template>
|
<template>
|
||||||
|
<div class="p-[16px]">
|
||||||
|
<div class="flex flex-row justify-between">
|
||||||
|
<a-dropdown trigger="hover">
|
||||||
|
<template #content>
|
||||||
|
<a-doption @click="showRelatedDrawer('api')">{{ t('bugManagement.detail.apiCase') }}</a-doption>
|
||||||
|
<a-doption @click="showRelatedDrawer('scenario')">{{ t('bugManagement.detail.scenarioCase') }}</a-doption>
|
||||||
|
<a-doption @click="showRelatedDrawer('ui')">{{ t('bugManagement.detail.uiCase') }}</a-doption>
|
||||||
|
<a-doption @click="showRelatedDrawer('performance')">{{
|
||||||
|
t('bugManagement.detail.performanceCase')
|
||||||
|
}}</a-doption>
|
||||||
|
</template>
|
||||||
|
<a-button type="primary">{{ t('bugManagement.edit.linkCase') }}</a-button>
|
||||||
|
</a-dropdown>
|
||||||
|
<a-input-search
|
||||||
|
v-model:model-value="keyword"
|
||||||
|
allow-clear
|
||||||
|
:placeholder="t('bugManagement.detail.searchCase')"
|
||||||
|
class="w-[230px]"
|
||||||
|
@search="searchUser"
|
||||||
|
@press-enter="searchUser"
|
||||||
|
></a-input-search>
|
||||||
|
</div>
|
||||||
|
<ms-base-table class="mt-[16px]" v-bind="propsRes" v-on="propsEvent">
|
||||||
|
<template #name="{ record }">
|
||||||
|
<span>{{ record.name }}</span>
|
||||||
|
<span v-if="record.adminFlag" class="ml-[4px] text-[var(--color-text-4)]">{{ `(${t('common.admin')})` }}</span>
|
||||||
|
</template>
|
||||||
|
<template #operation="{ record }">
|
||||||
|
<MsRemoveButton
|
||||||
|
:title="t('system.organization.removeName', { name: record.name })"
|
||||||
|
:sub-title-tip="t('system.organization.removeTip')"
|
||||||
|
@ok="handleRemove()"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</ms-base-table>
|
||||||
|
</div>
|
||||||
<MsDrawer
|
<MsDrawer
|
||||||
:width="680"
|
:width="680"
|
||||||
:visible="currentVisible"
|
:visible="relatedVisible"
|
||||||
unmount-on-close
|
unmount-on-close
|
||||||
:footer="false"
|
:footer="false"
|
||||||
:title="t('system.organization.addMember')"
|
|
||||||
:mask="false"
|
:mask="false"
|
||||||
@cancel="handleCancel"
|
@cancel="relatedVisible = false"
|
||||||
>
|
>
|
||||||
<div>
|
<template #title>
|
||||||
<div class="flex flex-row justify-between">
|
<div class="flex flex-row items-center gap-[4px]">
|
||||||
<a-dropdown trigger="hover">
|
<div>{{ t('bugManagement.detail.relatedCase') }}</div>
|
||||||
<template #content>
|
<a-select>
|
||||||
<a-doption @click="showRelatedDrawer('api')">{{ t('bugManagement.detail.apiCase') }}</a-doption>
|
<a-option>1</a-option>
|
||||||
<a-doption @click="showRelatedDrawer('scenario')">{{ t('bugManagement.detail.scenarioCase') }}</a-doption>
|
<a-option>2</a-option>
|
||||||
<a-doption @click="showRelatedDrawer('ui')">{{ t('bugManagement.detail.uiCase') }}</a-doption>
|
<a-option>3</a-option>
|
||||||
<a-doption @click="showRelatedDrawer('performance')">{{
|
</a-select>
|
||||||
t('bugManagement.detail.performanceCase')
|
|
||||||
}}</a-doption>
|
|
||||||
</template>
|
|
||||||
<a-button type="primary">{{ t('bugManagement.edit.linkCase') }}</a-button>
|
|
||||||
</a-dropdown>
|
|
||||||
<a-input-search
|
|
||||||
v-model:model-value="keyword"
|
|
||||||
allow-clear
|
|
||||||
:placeholder="t('bugManagement.detail.searchCase')"
|
|
||||||
class="w-[230px]"
|
|
||||||
@search="searchUser"
|
|
||||||
@press-enter="searchUser"
|
|
||||||
></a-input-search>
|
|
||||||
</div>
|
</div>
|
||||||
<ms-base-table class="mt-[16px]" v-bind="propsRes" v-on="propsEvent">
|
</template>
|
||||||
<template #name="{ record }">
|
|
||||||
<span>{{ record.name }}</span>
|
|
||||||
<span v-if="record.adminFlag" class="ml-[4px] text-[var(--color-text-4)]">{{
|
|
||||||
`(${t('common.admin')})`
|
|
||||||
}}</span>
|
|
||||||
</template>
|
|
||||||
<template #operation="{ record }">
|
|
||||||
<MsRemoveButton
|
|
||||||
:title="t('system.organization.removeName', { name: record.name })"
|
|
||||||
:sub-title-tip="t('system.organization.removeTip')"
|
|
||||||
@ok="handleRemove(record)"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</ms-base-table>
|
|
||||||
</div>
|
|
||||||
<MsDrawer
|
|
||||||
:width="680"
|
|
||||||
:visible="relatedVisible"
|
|
||||||
unmount-on-close
|
|
||||||
:footer="false"
|
|
||||||
:mask="false"
|
|
||||||
@cancel="relatedVisible = false"
|
|
||||||
>
|
|
||||||
<template #title>
|
|
||||||
<div class="flex flex-row items-center gap-[4px]">
|
|
||||||
<div>{{ t('bugManagement.detail.relatedCase') }}</div>
|
|
||||||
<a-select>
|
|
||||||
<a-option></a-option>
|
|
||||||
<a-option></a-option>
|
|
||||||
<a-option></a-option>
|
|
||||||
</a-select>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</MsDrawer>
|
|
||||||
</MsDrawer>
|
</MsDrawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, watch } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { Message, TableData } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
|
||||||
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||||
|
@ -78,20 +66,10 @@
|
||||||
import useTable from '@/components/pure/ms-table/useTable';
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
import MsRemoveButton from '@/components/business/ms-remove-button/MsRemoveButton.vue';
|
import MsRemoveButton from '@/components/business/ms-remove-button/MsRemoveButton.vue';
|
||||||
|
|
||||||
import { deleteProjectMemberByOrg, postProjectMemberByProjectId } from '@/api/modules/setting/organizationAndProject';
|
import { postProjectMemberByProjectId } from '@/api/modules/setting/organizationAndProject';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
export interface projectDrawerProps {
|
|
||||||
visible: boolean;
|
|
||||||
organizationId?: string;
|
|
||||||
projectId?: string;
|
|
||||||
}
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const props = defineProps<projectDrawerProps>();
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: 'cancel'): void;
|
|
||||||
(e: 'requestFetchData'): void;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const relatedVisible = ref(false);
|
const relatedVisible = ref(false);
|
||||||
const relatedType = ref('api');
|
const relatedType = ref('api');
|
||||||
|
@ -100,8 +78,6 @@
|
||||||
relatedType.value = type;
|
relatedType.value = type;
|
||||||
};
|
};
|
||||||
|
|
||||||
const currentVisible = ref(props.visible);
|
|
||||||
|
|
||||||
const keyword = ref('');
|
const keyword = ref('');
|
||||||
|
|
||||||
const projectColumn: MsTableColumn = [
|
const projectColumn: MsTableColumn = [
|
||||||
|
@ -125,7 +101,7 @@
|
||||||
{ title: 'system.organization.operation', slotName: 'operation' },
|
{ title: 'system.organization.operation', slotName: 'operation' },
|
||||||
];
|
];
|
||||||
|
|
||||||
const { propsRes, propsEvent, loadList, setLoadListParams, setKeyword } = useTable(postProjectMemberByProjectId, {
|
const { propsRes, propsEvent, loadList, setKeyword } = useTable(postProjectMemberByProjectId, {
|
||||||
heightUsed: 240,
|
heightUsed: 240,
|
||||||
columns: projectColumn,
|
columns: projectColumn,
|
||||||
scroll: { x: '100%' },
|
scroll: { x: '100%' },
|
||||||
|
@ -139,20 +115,12 @@
|
||||||
await loadList();
|
await loadList();
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleCancel = () => {
|
|
||||||
keyword.value = '';
|
|
||||||
emit('cancel');
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
await loadList();
|
await loadList();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRemove = async (record: TableData) => {
|
const handleRemove = async () => {
|
||||||
try {
|
try {
|
||||||
if (props.projectId) {
|
|
||||||
await deleteProjectMemberByOrg(props.projectId, record.id);
|
|
||||||
}
|
|
||||||
Message.success(t('common.removeSuccess'));
|
Message.success(t('common.removeSuccess'));
|
||||||
fetchData();
|
fetchData();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -160,22 +128,6 @@
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
watch(
|
|
||||||
() => props.projectId,
|
|
||||||
() => {
|
|
||||||
setLoadListParams({ projectId: props.projectId });
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
watch(
|
|
||||||
() => props.visible,
|
|
||||||
(visible) => {
|
|
||||||
currentVisible.value = visible;
|
|
||||||
if (visible) {
|
|
||||||
fetchData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<MsCard simple>
|
<MsCard simple>
|
||||||
<MsAdvanceFilter :filter-config-list="filterConfigList" :row-count="filterRowCount">
|
<MsAdvanceFilter :filter-config-list="filterConfigList" :row-count="filterRowCount" @keyword-search="fetchData">
|
||||||
<template #left>
|
<template #left>
|
||||||
<div class="flex gap-[12px]">
|
<div class="flex gap-[12px]">
|
||||||
<a-button type="primary" @click="handleCreate">{{ t('bugManagement.createBug') }} </a-button>
|
<a-button type="primary" @click="handleCreate">{{ t('bugManagement.createBug') }} </a-button>
|
||||||
|
@ -13,6 +13,14 @@
|
||||||
<template #name="{ record, rowIndex }">
|
<template #name="{ record, rowIndex }">
|
||||||
<a-button type="text" class="px-0" @click="handleShowDetail(record.id, rowIndex)">{{ record.name }}</a-button>
|
<a-button type="text" class="px-0" @click="handleShowDetail(record.id, rowIndex)">{{ record.name }}</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.status" />
|
||||||
|
</template>
|
||||||
<template #numberOfCase="{ record }">
|
<template #numberOfCase="{ record }">
|
||||||
<span class="cursor-pointer text-[rgb(var(--primary-5))]" @click="jumpToTestPlan(record)">{{
|
<span class="cursor-pointer text-[rgb(var(--primary-5))]" @click="jumpToTestPlan(record)">{{
|
||||||
record.memberCount
|
record.memberCount
|
||||||
|
@ -24,7 +32,7 @@
|
||||||
<a-divider direction="vertical" />
|
<a-divider direction="vertical" />
|
||||||
<MsButton class="!mr-0" @click="handleEdit(record)">{{ t('common.edit') }}</MsButton>
|
<MsButton class="!mr-0" @click="handleEdit(record)">{{ t('common.edit') }}</MsButton>
|
||||||
<a-divider direction="vertical" />
|
<a-divider direction="vertical" />
|
||||||
<MsButton class="!mr-0" status="danger" @click="handleDelete(record)">{{ t('common.delete') }}</MsButton>
|
<MsTableMoreAction :list="moreActionList" trigger="click" @select="handleMoreActionSelect($event, record)" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #empty> </template>
|
<template #empty> </template>
|
||||||
|
@ -92,6 +100,9 @@
|
||||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||||
import { MsTableColumn } from '@/components/pure/ms-table/type';
|
import { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||||
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 { 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 BugDetailDrawer from './components/bug-detail-drawer.vue';
|
||||||
|
|
||||||
import { getBugList, getExportConfig } from '@/api/modules/bug-management';
|
import { getBugList, getExportConfig } from '@/api/modules/bug-management';
|
||||||
|
@ -170,13 +181,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'bugManagement.severity',
|
title: 'bugManagement.severity',
|
||||||
slotName: 'memberCount',
|
slotName: 'severity',
|
||||||
|
width: 139,
|
||||||
showDrag: true,
|
showDrag: true,
|
||||||
dataIndex: 'severity',
|
dataIndex: 'severity',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'bugManagement.status',
|
title: 'bugManagement.status',
|
||||||
dataIndex: 'status',
|
dataIndex: 'status',
|
||||||
|
width: 139,
|
||||||
|
slotName: 'status',
|
||||||
showDrag: true,
|
showDrag: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -228,7 +242,7 @@
|
||||||
slotName: 'operation',
|
slotName: 'operation',
|
||||||
dataIndex: 'operation',
|
dataIndex: 'operation',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
width: 230,
|
width: 140,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
await tableStore.initColumn(TableKeyEnum.BUG_MANAGEMENT, columns, 'drawer');
|
await tableStore.initColumn(TableKeyEnum.BUG_MANAGEMENT, columns, 'drawer');
|
||||||
|
@ -243,11 +257,11 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const { propsRes, propsEvent, loadList, setKeyword, setLoadListParams, setProps } = useTable(
|
const { propsRes, propsEvent, setKeyword, setLoadListParams, setProps } = useTable(
|
||||||
getBugList,
|
getBugList,
|
||||||
{
|
{
|
||||||
tableKey: TableKeyEnum.BUG_MANAGEMENT,
|
tableKey: TableKeyEnum.BUG_MANAGEMENT,
|
||||||
selectable: false,
|
selectable: true,
|
||||||
noDisable: false,
|
noDisable: false,
|
||||||
showJumpMethod: true,
|
showJumpMethod: true,
|
||||||
showSetting: true,
|
showSetting: true,
|
||||||
|
@ -261,9 +275,61 @@
|
||||||
setProps({ heightUsed: heightUsed.value });
|
setProps({ heightUsed: heightUsed.value });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const data: BugListItem[] = [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
deleted: false,
|
||||||
|
num: '1',
|
||||||
|
name: 'Bug 1',
|
||||||
|
severity: 'High',
|
||||||
|
status: 'Open',
|
||||||
|
handleUser: 'John Doe',
|
||||||
|
relationCaseCount: 3,
|
||||||
|
platform: 'Windows',
|
||||||
|
tag: ['Critical'],
|
||||||
|
createUser: 'Alice',
|
||||||
|
updateUser: 'Bob',
|
||||||
|
createTime: '2023-12-07T10:00:00Z',
|
||||||
|
updateTime: '2023-12-07T11:30:00Z',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
deleted: false,
|
||||||
|
num: '2',
|
||||||
|
name: 'Bug 2',
|
||||||
|
severity: 'Medium',
|
||||||
|
status: 'In Progress',
|
||||||
|
handleUser: 'Jane Smith',
|
||||||
|
relationCaseCount: 1,
|
||||||
|
platform: 'Linux',
|
||||||
|
tag: ['Critical'],
|
||||||
|
createUser: 'Eve',
|
||||||
|
updateUser: 'Charlie',
|
||||||
|
createTime: '2023-12-06T09:15:00Z',
|
||||||
|
updateTime: '2023-12-06T15:45:00Z',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
deleted: false,
|
||||||
|
num: '3',
|
||||||
|
name: 'Bug 3',
|
||||||
|
severity: 'Low',
|
||||||
|
status: 'Resolved',
|
||||||
|
handleUser: 'Alex Johnson',
|
||||||
|
relationCaseCount: 2,
|
||||||
|
platform: 'Mac',
|
||||||
|
tag: ['Critical'],
|
||||||
|
createUser: 'David',
|
||||||
|
updateUser: 'Frank',
|
||||||
|
createTime: '2023-12-05T14:20:00Z',
|
||||||
|
updateTime: '2023-12-06T10:10:00Z',
|
||||||
|
},
|
||||||
|
// Add more data as needed
|
||||||
|
];
|
||||||
|
|
||||||
const fetchData = async (v = '') => {
|
const fetchData = async (v = '') => {
|
||||||
setKeyword(v);
|
setKeyword(v);
|
||||||
await loadList();
|
setProps({ data });
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCreate = () => {
|
const handleCreate = () => {
|
||||||
|
@ -315,9 +381,68 @@
|
||||||
exportOptionData.value = res;
|
exportOptionData.value = res;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const moreActionList: ActionsItem[] = [
|
||||||
|
{
|
||||||
|
label: t('common.delete'),
|
||||||
|
danger: true,
|
||||||
|
eventTag: 'delete',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
function handleMoreActionSelect(item: ActionsItem, record: BugListItem) {
|
||||||
|
if (item.eventTag === 'delete') {
|
||||||
|
handleDelete(record);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const severityOption = [
|
||||||
|
{
|
||||||
|
label: t('bugManagement.severityO.fatal'),
|
||||||
|
value: 'High',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('bugManagement.severityO.serious'),
|
||||||
|
value: 'Medium',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('bugManagement.severityO.general'),
|
||||||
|
value: 'Low',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('bugManagement.severityO.reminder'),
|
||||||
|
value: 'Info',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const statusOption = [
|
||||||
|
{
|
||||||
|
label: t('bugManagement.statusO.create'),
|
||||||
|
value: 'Create',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('bugManagement.statusO.processing'),
|
||||||
|
value: 'Processing',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('bugManagement.statusO.resolved'),
|
||||||
|
value: 'Resolved',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('bugManagement.statusO.closed'),
|
||||||
|
value: 'Closed',
|
||||||
|
},
|
||||||
|
{ label: t('bugManagement.statusO.refused'), value: 'Refused' },
|
||||||
|
];
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
setLoadListParams({ projectId: projectId.value });
|
setLoadListParams({ projectId: projectId.value });
|
||||||
fetchData();
|
fetchData();
|
||||||
setExportOptionData();
|
setExportOptionData();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
:deep(.arco-divider-vertical) {
|
||||||
|
margin: 0 8px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -49,5 +49,18 @@ export default {
|
||||||
performanceCase: '性能用例',
|
performanceCase: '性能用例',
|
||||||
searchCase: '通过名称搜索',
|
searchCase: '通过名称搜索',
|
||||||
},
|
},
|
||||||
|
severityO: {
|
||||||
|
fatal: '致命',
|
||||||
|
serious: '严重',
|
||||||
|
general: '一般',
|
||||||
|
reminder: '提醒',
|
||||||
|
},
|
||||||
|
statusO: {
|
||||||
|
create: '新建',
|
||||||
|
processing: '处理中',
|
||||||
|
resolved: '已解决',
|
||||||
|
closed: '已关闭',
|
||||||
|
refused: '已拒绝',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -359,6 +359,7 @@
|
||||||
{
|
{
|
||||||
title: 'caseManagement.featureCase.tableColumnModule',
|
title: 'caseManagement.featureCase.tableColumnModule',
|
||||||
slotName: 'moduleId',
|
slotName: 'moduleId',
|
||||||
|
dataIndex: 'moduleId',
|
||||||
showInTable: true,
|
showInTable: true,
|
||||||
width: 300,
|
width: 300,
|
||||||
showDrag: true,
|
showDrag: true,
|
||||||
|
|
Loading…
Reference in New Issue