feat(用例评审): 用例评审部分接口&个人信息头像
This commit is contained in:
parent
07095ecd5a
commit
2c166fa1d7
|
@ -170,7 +170,7 @@ const transform: AxiosTransform = {
|
||||||
throw new Error(e as unknown as string);
|
throw new Error(e as unknown as string);
|
||||||
}
|
}
|
||||||
checkStatus(error?.response?.status, msg, errorMessageMode);
|
checkStatus(error?.response?.status, msg, errorMessageMode);
|
||||||
return Promise.reject(error?.response?.data?.message);
|
return Promise.reject(error?.response?.data?.message || error);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
import { RouteRecordRaw, useRoute, useRouter } from 'vue-router';
|
import { RouteRecordRaw, useRoute, useRouter } from 'vue-router';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
|
||||||
|
import MsAvatar from '@/components/pure/ms-avatar/index.vue';
|
||||||
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||||
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||||
import MsPersonInfoDrawer from '@/components/business/ms-personal-drawer/index.vue';
|
import MsPersonInfoDrawer from '@/components/business/ms-personal-drawer/index.vue';
|
||||||
|
@ -288,8 +289,8 @@
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<a-menu-item class="flex items-center justify-between" key="personalInfo">
|
<a-menu-item class="flex items-center justify-between" key="personalInfo">
|
||||||
<div class="hover:!bg-transparent">
|
<div class="flex items-center gap-[8px] hover:!bg-transparent">
|
||||||
<MsIcon type="icon-icon_that_person" />
|
<MsAvatar avatar={userStore.avatar} size={20} />
|
||||||
{userStore.name}
|
{userStore.name}
|
||||||
</div>
|
</div>
|
||||||
<icon-caret-down class="!m-0" />
|
<icon-caret-down class="!m-0" />
|
||||||
|
|
|
@ -110,9 +110,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div v-show="activeAvatarType === 'word'" class="mb-[8px] flex flex-wrap gap-[24px] pt-[14px]">
|
<div v-show="activeAvatarType === 'word'" class="mb-[8px] flex flex-wrap gap-[24px] pt-[14px]">
|
||||||
<div class="avatar" @click="changeAvatar('word')">
|
<div class="avatar" @click="changeAvatar('word')">
|
||||||
<MsAvatar avatar="word" class="mb-[4px]">
|
<MsAvatar avatar="word" class="mb-[4px]" />
|
||||||
{{ userStore.name?.substring(0, 4) }}
|
|
||||||
</MsAvatar>
|
|
||||||
<div class="text-[12px] text-[var(--color-text-1)]">{{ t('ms.personal.wordAvatar') }}</div>
|
<div class="text-[12px] text-[var(--color-text-1)]">{{ t('ms.personal.wordAvatar') }}</div>
|
||||||
<MsIcon
|
<MsIcon
|
||||||
v-if="activeAvatar === 'word'"
|
v-if="activeAvatar === 'word'"
|
||||||
|
@ -157,6 +155,8 @@
|
||||||
});
|
});
|
||||||
const baseInfoFormRef = ref<FormInstance>();
|
const baseInfoFormRef = ref<FormInstance>();
|
||||||
const orgList = ref<OrganizationProjectListItem[]>([]);
|
const orgList = ref<OrganizationProjectListItem[]>([]);
|
||||||
|
const activeAvatarType = ref<'builtIn' | 'word'>('builtIn');
|
||||||
|
const activeAvatar = ref('default');
|
||||||
|
|
||||||
function initBaseInfo() {
|
function initBaseInfo() {
|
||||||
descriptions.value = [
|
descriptions.value = [
|
||||||
|
@ -186,6 +186,8 @@
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const res = await getBaseInfo(userStore.id || '');
|
const res = await getBaseInfo(userStore.id || '');
|
||||||
orgList.value = res.orgProjectList;
|
orgList.value = res.orgProjectList;
|
||||||
|
activeAvatar.value = res.avatar;
|
||||||
|
activeAvatarType.value = res.avatar === 'word' ? 'word' : 'builtIn';
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
@ -251,8 +253,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const avatarModalVisible = ref(false);
|
const avatarModalVisible = ref(false);
|
||||||
const activeAvatarType = ref<'builtIn' | 'word'>('builtIn');
|
|
||||||
const activeAvatar = ref('default');
|
|
||||||
const avatarList = ref<string[]>([]);
|
const avatarList = ref<string[]>([]);
|
||||||
let i = 1;
|
let i = 1;
|
||||||
while (i <= 46) {
|
while (i <= 46) {
|
||||||
|
|
|
@ -1,17 +1,37 @@
|
||||||
<template>
|
<template>
|
||||||
<MsIcon v-if="props.avatar === 'default'" type="icon-icon_that_person" size="40" class="text-[var(--color-text-4)]" />
|
<MsIcon
|
||||||
<a-avatar v-else-if="props.avatar === 'word'" class="bg-[rgb(var(--primary-1))] text-[rgb(var(--primary-6))]">
|
v-if="props.avatar === 'default'"
|
||||||
<slot></slot>
|
type="icon-icon_that_person"
|
||||||
|
:size="props.size"
|
||||||
|
class="text-[var(--color-text-4)]"
|
||||||
|
/>
|
||||||
|
<a-avatar
|
||||||
|
v-else-if="props.avatar === 'word'"
|
||||||
|
:size="props.size"
|
||||||
|
class="bg-[rgb(var(--primary-1))] text-[rgb(var(--primary-6))]"
|
||||||
|
>
|
||||||
|
<slot>{{ userStore.name?.substring(0, 4) }}</slot>
|
||||||
</a-avatar>
|
</a-avatar>
|
||||||
<a-avatar v-else :image-url="avatar"></a-avatar>
|
<a-avatar v-else :image-url="avatar" :size="props.size"></a-avatar>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
import useUserStore from '@/store/modules/user/index';
|
||||||
avatar: 'default' | 'word' | string;
|
|
||||||
}>();
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
avatar?: 'default' | 'word' | string;
|
||||||
|
size?: number;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
avatar: 'default',
|
||||||
|
size: 40,
|
||||||
|
}
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped></style>
|
<style lang="less" scoped></style>
|
||||||
|
|
|
@ -158,9 +158,6 @@
|
||||||
:deep(.arco-split-trigger-icon) {
|
:deep(.arco-split-trigger-icon) {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
.ms-split-box--top {
|
|
||||||
height: calc(v-bind(innerSize) - 4px);
|
|
||||||
}
|
|
||||||
.ms-split-box--bottom {
|
.ms-split-box--bottom {
|
||||||
@apply h-full;
|
@apply h-full;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
</template>
|
</template>
|
||||||
<div class="h-full px-[24px]">
|
<div class="h-full px-[24px]">
|
||||||
<a-divider class="my-0" />
|
<a-divider class="my-0" />
|
||||||
<div class="flex h-[calc(100%-1px)]">
|
<div class="flex h-[calc(100%-1px)] w-full">
|
||||||
<div class="h-full w-[356px] border-r border-[var(--color-text-n8)] pr-[16px] pt-[16px]">
|
<div class="h-full w-[356px] border-r border-[var(--color-text-n8)] pr-[16px] pt-[16px]">
|
||||||
<div class="mb-[16px] flex">
|
<div class="mb-[16px] flex">
|
||||||
<a-input
|
<a-input
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
</div>
|
</div>
|
||||||
<MsPagination :total="total" :page-size="pageSize" :current="pageCurrent" size="mini" simple />
|
<MsPagination :total="total" :page-size="pageSize" :current="pageCurrent" size="mini" simple />
|
||||||
</div>
|
</div>
|
||||||
<div class="relative flex flex-1 flex-col">
|
<div class="relative flex w-[calc(100%-356px)] flex-col">
|
||||||
<div class="pl-[16px] pt-[16px]">
|
<div class="pl-[16px] pt-[16px]">
|
||||||
<div class="rounded-[var(--border-radius-small)] bg-[var(--color-text-n9)] p-[16px]">
|
<div class="rounded-[var(--border-radius-small)] bg-[var(--color-text-n9)] p-[16px]">
|
||||||
<div class="mb-[12px] flex items-center justify-between">
|
<div class="mb-[12px] flex items-center justify-between">
|
||||||
|
@ -104,16 +104,31 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a-tabs v-model:active-key="showTab" class="no-content">
|
<a-tabs v-model:active-key="showTab" class="no-content">
|
||||||
<a-tab-pane v-for="item of tabList" :key="item.key" :title="item.title" />
|
<a-tab-pane :key="tabList[0].key" :title="tabList[0].title" />
|
||||||
|
<a-tab-pane :key="tabList[1].key" :title="tabList[1].title" />
|
||||||
|
<a-tab-pane :key="tabList[2].key">
|
||||||
|
<template #title>
|
||||||
|
<div class="flex items-center">
|
||||||
|
{{ tabList[2].title }}
|
||||||
|
<div
|
||||||
|
:class="`ml-[4px] rounded-full ${
|
||||||
|
showTab === tabList[2].key ? 'bg-[rgb(var(--primary-5))]' : 'bg-[var(--color-text-brand)]'
|
||||||
|
} px-[4px] text-[12px] text-white`"
|
||||||
|
>
|
||||||
|
{{ caseDetail.demandCount > 99 ? '99+' : caseDetail.demandCount }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-tab-pane>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
</div>
|
</div>
|
||||||
<a-divider class="my-0" />
|
<a-divider class="my-0" />
|
||||||
<div class="content-center">
|
<div class="content-center">
|
||||||
<MsDescription v-if="showTab === 'baseInfo'" :descriptions="descriptions" label-width="90px" />
|
<MsDescription v-if="showTab === 'baseInfo'" :descriptions="descriptions" label-width="90px" />
|
||||||
<div v-if="showTab === 'detail'" class="h-full">
|
<div v-else-if="showTab === 'detail'" class="h-full">
|
||||||
<MsSplitBox :size="0.8" direction="vertical" min="0" :max="0.99">
|
<MsSplitBox :size="0.8" direction="vertical" min="0" :max="0.99">
|
||||||
<template #top>
|
<template #top>
|
||||||
<div> toptop </div>
|
<caseTabDetail :form="{}" :allow-edit="false" />
|
||||||
</template>
|
</template>
|
||||||
<template #bottom>
|
<template #bottom>
|
||||||
<div class="flex h-full flex-col overflow-hidden">
|
<div class="flex h-full flex-col overflow-hidden">
|
||||||
|
@ -153,6 +168,20 @@
|
||||||
</template>
|
</template>
|
||||||
</MsSplitBox>
|
</MsSplitBox>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
{{ t('caseManagement.caseReview.demandCases') }}
|
||||||
|
<a-input-search
|
||||||
|
v-model="demandKeyword"
|
||||||
|
:placeholder="t('caseManagement.caseReview.demandSearchPlaceholder')"
|
||||||
|
allow-clear
|
||||||
|
class="w-[300px]"
|
||||||
|
@press-enter="searchDemand"
|
||||||
|
@search="searchDemand"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<caseTabDemand ref="caseDemandRef" :fun-params="{ caseId: route.query.id, keyword: demandKeyword }" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content-footer">
|
<div class="content-footer">
|
||||||
<div class="mb-[16px] flex items-center">
|
<div class="mb-[16px] flex items-center">
|
||||||
|
@ -232,6 +261,7 @@
|
||||||
/**
|
/**
|
||||||
* @description 功能测试-用例评审-用例详情
|
* @description 功能测试-用例评审-用例详情
|
||||||
*/
|
*/
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
import { FormInstance } from '@arco-design/web-vue';
|
import { FormInstance } from '@arco-design/web-vue';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
@ -242,13 +272,18 @@
|
||||||
import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
|
import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
|
||||||
import caseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
|
import caseLevel from '@/components/business/ms-case-associate/caseLevel.vue';
|
||||||
import type { CaseLevel } from '@/components/business/ms-case-associate/types';
|
import type { CaseLevel } from '@/components/business/ms-case-associate/types';
|
||||||
|
import caseTabDemand from '../caseManagementFeature/components/tabContent/tabDemand/associatedDemandTable.vue';
|
||||||
|
import caseTabDetail from '../caseManagementFeature/components/tabContent/tabDetail.vue';
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const reviewName = ref('打算肯定还是觉得还是觉得还是计划的');
|
const reviewName = ref('打算肯定还是觉得还是觉得还是计划的');
|
||||||
const caseDetail = ref({});
|
const caseDetail = ref({
|
||||||
|
demandCount: 999,
|
||||||
|
});
|
||||||
const onlyMine = ref(false);
|
const onlyMine = ref(false);
|
||||||
const keyword = ref('');
|
const keyword = ref('');
|
||||||
|
|
||||||
|
@ -415,6 +450,12 @@
|
||||||
reason: '',
|
reason: '',
|
||||||
});
|
});
|
||||||
const dialogFormRef = ref<FormInstance>();
|
const dialogFormRef = ref<FormInstance>();
|
||||||
|
const demandKeyword = ref('');
|
||||||
|
const caseDemandRef = ref<InstanceType<typeof caseTabDemand>>();
|
||||||
|
|
||||||
|
function searchDemand() {
|
||||||
|
caseDemandRef.value?.initData();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
|
@ -86,8 +86,8 @@
|
||||||
<template v-if="keyword.trim() === ''" #empty>
|
<template v-if="keyword.trim() === ''" #empty>
|
||||||
<div class="flex items-center justify-center p-[8px] text-[var(--color-text-4)]">
|
<div class="flex items-center justify-center p-[8px] text-[var(--color-text-4)]">
|
||||||
{{ t('caseManagement.caseReview.tableNoData') }}
|
{{ t('caseManagement.caseReview.tableNoData') }}
|
||||||
<MsButton class="ml-[8px]" @click="handleAddClick">
|
<MsButton class="ml-[8px]" @click="createCase">
|
||||||
{{ t('caseManagement.caseReview.create') }}
|
{{ t('caseManagement.caseReview.crateCase') }}
|
||||||
</MsButton>
|
</MsButton>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -586,10 +586,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleAddClick() {
|
|
||||||
console.log('handleAddClick');
|
|
||||||
}
|
|
||||||
|
|
||||||
function openDetail(id: string) {
|
function openDetail(id: string) {
|
||||||
router.push({
|
router.push({
|
||||||
name: CaseManagementRouteEnum.CASE_MANAGEMENT_REVIEW_DETAIL_CASE_DETAIL,
|
name: CaseManagementRouteEnum.CASE_MANAGEMENT_REVIEW_DETAIL_CASE_DETAIL,
|
||||||
|
@ -606,7 +602,7 @@
|
||||||
|
|
||||||
function createCase() {
|
function createCase() {
|
||||||
router.push({
|
router.push({
|
||||||
name: CaseManagementRouteEnum.CASE_MANAGEMENT_REVIEW_CREATE,
|
name: CaseManagementRouteEnum.CASE_MANAGEMENT_CASE_DETAIL,
|
||||||
query: {
|
query: {
|
||||||
reviewId: route.query.id,
|
reviewId: route.query.id,
|
||||||
},
|
},
|
||||||
|
|
|
@ -129,4 +129,5 @@ export default {
|
||||||
'caseManagement.caseReview.submitReview': 'Submit review',
|
'caseManagement.caseReview.submitReview': 'Submit review',
|
||||||
'caseManagement.caseReview.reviewHistory': 'Review history',
|
'caseManagement.caseReview.reviewHistory': 'Review history',
|
||||||
'caseManagement.caseReview.noMatchReviewer': 'No matching handler, can be set in {menu}',
|
'caseManagement.caseReview.noMatchReviewer': 'No matching handler, can be set in {menu}',
|
||||||
|
'caseManagement.caseReview.crateCase': 'Create case',
|
||||||
};
|
};
|
||||||
|
|
|
@ -119,4 +119,7 @@ export default {
|
||||||
'caseManagement.caseReview.submitReview': '提交评审',
|
'caseManagement.caseReview.submitReview': '提交评审',
|
||||||
'caseManagement.caseReview.reviewHistory': '评审历史',
|
'caseManagement.caseReview.reviewHistory': '评审历史',
|
||||||
'caseManagement.caseReview.noMatchReviewer': '无匹配处理人,可在 ',
|
'caseManagement.caseReview.noMatchReviewer': '无匹配处理人,可在 ',
|
||||||
|
'caseManagement.caseReview.crateCase': '创建用例',
|
||||||
|
'caseManagement.caseReview.demandCases': '需求关联列表',
|
||||||
|
'caseManagement.caseReview.demandSearchPlaceholder': '通过名称搜索',
|
||||||
};
|
};
|
||||||
|
|
|
@ -239,6 +239,19 @@
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化模块文件数量
|
||||||
|
*/
|
||||||
|
watch(
|
||||||
|
() => props.modulesCount,
|
||||||
|
(obj) => {
|
||||||
|
storageList.value = originStorageList.value.map((e) => ({
|
||||||
|
...e,
|
||||||
|
count: obj?.[e.id] || 0,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const focusItemKey = ref('');
|
const focusItemKey = ref('');
|
||||||
|
|
||||||
function setActiveFolder(id: string) {
|
function setActiveFolder(id: string) {
|
||||||
|
|
|
@ -229,7 +229,13 @@
|
||||||
* 右侧表格数据刷新后,若当前展示的是模块,则刷新模块树的统计数量
|
* 右侧表格数据刷新后,若当前展示的是模块,则刷新模块树的统计数量
|
||||||
*/
|
*/
|
||||||
function handleModuleTableInit(params: FileListQueryParams) {
|
function handleModuleTableInit(params: FileListQueryParams) {
|
||||||
initModulesCount(params);
|
initModulesCount({
|
||||||
|
...params,
|
||||||
|
combine: {
|
||||||
|
...params.combine,
|
||||||
|
storage: showType.value === 'Module' ? 'minio' : 'git', // 这里因为存在切换我的、全部文件夹时,激活的是存储库列表,所以还要区分一下当前展示的类型是啥
|
||||||
|
},
|
||||||
|
});
|
||||||
tableFilterParams.value = { ...params };
|
tableFilterParams.value = { ...params };
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in New Issue