feat(工作台): 工作台首页联调卡片&柱状图饼图样式调整
This commit is contained in:
parent
622cc8c814
commit
9bd017a800
|
@ -17,7 +17,9 @@ import type {
|
||||||
import {
|
import {
|
||||||
EditDashboardLayoutUrl,
|
EditDashboardLayoutUrl,
|
||||||
GetDashboardLayoutUrl,
|
GetDashboardLayoutUrl,
|
||||||
|
WorkApiCaseCountDetailUrl,
|
||||||
WorkApiChangeListUrl,
|
WorkApiChangeListUrl,
|
||||||
|
WorkApiCountDetailUrl,
|
||||||
WorkAssociateCaseDetailUrl,
|
WorkAssociateCaseDetailUrl,
|
||||||
WorkbenchApiCaseListUrl,
|
WorkbenchApiCaseListUrl,
|
||||||
WorkbenchBugListUrl,
|
WorkbenchBugListUrl,
|
||||||
|
@ -26,13 +28,18 @@ import {
|
||||||
WorkbenchScenarioListUrl,
|
WorkbenchScenarioListUrl,
|
||||||
WorkbenchTestPlanListUrl,
|
WorkbenchTestPlanListUrl,
|
||||||
WorkbenchTestPlanStatisticUrl,
|
WorkbenchTestPlanStatisticUrl,
|
||||||
|
WorkBugByMeCreatedUrl,
|
||||||
|
WorkBugCountDetailUrl,
|
||||||
|
WorkBugHandleByMeUrl,
|
||||||
WorkBugHandlerDetailUrl,
|
WorkBugHandlerDetailUrl,
|
||||||
WorkCaseCountDetailUrl,
|
WorkCaseCountDetailUrl,
|
||||||
WorkCaseReviewDetailUrl,
|
WorkCaseReviewDetailUrl,
|
||||||
|
WorkHandleUserOptionsUrl,
|
||||||
WorkMemberViewDetailUrl,
|
WorkMemberViewDetailUrl,
|
||||||
WorkMyCreatedDetailUrl,
|
WorkMyCreatedDetailUrl,
|
||||||
WorkProOverviewDetailUrl,
|
WorkProOverviewDetailUrl,
|
||||||
WorkReviewListUrl,
|
WorkReviewListUrl,
|
||||||
|
WorkScenarioCaseCountDetailUrl,
|
||||||
WorkTodoBugListUrl,
|
WorkTodoBugListUrl,
|
||||||
WorkTodoPlanListUrl,
|
WorkTodoPlanListUrl,
|
||||||
WorkTodoReviewListUrl,
|
WorkTodoReviewListUrl,
|
||||||
|
@ -75,15 +82,15 @@ export function workbenchApiCaseList(data: TableQueryParams) {
|
||||||
|
|
||||||
// 工作台首页概览
|
// 工作台首页概览
|
||||||
export function workProOverviewDetail(data: WorkHomePageDetail) {
|
export function workProOverviewDetail(data: WorkHomePageDetail) {
|
||||||
return MSR.post<OverViewOfProject>({ url: WorkProOverviewDetailUrl, data });
|
return MSR.post<OverViewOfProject>({ url: WorkProOverviewDetailUrl, data }, { ignoreCancelToken: true });
|
||||||
}
|
}
|
||||||
// 我创建的
|
// 我创建的
|
||||||
export function workMyCreatedDetail(data: WorkHomePageDetail) {
|
export function workMyCreatedDetail(data: WorkHomePageDetail) {
|
||||||
return MSR.post<OverViewOfProject>({ url: WorkMyCreatedDetailUrl, data });
|
return MSR.post<OverViewOfProject>({ url: WorkMyCreatedDetailUrl, data }, { ignoreCancelToken: true });
|
||||||
}
|
}
|
||||||
// 人员概览
|
// 人员概览
|
||||||
export function workMemberViewDetail(data: WorkHomePageDetail) {
|
export function workMemberViewDetail(data: WorkHomePageDetail) {
|
||||||
return MSR.post<OverViewOfProject>({ url: WorkMemberViewDetailUrl, data });
|
return MSR.post<OverViewOfProject>({ url: WorkMemberViewDetailUrl, data }, { ignoreCancelToken: true });
|
||||||
}
|
}
|
||||||
// 获取用户布局
|
// 获取用户布局
|
||||||
export function getDashboardLayout(orgId: string) {
|
export function getDashboardLayout(orgId: string) {
|
||||||
|
@ -97,21 +104,21 @@ export function editDashboardLayout(data: SelectedCardItem[], orgId: string) {
|
||||||
|
|
||||||
// 工作台-首页-用例数
|
// 工作台-首页-用例数
|
||||||
export function workCaseCountDetail(data: WorkHomePageDetail) {
|
export function workCaseCountDetail(data: WorkHomePageDetail) {
|
||||||
return MSR.post<PassRateDataType>({ url: WorkCaseCountDetailUrl, data });
|
return MSR.post<PassRateDataType>({ url: WorkCaseCountDetailUrl, data }, { ignoreCancelToken: true });
|
||||||
}
|
}
|
||||||
// 工作台-首页-关联用例数
|
// 工作台-首页-关联用例数
|
||||||
export function workAssociateCaseDetail(data: WorkHomePageDetail) {
|
export function workAssociateCaseDetail(data: WorkHomePageDetail) {
|
||||||
return MSR.post<PassRateDataType>({ url: WorkAssociateCaseDetailUrl, data });
|
return MSR.post<PassRateDataType>({ url: WorkAssociateCaseDetailUrl, data }, { ignoreCancelToken: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
// 工作台-首页-用例评审数
|
// 工作台-首页-用例评审数
|
||||||
export function workCaseReviewDetail(data: WorkHomePageDetail) {
|
export function workCaseReviewDetail(data: WorkHomePageDetail) {
|
||||||
return MSR.post<PassRateDataType>({ url: WorkCaseReviewDetailUrl, data });
|
return MSR.post<PassRateDataType>({ url: WorkCaseReviewDetailUrl, data }, { ignoreCancelToken: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
// 工作台-首页-缺陷处理人
|
// 工作台-首页-缺陷处理人
|
||||||
export function workBugHandlerDetail(data: WorkHomePageDetail) {
|
export function workBugHandlerDetail(data: WorkHomePageDetail) {
|
||||||
return MSR.post<OverViewOfProject>({ url: WorkBugHandlerDetailUrl, data });
|
return MSR.post<OverViewOfProject>({ url: WorkBugHandlerDetailUrl, data }, { ignoreCancelToken: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
// 工作台-首页-接口变更
|
// 工作台-首页-接口变更
|
||||||
|
@ -130,6 +137,41 @@ export function workReviewList(data: WorkHomePageDetail) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 工作台-首页-缺陷数量
|
||||||
|
export function workBugCountDetail(data: WorkHomePageDetail) {
|
||||||
|
return MSR.post<PassRateDataType>({ url: WorkBugCountDetailUrl, data }, { ignoreCancelToken: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 工作台-首页-我创建的缺陷
|
||||||
|
export function workBugByMeCreated(data: WorkHomePageDetail) {
|
||||||
|
return MSR.post<PassRateDataType>({ url: WorkBugByMeCreatedUrl, data }, { ignoreCancelToken: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 工作台-首页-待我处理的缺陷
|
||||||
|
export function workBugHandleByMe(data: WorkHomePageDetail) {
|
||||||
|
return MSR.post<PassRateDataType>({ url: WorkBugHandleByMeUrl, data }, { ignoreCancelToken: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 工作台-首页-接口数量
|
||||||
|
export function workApiCountDetail(data: WorkHomePageDetail) {
|
||||||
|
return MSR.post<PassRateDataType>({ url: WorkApiCountDetailUrl, data }, { ignoreCancelToken: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 工作台-首页-接口用例数量
|
||||||
|
export function workApiCaseCountDetail(data: WorkHomePageDetail) {
|
||||||
|
return MSR.post<PassRateDataType>({ url: WorkApiCaseCountDetailUrl, data }, { ignoreCancelToken: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 工作台-首页-场景用例数量
|
||||||
|
export function workScenarioCaseCountDetail(data: WorkHomePageDetail) {
|
||||||
|
return MSR.post<PassRateDataType>({ url: WorkScenarioCaseCountDetailUrl, data }, { ignoreCancelToken: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 工作台-首页-缺陷处理人列表
|
||||||
|
export function workHandleUserOptions(projectId: string) {
|
||||||
|
return MSR.get({ url: WorkHandleUserOptionsUrl, params: projectId }, { ignoreCancelToken: true });
|
||||||
|
}
|
||||||
|
|
||||||
// 待办-用例评审列表
|
// 待办-用例评审列表
|
||||||
export function workbenchTodoReviewList(data: TableQueryParams) {
|
export function workbenchTodoReviewList(data: TableQueryParams) {
|
||||||
return MSR.post<CommonList<ReviewItem>>({ url: WorkTodoReviewListUrl, data });
|
return MSR.post<CommonList<ReviewItem>>({ url: WorkTodoReviewListUrl, data });
|
||||||
|
|
|
@ -19,3 +19,10 @@ export const WorkBugHandlerDetailUrl = '/dashboard/bug_handle_user'; // 工作
|
||||||
export const WorkApiChangeListUrl = '/dashboard/api_change'; // 工作台-首页-接口变更
|
export const WorkApiChangeListUrl = '/dashboard/api_change'; // 工作台-首页-接口变更
|
||||||
export const WorkCaseReviewDetailUrl = '/dashboard/review_case_count'; // 工作台-首页-用例评审数
|
export const WorkCaseReviewDetailUrl = '/dashboard/review_case_count'; // 工作台-首页-用例评审数
|
||||||
export const WorkReviewListUrl = '/dashboard/reviewing_by_me'; // 工作台-首页-待我评审
|
export const WorkReviewListUrl = '/dashboard/reviewing_by_me'; // 工作台-首页-待我评审
|
||||||
|
export const WorkApiCountDetailUrl = '/dashboard/api_count'; // 工作台-首页-接口数量
|
||||||
|
export const WorkApiCaseCountDetailUrl = '/dashboard/api_case_count'; // 工作台-首页-接口用例数量
|
||||||
|
export const WorkScenarioCaseCountDetailUrl = '/dashboard/scenario_count'; // 工作台-首页-场景用例数量
|
||||||
|
export const WorkHandleUserOptionsUrl = '/dashboard/bug_handle_user/list'; // 工作台-首页-缺陷处理人列表
|
||||||
|
export const WorkBugCountDetailUrl = '/dashboard/bug_count'; // 工作台-首页-缺陷数量
|
||||||
|
export const WorkBugByMeCreatedUrl = '/dashboard/create_bug_by_me'; // 工作台-首页-我创建的缺陷
|
||||||
|
export const WorkBugHandleByMeUrl = '/dashboard/handle_bug_by_me'; // 工作台-首页-待我处理的缺陷
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { nextTick, ref } from 'vue';
|
import { nextTick, ref } from 'vue';
|
||||||
|
|
||||||
import { BarChart, LineChart, PieChart, RadarChart } from 'echarts/charts';
|
import { BarChart, CustomChart, LineChart, PieChart, RadarChart } from 'echarts/charts';
|
||||||
import {
|
import {
|
||||||
DataZoomComponent,
|
DataZoomComponent,
|
||||||
GraphicComponent,
|
GraphicComponent,
|
||||||
|
@ -21,6 +21,7 @@
|
||||||
use([
|
use([
|
||||||
CanvasRenderer,
|
CanvasRenderer,
|
||||||
BarChart,
|
BarChart,
|
||||||
|
CustomChart,
|
||||||
LineChart,
|
LineChart,
|
||||||
PieChart,
|
PieChart,
|
||||||
RadarChart,
|
RadarChart,
|
||||||
|
|
|
@ -31,7 +31,7 @@ export interface SelectedCardItem {
|
||||||
|
|
||||||
// 查询入参
|
// 查询入参
|
||||||
export interface WorkHomePageDetail extends TableQueryParams {
|
export interface WorkHomePageDetail extends TableQueryParams {
|
||||||
dayNumber: number | null;
|
dayNumber: number | string;
|
||||||
startTime: number | null;
|
startTime: number | null;
|
||||||
endTime: number | null;
|
endTime: number | null;
|
||||||
projectIds: string[];
|
projectIds: string[];
|
||||||
|
@ -40,9 +40,9 @@ export interface WorkHomePageDetail extends TableQueryParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TimeFormParams {
|
export interface TimeFormParams {
|
||||||
dayNumber: number | null;
|
dayNumber: number | string;
|
||||||
startTime: number | null;
|
startTime: number;
|
||||||
endTime: number | null;
|
endTime: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OverViewOfProject {
|
export interface OverViewOfProject {
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
:search-keys="['name']"
|
:search-keys="['name']"
|
||||||
class="!w-[240px]"
|
class="!w-[240px]"
|
||||||
:prefix="t('workbench.homePage.project')"
|
:prefix="t('workbench.homePage.project')"
|
||||||
|
@change="changeProject"
|
||||||
>
|
>
|
||||||
</MsSelect>
|
</MsSelect>
|
||||||
</div>
|
</div>
|
||||||
|
@ -23,25 +24,25 @@
|
||||||
<div class="case-count-item">
|
<div class="case-count-item">
|
||||||
<div v-for="(ele, index) of executionTimeValue" :key="index" class="case-count-item-content">
|
<div v-for="(ele, index) of executionTimeValue" :key="index" class="case-count-item-content">
|
||||||
<div class="case-count-item-title">{{ ele.name }}</div>
|
<div class="case-count-item-title">{{ ele.name }}</div>
|
||||||
<div class="case-count-item-number">{{ addCommasToNumber(ele.count) }}</div>
|
<div class="case-count-item-number">{{ hasPermission ? addCommasToNumber(ele.count as number) : '-' }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="case-count-item">
|
<div class="case-count-item">
|
||||||
<div v-for="(ele, index) of apiCountValue" :key="index" class="case-count-item-content">
|
<div v-for="(ele, index) of apiCountValue" :key="index" class="case-count-item-content">
|
||||||
<div class="case-count-item-title">{{ ele.name }}</div>
|
<div class="case-count-item-title">{{ ele.name }}</div>
|
||||||
<div class="case-count-item-number">{{ addCommasToNumber(ele.count) }}</div>
|
<div class="case-count-item-number">{{ hasPermission ? addCommasToNumber(ele.count as number) : '-' }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="case-ratio-wrapper mt-[16px]">
|
<div class="case-ratio-wrapper mt-[16px]">
|
||||||
<div class="case-ratio-item">
|
<div class="case-ratio-item">
|
||||||
<RatioPie :data="coverData" :rate-config="coverTitleConfig" />
|
<RatioPie :has-permission="hasPermission" :data="coverData" :rate-config="coverTitleConfig" />
|
||||||
</div>
|
</div>
|
||||||
<div class="case-ratio-item">
|
<div class="case-ratio-item">
|
||||||
<RatioPie :data="caseExecuteData" :rate-config="executeTitleConfig" />
|
<RatioPie :has-permission="hasPermission" :data="caseExecuteData" :rate-config="executeTitleConfig" />
|
||||||
</div>
|
</div>
|
||||||
<div class="case-ratio-item">
|
<div class="case-ratio-item">
|
||||||
<RatioPie :data="casePassData" :rate-config="casePassTitleConfig" />
|
<RatioPie :has-permission="hasPermission" :data="casePassData" :rate-config="casePassTitleConfig" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -57,6 +58,7 @@
|
||||||
import MsSelect from '@/components/business/ms-select';
|
import MsSelect from '@/components/business/ms-select';
|
||||||
import RatioPie from './ratioPie.vue';
|
import RatioPie from './ratioPie.vue';
|
||||||
|
|
||||||
|
import { workApiCaseCountDetail, workScenarioCaseCountDetail } from '@/api/modules/workbench';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
import { addCommasToNumber } from '@/utils';
|
import { addCommasToNumber } from '@/utils';
|
||||||
|
@ -72,30 +74,34 @@
|
||||||
item: SelectedCardItem;
|
item: SelectedCardItem;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'change'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
const innerProjectIds = defineModel<string[]>('projectIds', {
|
const innerProjectIds = defineModel<string[]>('projectIds', {
|
||||||
required: true,
|
required: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const projectId = ref<string>(innerProjectIds.value[0]);
|
const projectId = ref<string>(innerProjectIds.value[0]);
|
||||||
|
|
||||||
const executionTimeValue = ref<{ name: string; count: number }[]>([
|
const executionTimeValue = ref<{ name: string; count: number | string }[]>([
|
||||||
{
|
{
|
||||||
name: '执行次数',
|
name: '执行次数',
|
||||||
count: 100,
|
count: '-',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const apiCountValue = ref<{ name: string; count: number }[]>([
|
const apiCountValue = ref<{ name: string; count: number | string }[]>([
|
||||||
{
|
{
|
||||||
name:
|
name:
|
||||||
props.item.key === WorkCardEnum.API_CASE_COUNT
|
props.item.key === WorkCardEnum.API_CASE_COUNT
|
||||||
? t('workbench.homePage.apiUseCasesNumber')
|
? t('workbench.homePage.apiUseCasesNumber')
|
||||||
: t('workbench.homePage.scenarioUseCasesNumber'),
|
: t('workbench.homePage.scenarioUseCasesNumber'),
|
||||||
count: 100,
|
count: '-',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: t('workbench.homePage.misstatementCount'),
|
name: t('workbench.homePage.misstatementCount'),
|
||||||
count: 100,
|
count: '-',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -129,6 +135,7 @@
|
||||||
name: t('common.executed'),
|
name: t('common.executed'),
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const casePassData = ref<{ name: string; value: number }[]>([
|
const casePassData = ref<{ name: string; value: number }[]>([
|
||||||
{
|
{
|
||||||
value: 0,
|
value: 0,
|
||||||
|
@ -143,8 +150,11 @@
|
||||||
const coverTitleConfig = computed(() => {
|
const coverTitleConfig = computed(() => {
|
||||||
return {
|
return {
|
||||||
name: t('workbench.homePage.apiCoverage'),
|
name: t('workbench.homePage.apiCoverage'),
|
||||||
count: '80%',
|
|
||||||
color: ['#EDEDF1', '#00C261'],
|
color: ['#EDEDF1', '#00C261'],
|
||||||
|
tooltipText:
|
||||||
|
props.item.key === WorkCardEnum.API_CASE_COUNT
|
||||||
|
? t('workbench.homePage.apiCaseCountCoverRateTooltip')
|
||||||
|
: t('workbench.homePage.scenarioCaseCountCoverRateTooltip'),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -152,13 +162,13 @@
|
||||||
return props.item.key === WorkCardEnum.API_CASE_COUNT
|
return props.item.key === WorkCardEnum.API_CASE_COUNT
|
||||||
? {
|
? {
|
||||||
name: t('workbench.homePage.caseExecutionRate'),
|
name: t('workbench.homePage.caseExecutionRate'),
|
||||||
count: '80%',
|
color: ['#00C261', '#EDEDF1'],
|
||||||
color: ['#EDEDF1', '#00C261'],
|
tooltipText: t('workbench.homePage.apiCaseCountExecuteRateTooltip'),
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
name: t('workbench.homePage.sceneExecutionRate'),
|
name: t('workbench.homePage.sceneExecutionRate'),
|
||||||
count: '80%',
|
|
||||||
color: ['#EDEDF1', '#00C261'],
|
color: ['#EDEDF1', '#00C261'],
|
||||||
|
tooltipText: t('workbench.homePage.scenarioCaseCountExecuteRateTooltip'),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -166,17 +176,77 @@
|
||||||
return props.item.key === WorkCardEnum.API_CASE_COUNT
|
return props.item.key === WorkCardEnum.API_CASE_COUNT
|
||||||
? {
|
? {
|
||||||
name: t('workbench.homePage.casePassedRate'),
|
name: t('workbench.homePage.casePassedRate'),
|
||||||
count: '80%',
|
|
||||||
color: ['#00C261', '#ED0303'],
|
color: ['#00C261', '#ED0303'],
|
||||||
|
tooltipText: t('workbench.homePage.apiCaseCountPassRateTooltip'),
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
name: t('workbench.homePage.executionRate'),
|
name: t('workbench.homePage.executionRate'),
|
||||||
count: '80%',
|
|
||||||
color: ['#00C261', '#ED0303'],
|
color: ['#00C261', '#ED0303'],
|
||||||
|
tooltipText: t('workbench.homePage.scenarioCaseCountPassRateTooltip'),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
function initApiOrScenarioCount() {}
|
const hasPermission = ref<boolean>(false);
|
||||||
|
async function initApiOrScenarioCount() {
|
||||||
|
try {
|
||||||
|
const { startTime, endTime, dayNumber } = timeForm.value;
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
current: 1,
|
||||||
|
pageSize: 5,
|
||||||
|
startTime: dayNumber ? null : startTime,
|
||||||
|
endTime: dayNumber ? null : endTime,
|
||||||
|
dayNumber: dayNumber ?? null,
|
||||||
|
projectIds: innerProjectIds.value,
|
||||||
|
organizationId: appStore.currentOrgId,
|
||||||
|
handleUsers: [],
|
||||||
|
};
|
||||||
|
let detail;
|
||||||
|
if (props.item.key === WorkCardEnum.API_CASE_COUNT) {
|
||||||
|
detail = await workApiCaseCountDetail(params);
|
||||||
|
} else {
|
||||||
|
detail = await workScenarioCaseCountDetail(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
hasPermission.value = detail.errorCode !== 109001;
|
||||||
|
|
||||||
|
caseExecuteData.value = (detail.statusStatisticsMap?.execRate || []).map((e) => {
|
||||||
|
return {
|
||||||
|
...e,
|
||||||
|
value: e.count,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
casePassData.value = (detail.statusStatisticsMap?.passRate || []).map((e) => {
|
||||||
|
return {
|
||||||
|
...e,
|
||||||
|
value: e.count,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
if (hasPermission.value) {
|
||||||
|
// 执行次数
|
||||||
|
executionTimeValue.value = detail.statusStatisticsMap?.execCount || [];
|
||||||
|
// 数量
|
||||||
|
const valueKey = props.item.key === WorkCardEnum.API_CASE_COUNT ? 'apiCaseCount' : 'apiScenarioCount';
|
||||||
|
apiCountValue.value = detail.statusStatisticsMap?.[valueKey] || [];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeProject() {
|
||||||
|
nextTick(() => {
|
||||||
|
initApiOrScenarioCount();
|
||||||
|
emit('change');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
initApiOrScenarioCount();
|
||||||
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => innerProjectIds.value,
|
() => innerProjectIds.value,
|
||||||
|
@ -184,7 +254,6 @@
|
||||||
if (val) {
|
if (val) {
|
||||||
const [newProjectId] = val;
|
const [newProjectId] = val;
|
||||||
projectId.value = newProjectId;
|
projectId.value = newProjectId;
|
||||||
initApiOrScenarioCount();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
v-on="propsEvent"
|
v-on="propsEvent"
|
||||||
>
|
>
|
||||||
<template #num="{ record }">
|
<template #num="{ record }">
|
||||||
<MsButton type="text">{{ record.num || '-' }}</MsButton>
|
<MsButton type="text" @click="openDetail(record)">{{ record.num || '-' }}</MsButton>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="isNoPermission" #empty>
|
<template v-if="isNoPermission" #empty>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
|
@ -61,9 +61,14 @@
|
||||||
|
|
||||||
import { workApiChangeList } from '@/api/modules/workbench';
|
import { workApiChangeList } from '@/api/modules/workbench';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import useOpenNewPage from '@/hooks/useOpenNewPage';
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
|
|
||||||
|
import type { ApiDefinitionDetail } from '@/models/apiTest/management';
|
||||||
import type { SelectedCardItem, TimeFormParams } from '@/models/workbench/homePage';
|
import type { SelectedCardItem, TimeFormParams } from '@/models/workbench/homePage';
|
||||||
|
import { ApiTestRouteEnum } from '@/enums/routeEnum';
|
||||||
|
|
||||||
|
const { openNewPage } = useOpenNewPage();
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
@ -72,6 +77,10 @@
|
||||||
item: SelectedCardItem;
|
item: SelectedCardItem;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'change'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
const innerProjectIds = defineModel<string[]>('projectIds', {
|
const innerProjectIds = defineModel<string[]>('projectIds', {
|
||||||
required: true,
|
required: true,
|
||||||
});
|
});
|
||||||
|
@ -99,6 +108,7 @@
|
||||||
slotName: 'name',
|
slotName: 'name',
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
width: 200,
|
width: 200,
|
||||||
|
showTooltip: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'apiTestManagement.path',
|
title: 'apiTestManagement.path',
|
||||||
|
@ -147,6 +157,15 @@
|
||||||
updateTime: dayjs(item.updateTime).format('YYYY-MM-DD HH:mm:ss'),
|
updateTime: dayjs(item.updateTime).format('YYYY-MM-DD HH:mm:ss'),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 跳转详情
|
||||||
|
function openDetail(record: ApiDefinitionDetail) {
|
||||||
|
openNewPage(ApiTestRouteEnum.API_TEST_MANAGEMENT, {
|
||||||
|
dId: record.id,
|
||||||
|
pId: projectId.value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const isNoPermission = ref<boolean>(false);
|
const isNoPermission = ref<boolean>(false);
|
||||||
async function initData() {
|
async function initData() {
|
||||||
try {
|
try {
|
||||||
|
@ -169,7 +188,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeProject() {
|
function changeProject() {
|
||||||
|
nextTick(() => {
|
||||||
initData();
|
initData();
|
||||||
|
emit('change');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
|
@ -43,26 +43,31 @@
|
||||||
* @desc 接口数量
|
* @desc 接口数量
|
||||||
*/
|
*/
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { cloneDeep } from 'lodash-es';
|
|
||||||
|
|
||||||
import MsChart from '@/components/pure/chart/index.vue';
|
import MsChart from '@/components/pure/chart/index.vue';
|
||||||
import MsSelect from '@/components/business/ms-select';
|
import MsSelect from '@/components/business/ms-select';
|
||||||
import PassRatePie from './passRatePie.vue';
|
import PassRatePie from './passRatePie.vue';
|
||||||
import TabCard from './tabCard.vue';
|
import TabCard from './tabCard.vue';
|
||||||
|
|
||||||
|
import { workApiCountDetail } from '@/api/modules/workbench';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
|
|
||||||
import type { PassRateDataType, SelectedCardItem, TimeFormParams } from '@/models/workbench/homePage';
|
import type { SelectedCardItem, TimeFormParams } from '@/models/workbench/homePage';
|
||||||
|
|
||||||
import { handlePieData, handleUpdateTabPie } from '../utils';
|
import { handlePieData, handleUpdateTabPie } from '../utils';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const appStore = useAppStore();
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
item: SelectedCardItem;
|
item: SelectedCardItem;
|
||||||
projectIds: string[];
|
projectIds: string[];
|
||||||
}>();
|
}>();
|
||||||
const { t } = useI18n();
|
|
||||||
const appStore = useAppStore();
|
const emit = defineEmits<{
|
||||||
|
(e: 'change'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
const innerProjectIds = defineModel<string[]>('projectIds', {
|
const innerProjectIds = defineModel<string[]>('projectIds', {
|
||||||
required: true,
|
required: true,
|
||||||
|
@ -79,18 +84,9 @@
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const options = ref({});
|
|
||||||
|
|
||||||
// TODO 假数据
|
|
||||||
const detail = ref<PassRateDataType>({
|
|
||||||
statusStatisticsMap: null,
|
|
||||||
statusPercentList: null,
|
|
||||||
errorCode: 109001,
|
|
||||||
});
|
|
||||||
|
|
||||||
const coverValueList = ref<{ value: string | number; label: string; name: string }[]>([]);
|
const coverValueList = ref<{ value: string | number; label: string; name: string }[]>([]);
|
||||||
|
|
||||||
const passValueList = ref<{ value: string | number; label: string; name: string }[]>([]);
|
const completeValueList = ref<{ value: string | number; label: string; name: string }[]>([]);
|
||||||
const coverOptions = ref<Record<string, any>>({});
|
const coverOptions = ref<Record<string, any>>({});
|
||||||
const completeOptions = ref<Record<string, any>>({});
|
const completeOptions = ref<Record<string, any>>({});
|
||||||
const apiCountTabList = computed(() => {
|
const apiCountTabList = computed(() => {
|
||||||
|
@ -105,7 +101,7 @@
|
||||||
{
|
{
|
||||||
label: '',
|
label: '',
|
||||||
value: 'pass',
|
value: 'pass',
|
||||||
valueList: passValueList.value,
|
valueList: completeValueList.value,
|
||||||
options: { ...completeOptions.value },
|
options: { ...completeOptions.value },
|
||||||
tooltip: 'workbench.homePage.apiCountCompleteRateTooltip',
|
tooltip: 'workbench.homePage.apiCountCompleteRateTooltip',
|
||||||
},
|
},
|
||||||
|
@ -115,10 +111,10 @@
|
||||||
const apiCountOptions = ref({});
|
const apiCountOptions = ref({});
|
||||||
|
|
||||||
const hasPermission = ref<boolean>(false);
|
const hasPermission = ref<boolean>(false);
|
||||||
function initApiCount() {
|
async function initApiCount() {
|
||||||
try {
|
try {
|
||||||
const { startTime, endTime, dayNumber } = timeForm.value;
|
const { startTime, endTime, dayNumber } = timeForm.value;
|
||||||
const params = {
|
const detail = await workApiCountDetail({
|
||||||
current: 1,
|
current: 1,
|
||||||
pageSize: 5,
|
pageSize: 5,
|
||||||
startTime: dayNumber ? null : startTime,
|
startTime: dayNumber ? null : startTime,
|
||||||
|
@ -127,28 +123,29 @@
|
||||||
projectIds: innerProjectIds.value,
|
projectIds: innerProjectIds.value,
|
||||||
organizationId: appStore.currentOrgId,
|
organizationId: appStore.currentOrgId,
|
||||||
handleUsers: [],
|
handleUsers: [],
|
||||||
};
|
});
|
||||||
const { statusStatisticsMap, statusPercentList, errorCode } = detail.value;
|
const { statusStatisticsMap, statusPercentList, errorCode } = detail;
|
||||||
|
|
||||||
hasPermission.value = errorCode !== 109001;
|
hasPermission.value = errorCode !== 109001;
|
||||||
|
|
||||||
apiCountOptions.value = handlePieData(props.item.key, hasPermission.value, statusPercentList);
|
apiCountOptions.value = handlePieData(props.item.key, hasPermission.value, statusPercentList);
|
||||||
|
|
||||||
// 覆盖率
|
// 覆盖率 TODO 等接口
|
||||||
const { options: covOptions, valueList: coverList } = handleUpdateTabPie(
|
// const { options: covOptions, valueList: coverList } = handleUpdateTabPie(
|
||||||
statusStatisticsMap?.cover || [],
|
// statusStatisticsMap?.cover || [],
|
||||||
hasPermission.value,
|
// hasPermission.value,
|
||||||
`${props.item.key}-cover`
|
// `${props.item.key}-cover`
|
||||||
);
|
// );
|
||||||
coverValueList.value = coverList;
|
// coverValueList.value = coverList;
|
||||||
coverOptions.value = covOptions;
|
// coverOptions.value = covOptions;
|
||||||
|
|
||||||
|
// 完成率
|
||||||
const { options: comOptions, valueList: completedList } = handleUpdateTabPie(
|
const { options: comOptions, valueList: completedList } = handleUpdateTabPie(
|
||||||
statusStatisticsMap?.cover || [],
|
statusStatisticsMap?.completionRate || [],
|
||||||
hasPermission.value,
|
hasPermission.value,
|
||||||
`${props.item.key}-complete`
|
`${props.item.key}-complete`
|
||||||
);
|
);
|
||||||
passValueList.value = completedList;
|
completeValueList.value = completedList;
|
||||||
completeOptions.value = comOptions;
|
completeOptions.value = comOptions;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
|
@ -157,11 +154,15 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeProject() {
|
function changeProject() {
|
||||||
|
nextTick(() => {
|
||||||
initApiCount();
|
initApiCount();
|
||||||
|
emit('change');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initApiCount();
|
initApiCount();
|
||||||
|
emit('change');
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|
|
@ -64,6 +64,10 @@
|
||||||
item: SelectedCardItem;
|
item: SelectedCardItem;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'change'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
const innerProjectIds = defineModel<string[]>('projectIds', {
|
const innerProjectIds = defineModel<string[]>('projectIds', {
|
||||||
required: true,
|
required: true,
|
||||||
});
|
});
|
||||||
|
@ -149,7 +153,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeProject() {
|
function changeProject() {
|
||||||
|
emit('change');
|
||||||
|
nextTick(() => {
|
||||||
initCaseCount();
|
initCaseCount();
|
||||||
|
emit('change');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
|
@ -61,6 +61,10 @@
|
||||||
item: SelectedCardItem;
|
item: SelectedCardItem;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'change'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
const innerProjectIds = defineModel<string[]>('projectIds', {
|
const innerProjectIds = defineModel<string[]>('projectIds', {
|
||||||
required: true,
|
required: true,
|
||||||
});
|
});
|
||||||
|
@ -127,7 +131,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeProject() {
|
function changeProject() {
|
||||||
|
nextTick(() => {
|
||||||
initApiCount();
|
initApiCount();
|
||||||
|
emit('change');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
|
@ -46,10 +46,16 @@
|
||||||
import MsSelect from '@/components/business/ms-select';
|
import MsSelect from '@/components/business/ms-select';
|
||||||
import PassRatePie from './passRatePie.vue';
|
import PassRatePie from './passRatePie.vue';
|
||||||
|
|
||||||
|
import { workBugByMeCreated, workBugCountDetail, workBugHandleByMe } from '@/api/modules/workbench';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
|
|
||||||
import type { PassRateDataType, SelectedCardItem, TimeFormParams } from '@/models/workbench/homePage';
|
import type {
|
||||||
|
PassRateDataType,
|
||||||
|
SelectedCardItem,
|
||||||
|
TimeFormParams,
|
||||||
|
WorkHomePageDetail,
|
||||||
|
} from '@/models/workbench/homePage';
|
||||||
import { WorkCardEnum } from '@/enums/workbenchEnum';
|
import { WorkCardEnum } from '@/enums/workbenchEnum';
|
||||||
|
|
||||||
import { handlePieData, handleUpdateTabPie } from '../utils';
|
import { handlePieData, handleUpdateTabPie } from '../utils';
|
||||||
|
@ -62,6 +68,10 @@
|
||||||
item: SelectedCardItem;
|
item: SelectedCardItem;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'change'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
const innerProjectIds = defineModel<string[]>('projectIds', {
|
const innerProjectIds = defineModel<string[]>('projectIds', {
|
||||||
required: true,
|
required: true,
|
||||||
});
|
});
|
||||||
|
@ -81,25 +91,16 @@
|
||||||
|
|
||||||
const legacyOptions = ref<Record<string, any>>({});
|
const legacyOptions = ref<Record<string, any>>({});
|
||||||
|
|
||||||
// TODO 假数据
|
|
||||||
const detail = ref<PassRateDataType>({
|
|
||||||
statusStatisticsMap: {
|
|
||||||
legacy: [
|
|
||||||
{ name: '遗留率', count: 10 },
|
|
||||||
{ name: '缺陷总数', count: 2 },
|
|
||||||
{ name: '遗留缺陷数', count: 1 },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
statusPercentList: [
|
|
||||||
{ status: 'AAA', count: 1, percentValue: '10%' },
|
|
||||||
{ status: 'BBB', count: 3, percentValue: '0%' },
|
|
||||||
{ status: 'CCC', count: 6, percentValue: '0%' },
|
|
||||||
],
|
|
||||||
errorCode: 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
const countOptions = ref<Record<string, any>>({});
|
const countOptions = ref<Record<string, any>>({});
|
||||||
|
|
||||||
|
type SelectedBugCountKeys = WorkCardEnum.BUG_COUNT | WorkCardEnum.HANDLE_BUG_BY_ME | WorkCardEnum.CREATE_BUG_BY_ME;
|
||||||
|
|
||||||
|
const currentBugCount: (data: WorkHomePageDetail) => Promise<PassRateDataType> = {
|
||||||
|
[WorkCardEnum.BUG_COUNT]: workBugCountDetail,
|
||||||
|
[WorkCardEnum.HANDLE_BUG_BY_ME]: workBugHandleByMe,
|
||||||
|
[WorkCardEnum.CREATE_BUG_BY_ME]: workBugByMeCreated,
|
||||||
|
}[props.item.key as SelectedBugCountKeys];
|
||||||
|
|
||||||
const hasPermission = ref<boolean>(false);
|
const hasPermission = ref<boolean>(false);
|
||||||
async function initCount() {
|
async function initCount() {
|
||||||
try {
|
try {
|
||||||
|
@ -114,13 +115,16 @@
|
||||||
organizationId: appStore.currentOrgId,
|
organizationId: appStore.currentOrgId,
|
||||||
handleUsers: [],
|
handleUsers: [],
|
||||||
};
|
};
|
||||||
const { statusStatisticsMap, statusPercentList, errorCode } = detail.value;
|
|
||||||
|
const detail = await currentBugCount(params);
|
||||||
|
|
||||||
|
const { statusStatisticsMap, statusPercentList, errorCode } = detail;
|
||||||
hasPermission.value = errorCode !== 109001;
|
hasPermission.value = errorCode !== 109001;
|
||||||
|
|
||||||
countOptions.value = handlePieData(props.item.key, hasPermission.value, statusPercentList);
|
countOptions.value = handlePieData(props.item.key, hasPermission.value, statusPercentList);
|
||||||
|
|
||||||
const { options, valueList } = handleUpdateTabPie(
|
const { options, valueList } = handleUpdateTabPie(
|
||||||
statusStatisticsMap?.legacy || [],
|
statusStatisticsMap?.retentionRate || [],
|
||||||
hasPermission.value,
|
hasPermission.value,
|
||||||
`${props.item.key}-legacy`
|
`${props.item.key}-legacy`
|
||||||
);
|
);
|
||||||
|
@ -137,7 +141,10 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
function changeProject() {
|
function changeProject() {
|
||||||
|
nextTick(() => {
|
||||||
initCount();
|
initCount();
|
||||||
|
emit('change');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
@ -147,19 +154,21 @@
|
||||||
watch(
|
watch(
|
||||||
() => innerProjectIds.value,
|
() => innerProjectIds.value,
|
||||||
(val) => {
|
(val) => {
|
||||||
if (val) {
|
|
||||||
const [newProjectId] = val;
|
const [newProjectId] = val;
|
||||||
projectId.value = newProjectId;
|
projectId.value = newProjectId;
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => projectId.value,
|
() => projectId.value,
|
||||||
(val) => {
|
(val) => {
|
||||||
if (val) {
|
|
||||||
innerProjectIds.value = [val];
|
innerProjectIds.value = [val];
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -45,8 +45,7 @@
|
||||||
import MsChart from '@/components/pure/chart/index.vue';
|
import MsChart from '@/components/pure/chart/index.vue';
|
||||||
import MsSelect from '@/components/business/ms-select';
|
import MsSelect from '@/components/business/ms-select';
|
||||||
|
|
||||||
import { getProjectOptions } from '@/api/modules/project-management/projectMember';
|
import { workBugHandlerDetail, workHandleUserOptions } from '@/api/modules/workbench';
|
||||||
import { workBugHandlerDetail } from '@/api/modules/workbench';
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
import { characterLimit } from '@/utils';
|
import { characterLimit } from '@/utils';
|
||||||
|
@ -62,6 +61,10 @@
|
||||||
item: SelectedCardItem;
|
item: SelectedCardItem;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'change'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
const innerProjectIds = defineModel<string[]>('projectIds', {
|
const innerProjectIds = defineModel<string[]>('projectIds', {
|
||||||
required: true,
|
required: true,
|
||||||
});
|
});
|
||||||
|
@ -130,21 +133,27 @@
|
||||||
|
|
||||||
async function getMemberOptions() {
|
async function getMemberOptions() {
|
||||||
const [newProjectId] = innerProjectIds.value;
|
const [newProjectId] = innerProjectIds.value;
|
||||||
const res = await getProjectOptions(newProjectId);
|
const res = await workHandleUserOptions(newProjectId);
|
||||||
memberOptions.value = res.map((e: any) => ({
|
memberOptions.value = res.map((e: any) => ({
|
||||||
label: e.name,
|
label: e.text,
|
||||||
value: e.id,
|
value: e.value,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeProject() {
|
function changeProject() {
|
||||||
memberIds.value = [];
|
memberIds.value = [];
|
||||||
getMemberOptions();
|
getMemberOptions();
|
||||||
|
nextTick(() => {
|
||||||
getDefectMemberDetail();
|
getDefectMemberDetail();
|
||||||
|
emit('change');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeMember() {
|
function changeMember() {
|
||||||
|
nextTick(() => {
|
||||||
getDefectMemberDetail();
|
getDefectMemberDetail();
|
||||||
|
emit('change');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
@ -193,4 +202,14 @@
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped lang="less">
|
||||||
|
:deep(.arco-select-view-multiple.arco-select-view-size-medium .arco-select-view-tag) {
|
||||||
|
margin-top: 1px;
|
||||||
|
margin-bottom: 1px;
|
||||||
|
max-width: 80px;
|
||||||
|
height: auto;
|
||||||
|
min-height: 24px;
|
||||||
|
line-height: 22px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
:has-all-select="true"
|
:has-all-select="true"
|
||||||
:default-all-select="!(props.item.projectIds || []).length"
|
:default-all-select="!(props.item.projectIds || []).length"
|
||||||
:at-least-one="true"
|
:at-least-one="true"
|
||||||
|
@change="changeProject"
|
||||||
>
|
>
|
||||||
</MsSelect>
|
</MsSelect>
|
||||||
</div>
|
</div>
|
||||||
|
@ -45,6 +46,7 @@
|
||||||
import { contentTabList } from '@/config/workbench';
|
import { contentTabList } from '@/config/workbench';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
|
import { addCommasToNumber } from '@/utils';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
ModuleCardItem,
|
ModuleCardItem,
|
||||||
|
@ -62,6 +64,10 @@
|
||||||
item: SelectedCardItem;
|
item: SelectedCardItem;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'change'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
|
||||||
const innerProjectIds = defineModel<string[]>('projectIds', {
|
const innerProjectIds = defineModel<string[]>('projectIds', {
|
||||||
|
@ -111,14 +117,41 @@
|
||||||
|
|
||||||
// 处理data数据
|
// 处理data数据
|
||||||
options.value.series = detail.projectCountList.map((item) => {
|
options.value.series = detail.projectCountList.map((item) => {
|
||||||
|
const countData = item.count.map((e) => {
|
||||||
|
return {
|
||||||
|
name: item.name,
|
||||||
|
value: e !== 0 ? e : undefined,
|
||||||
|
tooltip: {
|
||||||
|
show: true,
|
||||||
|
trigger: 'item',
|
||||||
|
enterable: true,
|
||||||
|
formatter(params: any) {
|
||||||
|
const html = `
|
||||||
|
<div class="w-[186px] h-[50px] p-[16px] flex items-center justify-between">
|
||||||
|
<div class=" flex items-center">
|
||||||
|
<div class="mb-[2px] mr-[8px] h-[8px] w-[8px] rounded-sm bg-[${params.color}]" style="background:${
|
||||||
|
params.color
|
||||||
|
}"></div>
|
||||||
|
<div class="one-line-text max-w-[100px]"" style="color:#959598">${params.name}</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-[#323233] font-medium">${addCommasToNumber(params.value)}</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
return html;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
name: item.name,
|
name: item.name,
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
barWidth: 12,
|
barWidth: 12,
|
||||||
|
legendHoverLink: true,
|
||||||
|
large: true,
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
borderRadius: [2, 2, 0, 0], // 上边圆角
|
borderRadius: [2, 2, 0, 0], // 上边圆角
|
||||||
},
|
},
|
||||||
data: item.count,
|
data: countData,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -149,6 +182,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function changeProject() {
|
||||||
|
emit('change');
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initOverViewDetail();
|
initOverViewDetail();
|
||||||
});
|
});
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
:multiple="true"
|
:multiple="true"
|
||||||
:has-all-select="true"
|
:has-all-select="true"
|
||||||
:default-all-select="true"
|
:default-all-select="true"
|
||||||
|
@change="changeMember"
|
||||||
>
|
>
|
||||||
</MsSelect>
|
</MsSelect>
|
||||||
</div>
|
</div>
|
||||||
|
@ -64,6 +65,10 @@
|
||||||
item: SelectedCardItem;
|
item: SelectedCardItem;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'change'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
const innerProjectIds = defineModel<string[]>('projectIds', {
|
const innerProjectIds = defineModel<string[]>('projectIds', {
|
||||||
required: true,
|
required: true,
|
||||||
});
|
});
|
||||||
|
@ -138,8 +143,19 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeProject() {
|
function changeProject() {
|
||||||
|
memberIds.value = [];
|
||||||
getMemberOptions();
|
getMemberOptions();
|
||||||
|
nextTick(() => {
|
||||||
initOverViewMemberDetail();
|
initOverViewMemberDetail();
|
||||||
|
emit('change');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeMember() {
|
||||||
|
nextTick(() => {
|
||||||
|
initOverViewMemberDetail();
|
||||||
|
emit('change');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|
|
@ -1,6 +1,16 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="rate-content">
|
<div class="rate-content relative">
|
||||||
<MsChart :options="options" width="200px" />
|
<div class="relative flex h-full w-full items-center justify-center">
|
||||||
|
<a-tooltip
|
||||||
|
v-if="props.rateConfig.tooltipText"
|
||||||
|
:mouse-enter-delay="500"
|
||||||
|
:content="t(props.rateConfig.tooltipText || '')"
|
||||||
|
position="bottom"
|
||||||
|
>
|
||||||
|
<div class="tooltip-rate-tooltip"></div>
|
||||||
|
</a-tooltip>
|
||||||
|
<MsChart :options="options" width="146px" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -10,18 +20,22 @@
|
||||||
import MsChart from '@/components/pure/chart/index.vue';
|
import MsChart from '@/components/pure/chart/index.vue';
|
||||||
|
|
||||||
import { toolTipConfig } from '@/config/testPlan';
|
import { toolTipConfig } from '@/config/testPlan';
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import { addCommasToNumber } from '@/utils';
|
import { addCommasToNumber } from '@/utils';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
data: { name: string; value: number }[];
|
data: { name: string; value: number }[];
|
||||||
|
hasPermission: boolean;
|
||||||
rateConfig: {
|
rateConfig: {
|
||||||
name: string;
|
name: string;
|
||||||
count: string;
|
|
||||||
color: string[];
|
color: string[];
|
||||||
|
tooltipText: string;
|
||||||
};
|
};
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const commonOptionConfig = ref({
|
const options = ref<Record<string, any>>({
|
||||||
title: {
|
title: {
|
||||||
show: true,
|
show: true,
|
||||||
text: '',
|
text: '',
|
||||||
|
@ -47,6 +61,7 @@
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
...toolTipConfig,
|
...toolTipConfig,
|
||||||
|
show: !!props.hasPermission,
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
orient: 'vertical',
|
orient: 'vertical',
|
||||||
|
@ -103,25 +118,53 @@
|
||||||
},
|
},
|
||||||
data: [],
|
data: [],
|
||||||
},
|
},
|
||||||
|
graphic: {
|
||||||
|
type: 'text',
|
||||||
|
left: 'center',
|
||||||
|
bottom: 10,
|
||||||
|
style: {
|
||||||
|
text: t('workbench.homePage.notHasResPermission'),
|
||||||
|
fontSize: 14,
|
||||||
|
fill: '#959598',
|
||||||
|
backgroundColor: '#F9F9FE',
|
||||||
|
padding: [6, 16, 6, 16],
|
||||||
|
borderRadius: 4,
|
||||||
|
},
|
||||||
|
invisible: false,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
const options = ref({});
|
|
||||||
|
|
||||||
function initOptions() {
|
function initOptions() {
|
||||||
const { name, count, color } = props.rateConfig;
|
const { name, color } = props.rateConfig;
|
||||||
options.value = {
|
|
||||||
...commonOptionConfig.value,
|
if (props.hasPermission) {
|
||||||
title: {
|
options.value.series.data = props.data.slice(1);
|
||||||
...commonOptionConfig.value.title,
|
|
||||||
text: name,
|
options.value.legend.formatter = (seriousName: string) => {
|
||||||
subtext: count,
|
const item = props.data.find((e) => e.name === seriousName);
|
||||||
},
|
return `{a|${seriousName}} {b|${addCommasToNumber(item?.value || 0)}}`;
|
||||||
series: {
|
|
||||||
...commonOptionConfig.value.series,
|
|
||||||
data: [...props.data],
|
|
||||||
color,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
options.value.title.subtext = `${props.data[0].value ?? 0}%`;
|
||||||
|
} else {
|
||||||
|
options.value.series.data = [];
|
||||||
|
options.value.title.subtext = `-%`;
|
||||||
}
|
}
|
||||||
|
options.value.graphic.invisible = !!props.hasPermission;
|
||||||
|
options.value.tooltip.show = !!props.hasPermission;
|
||||||
|
options.value.title.text = name;
|
||||||
|
|
||||||
|
options.value.series.color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.data,
|
||||||
|
(val) => {
|
||||||
|
if (val) {
|
||||||
|
initOptions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initOptions();
|
initOptions();
|
||||||
|
@ -130,6 +173,14 @@
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.rate-content {
|
.rate-content {
|
||||||
height: 152px;
|
height: 158px;
|
||||||
|
}
|
||||||
|
.tooltip-rate-tooltip {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
z-index: 9;
|
||||||
|
width: 78px;
|
||||||
|
height: 78px;
|
||||||
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -57,6 +57,10 @@
|
||||||
item: SelectedCardItem;
|
item: SelectedCardItem;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'change'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
const innerProjectIds = defineModel<string[]>('projectIds', {
|
const innerProjectIds = defineModel<string[]>('projectIds', {
|
||||||
required: true,
|
required: true,
|
||||||
});
|
});
|
||||||
|
@ -120,7 +124,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeProject() {
|
function changeProject() {
|
||||||
|
nextTick(() => {
|
||||||
getRelatedCaseCount();
|
getRelatedCaseCount();
|
||||||
|
emit('change');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
|
@ -57,12 +57,16 @@
|
||||||
|
|
||||||
import { handlePieData, handleUpdateTabPie } from '../utils';
|
import { handlePieData, handleUpdateTabPie } from '../utils';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const appStore = useAppStore();
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
item: SelectedCardItem;
|
item: SelectedCardItem;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { t } = useI18n();
|
const emit = defineEmits<{
|
||||||
const appStore = useAppStore();
|
(e: 'change'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
const innerProjectIds = defineModel<string[]>('projectIds', {
|
const innerProjectIds = defineModel<string[]>('projectIds', {
|
||||||
required: true,
|
required: true,
|
||||||
|
@ -190,12 +194,16 @@
|
||||||
passOptions.value = passedOptions;
|
passOptions.value = passedOptions;
|
||||||
completeOptions.value = comOptions;
|
completeOptions.value = comOptions;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeProject() {
|
function changeProject() {
|
||||||
|
nextTick(() => {
|
||||||
initTestPlanCount();
|
initTestPlanCount();
|
||||||
|
emit('change');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
|
@ -27,6 +27,13 @@
|
||||||
class="mt-[16px]"
|
class="mt-[16px]"
|
||||||
v-on="propsEvent"
|
v-on="propsEvent"
|
||||||
>
|
>
|
||||||
|
<template #num="{ record }">
|
||||||
|
<a-tooltip :content="`${record.num}`">
|
||||||
|
<a-button type="text" class="px-0 !text-[14px] !leading-[22px]" @click="openDetail(record.id)">
|
||||||
|
<div class="one-line-text max-w-[168px]">{{ record.num }}</div>
|
||||||
|
</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
<template #passRateColumn>
|
<template #passRateColumn>
|
||||||
<div class="flex items-center text-[var(--color-text-3)]">
|
<div class="flex items-center text-[var(--color-text-3)]">
|
||||||
{{ t('caseManagement.caseReview.passRate') }}
|
{{ t('caseManagement.caseReview.passRate') }}
|
||||||
|
@ -58,6 +65,11 @@
|
||||||
}}
|
}}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
|
<template #createUserName="{ record }">
|
||||||
|
<a-tooltip :content="`${record.createUserName}`" position="tl">
|
||||||
|
<div class="one-line-text">{{ record.createUserName }}</div>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
<template v-if="isNoPermission" #empty>
|
<template v-if="isNoPermission" #empty>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<slot name="empty">
|
<slot name="empty">
|
||||||
|
@ -86,9 +98,13 @@
|
||||||
|
|
||||||
import { workReviewList } from '@/api/modules/workbench';
|
import { workReviewList } from '@/api/modules/workbench';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import useOpenNewPage from '@/hooks/useOpenNewPage';
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
|
|
||||||
import type { SelectedCardItem, TimeFormParams } from '@/models/workbench/homePage';
|
import type { SelectedCardItem, TimeFormParams } from '@/models/workbench/homePage';
|
||||||
|
import { CaseManagementRouteEnum } from '@/enums/routeEnum';
|
||||||
|
|
||||||
|
const { openNewPage } = useOpenNewPage();
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
|
||||||
|
@ -98,6 +114,10 @@
|
||||||
item: SelectedCardItem;
|
item: SelectedCardItem;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'change'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
const innerProjectIds = defineModel<string[]>('projectIds', {
|
const innerProjectIds = defineModel<string[]>('projectIds', {
|
||||||
required: true,
|
required: true,
|
||||||
});
|
});
|
||||||
|
@ -122,9 +142,10 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'caseManagement.caseReview.reviewName',
|
title: 'caseManagement.caseReview.reviewName',
|
||||||
slotName: 'reviewName',
|
slotName: 'name',
|
||||||
dataIndex: 'reviewName',
|
dataIndex: 'name',
|
||||||
width: 200,
|
width: 200,
|
||||||
|
showTooltip: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'caseManagement.caseReview.passRate',
|
title: 'caseManagement.caseReview.passRate',
|
||||||
|
@ -139,6 +160,12 @@
|
||||||
showDrag: true,
|
showDrag: true,
|
||||||
width: 100,
|
width: 100,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'common.creator',
|
||||||
|
slotName: 'createUserName',
|
||||||
|
dataIndex: 'createUser',
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(workReviewList, {
|
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(workReviewList, {
|
||||||
|
@ -169,8 +196,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openDetail(id: number) {
|
||||||
|
openNewPage(CaseManagementRouteEnum.CASE_MANAGEMENT_REVIEW_DETAIL, { id });
|
||||||
|
}
|
||||||
|
|
||||||
function changeProject() {
|
function changeProject() {
|
||||||
|
nextTick(() => {
|
||||||
initData();
|
initData();
|
||||||
|
emit('change');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
|
@ -56,57 +56,77 @@
|
||||||
v-if="[WorkCardEnum.CREATE_BY_ME, WorkCardEnum.PROJECT_VIEW].includes(item.key)"
|
v-if="[WorkCardEnum.CREATE_BY_ME, WorkCardEnum.PROJECT_VIEW].includes(item.key)"
|
||||||
v-model:projectIds="item.projectIds"
|
v-model:projectIds="item.projectIds"
|
||||||
:item="item"
|
:item="item"
|
||||||
|
@change="changeHandler"
|
||||||
/>
|
/>
|
||||||
<OverviewMember
|
<OverviewMember
|
||||||
v-else-if="item.key === WorkCardEnum.PROJECT_MEMBER_VIEW"
|
v-else-if="item.key === WorkCardEnum.PROJECT_MEMBER_VIEW"
|
||||||
v-model:projectIds="item.projectIds"
|
v-model:projectIds="item.projectIds"
|
||||||
v-model:handleUsers="item.handleUsers"
|
v-model:handleUsers="item.handleUsers"
|
||||||
:item="item"
|
:item="item"
|
||||||
|
@change="changeHandler"
|
||||||
|
/>
|
||||||
|
<CaseCount
|
||||||
|
v-else-if="item.key === WorkCardEnum.CASE_COUNT"
|
||||||
|
v-model:projectIds="item.projectIds"
|
||||||
|
:item="item"
|
||||||
|
@change="changeHandler"
|
||||||
/>
|
/>
|
||||||
<CaseCount v-else-if="item.key === WorkCardEnum.CASE_COUNT" v-model:projectIds="item.projectIds" :item="item" />
|
|
||||||
<RelatedCaseCount
|
<RelatedCaseCount
|
||||||
v-else-if="item.key === WorkCardEnum.ASSOCIATE_CASE_COUNT"
|
v-else-if="item.key === WorkCardEnum.ASSOCIATE_CASE_COUNT"
|
||||||
v-model:projectIds="item.projectIds"
|
v-model:projectIds="item.projectIds"
|
||||||
:item="item"
|
:item="item"
|
||||||
|
@change="changeHandler"
|
||||||
/>
|
/>
|
||||||
<CaseReviewedCount
|
<CaseReviewedCount
|
||||||
v-else-if="item.key === WorkCardEnum.REVIEW_CASE_COUNT"
|
v-else-if="item.key === WorkCardEnum.REVIEW_CASE_COUNT"
|
||||||
v-model:projectIds="item.projectIds"
|
v-model:projectIds="item.projectIds"
|
||||||
:item="item"
|
:item="item"
|
||||||
|
@change="changeHandler"
|
||||||
/>
|
/>
|
||||||
<WaitReviewList
|
<WaitReviewList
|
||||||
v-else-if="item.key === WorkCardEnum.REVIEWING_BY_ME"
|
v-else-if="item.key === WorkCardEnum.REVIEWING_BY_ME"
|
||||||
v-model:projectIds="item.projectIds"
|
v-model:projectIds="item.projectIds"
|
||||||
:item="item"
|
:item="item"
|
||||||
|
@change="changeHandler"
|
||||||
/>
|
/>
|
||||||
<ApiAndScenarioCase
|
<ApiAndScenarioCase
|
||||||
v-else-if="[WorkCardEnum.API_CASE_COUNT, WorkCardEnum.SCENARIO_COUNT].includes(item.key)"
|
v-else-if="[WorkCardEnum.API_CASE_COUNT, WorkCardEnum.SCENARIO_COUNT].includes(item.key)"
|
||||||
v-model:projectIds="item.projectIds"
|
v-model:projectIds="item.projectIds"
|
||||||
:type="item.key"
|
:type="item.key"
|
||||||
:item="item"
|
:item="item"
|
||||||
|
@change="changeHandler"
|
||||||
/>
|
/>
|
||||||
<ApiChangeList
|
<ApiChangeList
|
||||||
v-else-if="item.key === WorkCardEnum.API_CHANGE"
|
v-else-if="item.key === WorkCardEnum.API_CHANGE"
|
||||||
v-model:projectIds="item.projectIds"
|
v-model:projectIds="item.projectIds"
|
||||||
:item="item"
|
:item="item"
|
||||||
|
@change="changeHandler"
|
||||||
/>
|
/>
|
||||||
<DefectMemberBar
|
<DefectMemberBar
|
||||||
v-else-if="item.key === WorkCardEnum.BUG_HANDLE_USER"
|
v-else-if="item.key === WorkCardEnum.BUG_HANDLE_USER"
|
||||||
v-model:projectIds="item.projectIds"
|
v-model:projectIds="item.projectIds"
|
||||||
v-model:handleUsers="item.handleUsers"
|
v-model:handleUsers="item.handleUsers"
|
||||||
:item="item"
|
:item="item"
|
||||||
|
@change="changeHandler"
|
||||||
/>
|
/>
|
||||||
<DefectCount
|
<DefectCount
|
||||||
v-else-if="countOfBug.includes(item.key)"
|
v-else-if="countOfBug.includes(item.key)"
|
||||||
v-model:projectIds="item.projectIds"
|
v-model:projectIds="item.projectIds"
|
||||||
:item="item"
|
:item="item"
|
||||||
:type="item.key"
|
:type="item.key"
|
||||||
|
@change="changeHandler"
|
||||||
|
/>
|
||||||
|
<ApiCount
|
||||||
|
v-else-if="item.key === WorkCardEnum.API_COUNT"
|
||||||
|
v-model:projectIds="item.projectIds"
|
||||||
|
:item="item"
|
||||||
|
@change="changeHandler"
|
||||||
/>
|
/>
|
||||||
<ApiCount v-else-if="item.key === WorkCardEnum.API_COUNT" v-model:projectIds="item.projectIds" :item="item" />
|
|
||||||
<TestPlanCount
|
<TestPlanCount
|
||||||
v-else-if="item.key === WorkCardEnum.TEST_PLAN_COUNT"
|
v-else-if="item.key === WorkCardEnum.TEST_PLAN_COUNT"
|
||||||
v-model:projectIds="item.projectIds"
|
v-model:projectIds="item.projectIds"
|
||||||
:item="item"
|
:item="item"
|
||||||
|
@change="changeHandler"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -142,13 +162,13 @@
|
||||||
import DefectMemberBar from '@/views/workbench/homePage/components/defectMemberBar.vue';
|
import DefectMemberBar from '@/views/workbench/homePage/components/defectMemberBar.vue';
|
||||||
import OverviewMember from '@/views/workbench/homePage/components/overviewMember.vue';
|
import OverviewMember from '@/views/workbench/homePage/components/overviewMember.vue';
|
||||||
|
|
||||||
import { getDashboardLayout } from '@/api/modules/workbench';
|
import { editDashboardLayout, getDashboardLayout } from '@/api/modules/workbench';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import { useUserStore } from '@/store';
|
import { useUserStore } from '@/store';
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
import { getLocalStorage, setLocalStorage } from '@/utils/local-storage';
|
import { getLocalStorage, setLocalStorage } from '@/utils/local-storage';
|
||||||
|
|
||||||
import { SelectedCardItem } from '@/models/workbench/homePage';
|
import { SelectedCardItem, TimeFormParams } from '@/models/workbench/homePage';
|
||||||
import { WorkCardEnum } from '@/enums/workbenchEnum';
|
import { WorkCardEnum } from '@/enums/workbenchEnum';
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
@ -159,12 +179,12 @@
|
||||||
|
|
||||||
const rangeTime = ref<number[]>([]);
|
const rangeTime = ref<number[]>([]);
|
||||||
const tempRange = ref<(Date | string | number)[]>(['00:00:00', '00:00:00']);
|
const tempRange = ref<(Date | string | number)[]>(['00:00:00', '00:00:00']);
|
||||||
const initTime = {
|
const initTime: TimeFormParams = {
|
||||||
dayNumber: 3,
|
dayNumber: 3,
|
||||||
startTime: 0,
|
startTime: 0,
|
||||||
endTime: 0,
|
endTime: 0,
|
||||||
};
|
};
|
||||||
const timeForm = ref({ ...initTime });
|
const timeForm = ref<TimeFormParams>({ ...initTime });
|
||||||
|
|
||||||
function resetTime() {
|
function resetTime() {
|
||||||
timeForm.value = { ...initTime };
|
timeForm.value = { ...initTime };
|
||||||
|
@ -173,13 +193,16 @@
|
||||||
|
|
||||||
// 改变时间类型
|
// 改变时间类型
|
||||||
function handleChangeTime(value: string | number | boolean, ev: Event) {
|
function handleChangeTime(value: string | number | boolean, ev: Event) {
|
||||||
|
if (value) {
|
||||||
resetTime();
|
resetTime();
|
||||||
timeForm.value.dayNumber = value as number;
|
timeForm.value.dayNumber = value as number;
|
||||||
setLocalStorage(`WORK_TIME_${userStore.id}`, JSON.stringify(timeForm.value));
|
setLocalStorage(`WORK_TIME_${userStore.id}`, JSON.stringify(timeForm.value));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// 改变时间
|
// 改变时间
|
||||||
function handleTimeSelect(value: (Date | string | number | undefined)[]) {
|
function handleTimeSelect(value: (Date | string | number | undefined)[]) {
|
||||||
if (value) {
|
if (value) {
|
||||||
|
timeForm.value.dayNumber = '';
|
||||||
timeForm.value.startTime = 0;
|
timeForm.value.startTime = 0;
|
||||||
timeForm.value.endTime = 0;
|
timeForm.value.endTime = 0;
|
||||||
const start = (value as number[])[0];
|
const start = (value as number[])[0];
|
||||||
|
@ -228,6 +251,15 @@
|
||||||
initDefaultList();
|
initDefaultList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function changeHandler() {
|
||||||
|
try {
|
||||||
|
await editDashboardLayout(defaultWorkList.value, appStore.currentOrgId);
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initDefaultList();
|
initDefaultList();
|
||||||
const defaultTime = getLocalStorage(`WORK_TIME_${userStore.id}`);
|
const defaultTime = getLocalStorage(`WORK_TIME_${userStore.id}`);
|
||||||
|
@ -236,11 +268,25 @@
|
||||||
} else {
|
} else {
|
||||||
timeForm.value = JSON.parse(defaultTime);
|
timeForm.value = JSON.parse(defaultTime);
|
||||||
const { startTime, endTime } = timeForm.value;
|
const { startTime, endTime } = timeForm.value;
|
||||||
|
if (startTime && endTime) {
|
||||||
rangeTime.value = [startTime, endTime];
|
rangeTime.value = [startTime, endTime];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
provide('timeForm', timeForm);
|
const time = ref({ ...timeForm.value });
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => timeForm.value,
|
||||||
|
(val) => {
|
||||||
|
if (val.dayNumber || (val.endTime && val.startTime)) {
|
||||||
|
time.value = { ...val };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
provide('timeForm', time);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
|
|
|
@ -112,4 +112,5 @@ export default {
|
||||||
'workbench.homePage.executeRate': 'Execution Rate',
|
'workbench.homePage.executeRate': 'Execution Rate',
|
||||||
'workbench.homePage.completeRate': 'Completion Rate',
|
'workbench.homePage.completeRate': 'Completion Rate',
|
||||||
'workbench.homePage.legacyRate': 'Legacy Rate',
|
'workbench.homePage.legacyRate': 'Legacy Rate',
|
||||||
|
'workbench.homePage.unit': 'Unit: Number',
|
||||||
};
|
};
|
||||||
|
|
|
@ -98,4 +98,5 @@ export default {
|
||||||
'workbench.homePage.executeRate': '执行率',
|
'workbench.homePage.executeRate': '执行率',
|
||||||
'workbench.homePage.completeRate': '完成率',
|
'workbench.homePage.completeRate': '完成率',
|
||||||
'workbench.homePage.legacyRate': '遗留率',
|
'workbench.homePage.legacyRate': '遗留率',
|
||||||
|
'workbench.homePage.unit': '单位:个',
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,9 +10,13 @@ import { WorkCardEnum } from '@/enums/workbenchEnum';
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
// 通用颜色配置
|
// 通用颜色配置
|
||||||
export const commonColorConfig = [
|
export const commonColorConfig = [
|
||||||
|
'#783887',
|
||||||
|
'#FFC14E',
|
||||||
|
'#2DFCEF',
|
||||||
'#811FA3',
|
'#811FA3',
|
||||||
|
'#00D1FF',
|
||||||
|
'#FFA53D',
|
||||||
'#00C261',
|
'#00C261',
|
||||||
'#3370FF',
|
|
||||||
'#AA4FBF',
|
'#AA4FBF',
|
||||||
'#FFA1FF',
|
'#FFA1FF',
|
||||||
'#EE50A3',
|
'#EE50A3',
|
||||||
|
@ -23,15 +27,17 @@ export const commonColorConfig = [
|
||||||
'#62D256',
|
'#62D256',
|
||||||
'#14E1C6',
|
'#14E1C6',
|
||||||
'#50CEFB',
|
'#50CEFB',
|
||||||
|
'#3370FF',
|
||||||
'#2B5FD9',
|
'#2B5FD9',
|
||||||
|
'#76F0FF',
|
||||||
'#935AF6',
|
'#935AF6',
|
||||||
'#DC9BFF',
|
'#DC9BFF',
|
||||||
|
'#FFC75E',
|
||||||
'#D34400',
|
'#D34400',
|
||||||
'#F4D0BF',
|
'#F4D0BF',
|
||||||
'#F4D0BF',
|
'#FBD3E8',
|
||||||
|
'#D9F457',
|
||||||
'#0089D1',
|
'#0089D1',
|
||||||
'#0089D1',
|
|
||||||
'#62D256',
|
|
||||||
'#87F578',
|
'#87F578',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -63,21 +69,9 @@ export function getCommonBarOptions(hasRoom: boolean, color: string[]): Record<s
|
||||||
},
|
},
|
||||||
displayMode: 'single',
|
displayMode: 'single',
|
||||||
enterable: true,
|
enterable: true,
|
||||||
// TODO 单例模式
|
axisPointer: {
|
||||||
// formatter(params: any) {
|
type: 'shadow',
|
||||||
// const html = `
|
},
|
||||||
// <div class="w-[186px] h-[50px] p-[16px] flex items-center justify-between">
|
|
||||||
// <div class=" flex items-center">
|
|
||||||
// <div class="mb-[2px] mr-[8px] h-[8px] w-[8px] rounded-sm bg-[${params.color}]" style="background:${
|
|
||||||
// params.color
|
|
||||||
// }"></div>
|
|
||||||
// <div style="color:#959598">${params.name}</div>
|
|
||||||
// </div>
|
|
||||||
// <div class="text-[#323233] font-medium">${addCommasToNumber(params.value)}</div>
|
|
||||||
// </div>
|
|
||||||
// `;
|
|
||||||
// return html;
|
|
||||||
// },
|
|
||||||
formatter(params: any) {
|
formatter(params: any) {
|
||||||
const html = `
|
const html = `
|
||||||
<div class="w-[186px] ms-scroll-bar max-h-[206px] overflow-y-auto p-[16px] gap-[8px] flex flex-col">
|
<div class="w-[186px] ms-scroll-bar max-h-[206px] overflow-y-auto p-[16px] gap-[8px] flex flex-col">
|
||||||
|
@ -129,8 +123,8 @@ export function getCommonBarOptions(hasRoom: boolean, color: string[]): Record<s
|
||||||
},
|
},
|
||||||
yAxis: [
|
yAxis: [
|
||||||
{
|
{
|
||||||
type: 'value',
|
type: 'log',
|
||||||
name: '单位:个', // 设置单位
|
name: t('workbench.homePage.unit'), // 设置单位
|
||||||
position: 'left',
|
position: 'left',
|
||||||
nameTextStyle: {
|
nameTextStyle: {
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
|
@ -146,8 +140,7 @@ export function getCommonBarOptions(hasRoom: boolean, color: string[]): Record<s
|
||||||
type: 'dashed', // 水平线线型,可选 'solid'、'dashed'、'dotted'
|
type: 'dashed', // 水平线线型,可选 'solid'、'dashed'、'dotted'
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
min: 0,
|
min: 1,
|
||||||
max: 1,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
graphic: {
|
graphic: {
|
||||||
|
@ -166,7 +159,6 @@ export function getCommonBarOptions(hasRoom: boolean, color: string[]): Record<s
|
||||||
},
|
},
|
||||||
colorBy: 'series',
|
colorBy: 'series',
|
||||||
series: [],
|
series: [],
|
||||||
barCategoryGap: '50%', // 控制 X 轴分布居中效果
|
|
||||||
legend: {
|
legend: {
|
||||||
width: '60%',
|
width: '60%',
|
||||||
show: true,
|
show: true,
|
||||||
|
|
Loading…
Reference in New Issue