feat(工作台): 工作台首页联调部分卡片接口覆盖率
This commit is contained in:
parent
e2ef7e8c93
commit
cbc8cd8a7a
|
@ -8,6 +8,7 @@ import type { CaseManagementTable } from '@/models/caseManagement/featureCase';
|
||||||
import type { CommonList, TableQueryParams } from '@/models/common';
|
import type { CommonList, TableQueryParams } from '@/models/common';
|
||||||
import type { PassRateCountDetail, TestPlanItem } from '@/models/testPlan/testPlan';
|
import type { PassRateCountDetail, TestPlanItem } from '@/models/testPlan/testPlan';
|
||||||
import type {
|
import type {
|
||||||
|
ApiCoverageData,
|
||||||
OverViewOfProject,
|
OverViewOfProject,
|
||||||
PassRateDataType,
|
PassRateDataType,
|
||||||
SelectedCardItem,
|
SelectedCardItem,
|
||||||
|
@ -19,6 +20,7 @@ import {
|
||||||
GetDashboardLayoutUrl,
|
GetDashboardLayoutUrl,
|
||||||
WorkApiCaseCountDetailUrl,
|
WorkApiCaseCountDetailUrl,
|
||||||
WorkApiChangeListUrl,
|
WorkApiChangeListUrl,
|
||||||
|
WorkApiCountCoverRateUrl,
|
||||||
WorkApiCountDetailUrl,
|
WorkApiCountDetailUrl,
|
||||||
WorkAssociateCaseDetailUrl,
|
WorkAssociateCaseDetailUrl,
|
||||||
WorkbenchApiCaseListUrl,
|
WorkbenchApiCaseListUrl,
|
||||||
|
@ -37,6 +39,7 @@ import {
|
||||||
WorkHandleUserOptionsUrl,
|
WorkHandleUserOptionsUrl,
|
||||||
WorkMemberViewDetailUrl,
|
WorkMemberViewDetailUrl,
|
||||||
WorkMyCreatedDetailUrl,
|
WorkMyCreatedDetailUrl,
|
||||||
|
WorkPlanLegacyBugUrl,
|
||||||
WorkProOverviewDetailUrl,
|
WorkProOverviewDetailUrl,
|
||||||
WorkReviewListUrl,
|
WorkReviewListUrl,
|
||||||
WorkScenarioCaseCountDetailUrl,
|
WorkScenarioCaseCountDetailUrl,
|
||||||
|
@ -172,6 +175,16 @@ export function workHandleUserOptions(projectId: string) {
|
||||||
return MSR.get({ url: WorkHandleUserOptionsUrl, params: projectId }, { ignoreCancelToken: true });
|
return MSR.get({ url: WorkHandleUserOptionsUrl, params: projectId }, { ignoreCancelToken: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 工作台-首页-测试计划遗留缺陷
|
||||||
|
export function workPlanLegacyBug(data: WorkHomePageDetail) {
|
||||||
|
return MSR.post<PassRateDataType>({ url: WorkPlanLegacyBugUrl, data }, { ignoreCancelToken: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 工作台-首页-接口测试覆盖率
|
||||||
|
export function workApiCountCoverRage(projectId: string) {
|
||||||
|
return MSR.get<ApiCoverageData>({ url: WorkApiCountCoverRateUrl, 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 });
|
||||||
|
|
|
@ -26,3 +26,5 @@ export const WorkHandleUserOptionsUrl = '/dashboard/bug_handle_user/list'; //
|
||||||
export const WorkBugCountDetailUrl = '/dashboard/bug_count'; // 工作台-首页-缺陷数量
|
export const WorkBugCountDetailUrl = '/dashboard/bug_count'; // 工作台-首页-缺陷数量
|
||||||
export const WorkBugByMeCreatedUrl = '/dashboard/create_bug_by_me'; // 工作台-首页-我创建的缺陷
|
export const WorkBugByMeCreatedUrl = '/dashboard/create_bug_by_me'; // 工作台-首页-我创建的缺陷
|
||||||
export const WorkBugHandleByMeUrl = '/dashboard/handle_bug_by_me'; // 工作台-首页-待我处理的缺陷
|
export const WorkBugHandleByMeUrl = '/dashboard/handle_bug_by_me'; // 工作台-首页-待我处理的缺陷
|
||||||
|
export const WorkPlanLegacyBugUrl = '/dashboard/plan_legacy_bug'; // 工作台-首页-测试计划遗留缺陷
|
||||||
|
export const WorkApiCountCoverRateUrl = '/api/definition/rage'; // 工作台-首页-覆盖率
|
||||||
|
|
|
@ -62,12 +62,12 @@ export const defaultCover = [
|
||||||
{
|
{
|
||||||
label: 'workbench.homePage.covered',
|
label: 'workbench.homePage.covered',
|
||||||
value: '-',
|
value: '-',
|
||||||
name: '',
|
name: 'workbench.homePage.covered',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'workbench.homePage.notCover',
|
label: 'workbench.homePage.notCover',
|
||||||
value: '-',
|
value: '-',
|
||||||
name: '',
|
name: 'workbench.homePage.notCover',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
// 评审率
|
// 评审率
|
||||||
|
|
|
@ -83,3 +83,18 @@ export interface PassRateDataType {
|
||||||
| null;
|
| null;
|
||||||
errorCode: number;
|
errorCode: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ApiCoverageData {
|
||||||
|
allApiCount: number; // 总的 API 数量
|
||||||
|
unCoverWithApiDefinition: number; // 未覆盖 API 定义的数量
|
||||||
|
coverWithApiDefinition: number; // 覆盖了 API 定义的数量
|
||||||
|
apiCoverage: string; // API 覆盖率
|
||||||
|
|
||||||
|
unCoverWithApiCase: number; // 未覆盖 API 测试用例的数量
|
||||||
|
coverWithApiCase: number; // 覆盖了 API 测试用例的数量
|
||||||
|
apiCaseCoverage: string; // API 测试用例覆盖率(
|
||||||
|
|
||||||
|
unCoverWithApiScenario: number; // 未覆盖 API 场景的数量
|
||||||
|
coverWithApiScenario: number; // 覆盖了 API 场景的数量
|
||||||
|
scenarioCoverage: string; // API 场景覆盖率
|
||||||
|
}
|
||||||
|
|
|
@ -36,7 +36,12 @@
|
||||||
</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 :has-permission="hasPermission" :data="coverData" :rate-config="coverTitleConfig" />
|
<RatioPie
|
||||||
|
:has-permission="hasPermission"
|
||||||
|
:loading="loading"
|
||||||
|
:data="coverData"
|
||||||
|
:rate-config="coverTitleConfig"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="case-ratio-item">
|
<div class="case-ratio-item">
|
||||||
<RatioPie :has-permission="hasPermission" :data="caseExecuteData" :rate-config="executeTitleConfig" />
|
<RatioPie :has-permission="hasPermission" :data="caseExecuteData" :rate-config="executeTitleConfig" />
|
||||||
|
@ -54,16 +59,17 @@
|
||||||
* @desc 接口用例数量/场景用例数量
|
* @desc 接口用例数量/场景用例数量
|
||||||
*/
|
*/
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
|
||||||
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 { workApiCaseCountDetail, workApiCountCoverRage, 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';
|
||||||
|
|
||||||
import type { SelectedCardItem, TimeFormParams } from '@/models/workbench/homePage';
|
import type { ApiCoverageData, SelectedCardItem, TimeFormParams } from '@/models/workbench/homePage';
|
||||||
import { WorkCardEnum } from '@/enums/workbenchEnum';
|
import { WorkCardEnum } from '@/enums/workbenchEnum';
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
@ -72,6 +78,8 @@
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
item: SelectedCardItem;
|
item: SelectedCardItem;
|
||||||
|
status?: boolean;
|
||||||
|
cover?: ApiCoverageData;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
@ -86,7 +94,7 @@
|
||||||
|
|
||||||
const executionTimeValue = ref<{ name: string; count: number | string }[]>([
|
const executionTimeValue = ref<{ name: string; count: number | string }[]>([
|
||||||
{
|
{
|
||||||
name: '执行次数',
|
name: t('workbench.homePage.executionTimes'),
|
||||||
count: '-',
|
count: '-',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
@ -114,8 +122,11 @@
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
// 接口覆盖
|
const initCoverRate = [
|
||||||
const coverData = ref<{ name: string; value: number }[]>([
|
{
|
||||||
|
value: 0,
|
||||||
|
name: t('workbench.homePage.coverRate'),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
value: 0,
|
value: 0,
|
||||||
name: t('workbench.homePage.notCover'),
|
name: t('workbench.homePage.notCover'),
|
||||||
|
@ -124,7 +135,10 @@
|
||||||
value: 0,
|
value: 0,
|
||||||
name: t('workbench.homePage.covered'),
|
name: t('workbench.homePage.covered'),
|
||||||
},
|
},
|
||||||
]);
|
];
|
||||||
|
|
||||||
|
// 接口覆盖
|
||||||
|
const coverData = ref<{ name: string; value: number }[]>(cloneDeep(initCoverRate));
|
||||||
const caseExecuteData = ref<{ name: string; value: number }[]>([
|
const caseExecuteData = ref<{ name: string; value: number }[]>([
|
||||||
{
|
{
|
||||||
value: 0,
|
value: 0,
|
||||||
|
@ -187,8 +201,49 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
const hasPermission = ref<boolean>(false);
|
const hasPermission = ref<boolean>(false);
|
||||||
|
const loading = ref<boolean>(false);
|
||||||
|
|
||||||
|
function handleCoverData(detail: ApiCoverageData) {
|
||||||
|
const { unCoverWithApiCase, coverWithApiCase, apiCaseCoverage } = detail;
|
||||||
|
const { unCoverWithApiScenario, coverWithApiScenario, scenarioCoverage } = detail;
|
||||||
|
|
||||||
|
const coverage = props.item.key === WorkCardEnum.API_CASE_COUNT ? apiCaseCoverage : scenarioCoverage;
|
||||||
|
const unCoverWithCase =
|
||||||
|
props.item.key === WorkCardEnum.API_CASE_COUNT ? unCoverWithApiCase : unCoverWithApiScenario;
|
||||||
|
|
||||||
|
const coverWithCase = WorkCardEnum.API_CASE_COUNT ? coverWithApiCase : coverWithApiScenario;
|
||||||
|
coverData.value = [
|
||||||
|
{
|
||||||
|
value: Number(coverage.split('%')[0]),
|
||||||
|
name: t('workbench.homePage.coverRate'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: unCoverWithCase,
|
||||||
|
name: t('workbench.homePage.notCover'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: coverWithCase,
|
||||||
|
name: t('workbench.homePage.covered'),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
async function initApiCountRate() {
|
||||||
|
try {
|
||||||
|
loading.value = true;
|
||||||
|
const detail = await workApiCountCoverRage(projectId.value);
|
||||||
|
handleCoverData(detail);
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function initApiOrScenarioCount() {
|
async function initApiOrScenarioCount() {
|
||||||
try {
|
try {
|
||||||
|
coverData.value = cloneDeep(initCoverRate);
|
||||||
const { startTime, endTime, dayNumber } = timeForm.value;
|
const { startTime, endTime, dayNumber } = timeForm.value;
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
|
@ -241,6 +296,7 @@
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
initApiOrScenarioCount();
|
initApiOrScenarioCount();
|
||||||
emit('change');
|
emit('change');
|
||||||
|
initApiCountRate();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,6 +304,26 @@
|
||||||
initApiOrScenarioCount();
|
initApiOrScenarioCount();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.cover,
|
||||||
|
(val) => {
|
||||||
|
if (val) {
|
||||||
|
handleCoverData(val);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deep: true,
|
||||||
|
immediate: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.status,
|
||||||
|
(val) => {
|
||||||
|
loading.value = val;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => innerProjectIds.value,
|
() => innerProjectIds.value,
|
||||||
(val) => {
|
(val) => {
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
:tooltip-text="tabItem.tooltip"
|
:tooltip-text="tabItem.tooltip"
|
||||||
:options="tabItem.options"
|
:options="tabItem.options"
|
||||||
:size="60"
|
:size="60"
|
||||||
|
:loading="tabItem.value === 'cover' ? loading : undefined"
|
||||||
:has-permission="hasPermission"
|
:has-permission="hasPermission"
|
||||||
:value-list="tabItem.valueList"
|
:value-list="tabItem.valueList"
|
||||||
/>
|
/>
|
||||||
|
@ -49,11 +50,11 @@
|
||||||
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 { workApiCountCoverRage, 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 { SelectedCardItem, TimeFormParams } from '@/models/workbench/homePage';
|
import type { ApiCoverageData, SelectedCardItem, TimeFormParams } from '@/models/workbench/homePage';
|
||||||
|
|
||||||
import { handlePieData, handleUpdateTabPie } from '../utils';
|
import { handlePieData, handleUpdateTabPie } from '../utils';
|
||||||
|
|
||||||
|
@ -63,6 +64,8 @@
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
item: SelectedCardItem;
|
item: SelectedCardItem;
|
||||||
projectIds: string[];
|
projectIds: string[];
|
||||||
|
status?: boolean;
|
||||||
|
cover?: ApiCoverageData;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
@ -73,6 +76,8 @@
|
||||||
required: true,
|
required: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const loading = ref<boolean>(false);
|
||||||
|
|
||||||
const projectId = ref<string>(innerProjectIds.value[0]);
|
const projectId = ref<string>(innerProjectIds.value[0]);
|
||||||
|
|
||||||
const timeForm = inject<Ref<TimeFormParams>>(
|
const timeForm = inject<Ref<TimeFormParams>>(
|
||||||
|
@ -93,14 +98,14 @@
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: '',
|
label: '',
|
||||||
value: 'execution',
|
value: 'cover',
|
||||||
valueList: coverValueList.value,
|
valueList: coverValueList.value,
|
||||||
options: { ...coverOptions.value },
|
options: { ...coverOptions.value },
|
||||||
tooltip: 'workbench.homePage.apiCountCoverRateTooltip',
|
tooltip: 'workbench.homePage.apiCountCoverRateTooltip',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '',
|
label: '',
|
||||||
value: 'pass',
|
value: 'complete',
|
||||||
valueList: completeValueList.value,
|
valueList: completeValueList.value,
|
||||||
options: { ...completeOptions.value },
|
options: { ...completeOptions.value },
|
||||||
tooltip: 'workbench.homePage.apiCountCompleteRateTooltip',
|
tooltip: 'workbench.homePage.apiCountCompleteRateTooltip',
|
||||||
|
@ -109,8 +114,47 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
const apiCountOptions = ref({});
|
const apiCountOptions = ref({});
|
||||||
|
|
||||||
const hasPermission = ref<boolean>(false);
|
const hasPermission = ref<boolean>(false);
|
||||||
|
function handleCoverData(detail: ApiCoverageData) {
|
||||||
|
const { unCoverWithApiDefinition, coverWithApiDefinition, apiCoverage } = detail;
|
||||||
|
const coverData: {
|
||||||
|
name: string;
|
||||||
|
count: number;
|
||||||
|
}[] = [
|
||||||
|
{
|
||||||
|
count: Number(apiCoverage.split('%')[0]),
|
||||||
|
name: t('workbench.homePage.coverRate'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
count: coverWithApiDefinition,
|
||||||
|
name: t('workbench.homePage.covered'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
count: unCoverWithApiDefinition,
|
||||||
|
name: t('workbench.homePage.notCover'),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const { options: covOptions, valueList: coverList } = handleUpdateTabPie(
|
||||||
|
coverData,
|
||||||
|
hasPermission.value,
|
||||||
|
`${props.item.key}-cover`
|
||||||
|
);
|
||||||
|
coverValueList.value = coverList;
|
||||||
|
coverOptions.value = covOptions;
|
||||||
|
}
|
||||||
|
async function initApiCountRate() {
|
||||||
|
try {
|
||||||
|
loading.value = true;
|
||||||
|
const detail = await workApiCountCoverRage(projectId.value);
|
||||||
|
handleCoverData(detail);
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function initApiCount() {
|
async function initApiCount() {
|
||||||
try {
|
try {
|
||||||
const { startTime, endTime, dayNumber } = timeForm.value;
|
const { startTime, endTime, dayNumber } = timeForm.value;
|
||||||
|
@ -127,18 +171,8 @@
|
||||||
const { statusStatisticsMap, statusPercentList, errorCode } = detail;
|
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(
|
|
||||||
// statusStatisticsMap?.cover || [],
|
|
||||||
// hasPermission.value,
|
|
||||||
// `${props.item.key}-cover`
|
|
||||||
// );
|
|
||||||
// coverValueList.value = coverList;
|
|
||||||
// coverOptions.value = covOptions;
|
|
||||||
|
|
||||||
// 完成率
|
// 完成率
|
||||||
const { options: comOptions, valueList: completedList } = handleUpdateTabPie(
|
const { options: comOptions, valueList: completedList } = handleUpdateTabPie(
|
||||||
statusStatisticsMap?.completionRate || [],
|
statusStatisticsMap?.completionRate || [],
|
||||||
|
@ -157,6 +191,7 @@
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
initApiCount();
|
initApiCount();
|
||||||
emit('change');
|
emit('change');
|
||||||
|
initApiCountRate();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,6 +200,26 @@
|
||||||
emit('change');
|
emit('change');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.cover,
|
||||||
|
(val) => {
|
||||||
|
if (val) {
|
||||||
|
handleCoverData(val);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deep: true,
|
||||||
|
immediate: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.status,
|
||||||
|
(val) => {
|
||||||
|
loading.value = val;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => innerProjectIds.value,
|
() => innerProjectIds.value,
|
||||||
(val) => {
|
(val) => {
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
</template>
|
</template>
|
||||||
<div class="setting-wrapper">
|
<div class="setting-wrapper">
|
||||||
<div class="setting-wrapper-config">
|
<div class="setting-wrapper-config">
|
||||||
<CardSettingList @add="addCard" />
|
<CardSettingList v-model:selectedIds="selectedIds" @add="addCard" />
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-wrapper-content">
|
<div class="setting-wrapper-content">
|
||||||
<!-- 布局开始 -->
|
<!-- 布局开始 -->
|
||||||
|
@ -131,8 +131,11 @@
|
||||||
|
|
||||||
const defaultAllProjectType = [WorkCardEnum.PROJECT_VIEW, WorkCardEnum.CREATE_BY_ME];
|
const defaultAllProjectType = [WorkCardEnum.PROJECT_VIEW, WorkCardEnum.CREATE_BY_ME];
|
||||||
|
|
||||||
|
const selectedIds = ref<WorkCardEnum[]>([]);
|
||||||
|
|
||||||
// 添加卡片
|
// 添加卡片
|
||||||
function addCard(item: childrenWorkConfigItem) {
|
function addCard(item: childrenWorkConfigItem) {
|
||||||
|
selectedIds.value.push(item.value);
|
||||||
const newCard: SelectedCardItem = {
|
const newCard: SelectedCardItem = {
|
||||||
id: getGenerateId(),
|
id: getGenerateId(),
|
||||||
fullScreen: !!isFullScreenType.includes(item.value),
|
fullScreen: !!isFullScreenType.includes(item.value),
|
||||||
|
@ -153,6 +156,7 @@
|
||||||
function deleteHandler(item: SelectedCardItem) {
|
function deleteHandler(item: SelectedCardItem) {
|
||||||
const index = selectedCardList.value.findIndex((e) => e.id === item.id);
|
const index = selectedCardList.value.findIndex((e) => e.id === item.id);
|
||||||
selectedCardList.value.splice(index, 1);
|
selectedCardList.value.splice(index, 1);
|
||||||
|
selectedIds.value.splice(index, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const confirmLoading = ref<boolean>(false);
|
const confirmLoading = ref<boolean>(false);
|
||||||
|
@ -183,6 +187,7 @@
|
||||||
(val) => {
|
(val) => {
|
||||||
if (val) {
|
if (val) {
|
||||||
selectedCardList.value = cloneDeep(props.list);
|
selectedCardList.value = cloneDeep(props.list);
|
||||||
|
selectedIds.value = props.list.map((e) => e.key);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -59,6 +59,10 @@
|
||||||
(e: 'add', item: childrenWorkConfigItem): void;
|
(e: 'add', item: childrenWorkConfigItem): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const innerSelectedIds = defineModel<WorkCardEnum[]>('selectedIds', {
|
||||||
|
required: true,
|
||||||
|
});
|
||||||
|
|
||||||
const configList = ref<WorkConfigCard[]>([
|
const configList = ref<WorkConfigCard[]>([
|
||||||
// 概览
|
// 概览
|
||||||
{
|
{
|
||||||
|
@ -212,17 +216,14 @@
|
||||||
const searchKeyword = ref(''); // 存储搜索关键字
|
const searchKeyword = ref(''); // 存储搜索关键字
|
||||||
|
|
||||||
const filteredConfigList = computed(() => {
|
const filteredConfigList = computed(() => {
|
||||||
if (!searchKeyword.value) {
|
return configList.value.map((item) => ({
|
||||||
return configList.value;
|
...item,
|
||||||
}
|
children: item.children.filter(
|
||||||
return configList.value
|
(child) =>
|
||||||
.map((item) => ({
|
child.label.toLowerCase().includes(searchKeyword.value.toLowerCase()) &&
|
||||||
...item,
|
!innerSelectedIds.value.includes(child.value)
|
||||||
children: item.children.filter((child) =>
|
),
|
||||||
child.label.toLowerCase().includes(searchKeyword.value.toLowerCase())
|
}));
|
||||||
),
|
|
||||||
}))
|
|
||||||
.filter((item) => item.children.length > 0);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 搜索
|
// 搜索
|
||||||
|
|
|
@ -46,7 +46,12 @@
|
||||||
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 {
|
||||||
|
workBugByMeCreated,
|
||||||
|
workBugCountDetail,
|
||||||
|
workBugHandleByMe,
|
||||||
|
workPlanLegacyBug,
|
||||||
|
} 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';
|
||||||
|
|
||||||
|
@ -93,12 +98,17 @@
|
||||||
|
|
||||||
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;
|
type SelectedBugCountKeys =
|
||||||
|
| WorkCardEnum.BUG_COUNT
|
||||||
|
| WorkCardEnum.HANDLE_BUG_BY_ME
|
||||||
|
| WorkCardEnum.CREATE_BUG_BY_ME
|
||||||
|
| WorkCardEnum.PLAN_LEGACY_BUG;
|
||||||
|
|
||||||
const currentBugCount: (data: WorkHomePageDetail) => Promise<PassRateDataType> = {
|
const currentBugCount: (data: WorkHomePageDetail) => Promise<PassRateDataType> = {
|
||||||
[WorkCardEnum.BUG_COUNT]: workBugCountDetail,
|
[WorkCardEnum.BUG_COUNT]: workBugCountDetail,
|
||||||
[WorkCardEnum.HANDLE_BUG_BY_ME]: workBugHandleByMe,
|
[WorkCardEnum.HANDLE_BUG_BY_ME]: workBugHandleByMe,
|
||||||
[WorkCardEnum.CREATE_BUG_BY_ME]: workBugByMeCreated,
|
[WorkCardEnum.CREATE_BUG_BY_ME]: workBugByMeCreated,
|
||||||
|
[WorkCardEnum.PLAN_LEGACY_BUG]: workPlanLegacyBug,
|
||||||
}[props.item.key as SelectedBugCountKeys];
|
}[props.item.key as SelectedBugCountKeys];
|
||||||
|
|
||||||
const hasPermission = ref<boolean>(false);
|
const hasPermission = ref<boolean>(false);
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- 概览图 -->
|
<!-- 概览图 -->
|
||||||
<div>
|
<div>
|
||||||
<MsChart height="300px" :options="options" />
|
<MsChart height="260px" :options="options" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -115,9 +115,11 @@
|
||||||
// x轴
|
// x轴
|
||||||
options.value.xAxis.data = cardModuleList.value.map((e) => e.label);
|
options.value.xAxis.data = cardModuleList.value.map((e) => e.label);
|
||||||
|
|
||||||
|
let maxAxis = 5;
|
||||||
|
|
||||||
// 处理data数据
|
// 处理data数据
|
||||||
options.value.series = detail.projectCountList.map((item) => {
|
options.value.series = detail.projectCountList.map((item) => {
|
||||||
const countData = item.count.map((e) => {
|
const countData: Record<string, any> = item.count.map((e) => {
|
||||||
return {
|
return {
|
||||||
name: item.name,
|
name: item.name,
|
||||||
value: e !== 0 ? e : undefined,
|
value: e !== 0 ? e : undefined,
|
||||||
|
@ -142,6 +144,11 @@
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const itemMax = Math.max(...item.count);
|
||||||
|
|
||||||
|
maxAxis = Math.max(itemMax, maxAxis);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: item.name,
|
name: item.name,
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
|
@ -154,6 +161,10 @@
|
||||||
data: countData,
|
data: countData,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
options.value.yAxis[0].max = maxAxis < 100 ? 50 : maxAxis + 50;
|
||||||
|
|
||||||
|
options.value.series[0].barGap = 4;
|
||||||
|
options.value.series[0].barCategoryGap = 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function initOverViewDetail() {
|
async function initOverViewDetail() {
|
||||||
|
@ -178,6 +189,7 @@
|
||||||
|
|
||||||
handleData(detail);
|
handleData(detail);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,11 @@
|
||||||
options.value.graphic.invisible = invisible;
|
options.value.graphic.invisible = invisible;
|
||||||
options.value.graphic.style.text = text;
|
options.value.graphic.style.text = text;
|
||||||
options.value.xAxis.data = detail.xaxis.map((e) => characterLimit(e, 10));
|
options.value.xAxis.data = detail.xaxis.map((e) => characterLimit(e, 10));
|
||||||
|
let maxAxis = 5;
|
||||||
options.value.series = detail.projectCountList.map((item, index) => {
|
options.value.series = detail.projectCountList.map((item, index) => {
|
||||||
|
const itemMax = Math.max(...item.count);
|
||||||
|
|
||||||
|
maxAxis = Math.max(itemMax, maxAxis);
|
||||||
return {
|
return {
|
||||||
name: t(contentTabList[index].label),
|
name: t(contentTabList[index].label),
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
|
@ -110,6 +114,7 @@
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
options.value.yAxis[0].max = maxAxis < 100 ? 50 : maxAxis + 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function initOverViewMemberDetail() {
|
async function initOverViewMemberDetail() {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="pass-rate-content">
|
<a-spin class="pass-rate-content" :loading="props.loading">
|
||||||
<div class="relative flex items-center justify-center">
|
<div class="relative flex items-center justify-center">
|
||||||
<a-tooltip
|
<a-tooltip
|
||||||
v-if="props.tooltipText"
|
v-if="props.tooltipText"
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
<div class="pass-rate-count">{{ hasPermission ? addCommasToNumber(item.value as number) : '-' }}</div>
|
<div class="pass-rate-count">{{ hasPermission ? addCommasToNumber(item.value as number) : '-' }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</a-spin>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -35,6 +35,7 @@
|
||||||
size: number;
|
size: number;
|
||||||
tooltipText?: string;
|
tooltipText?: string;
|
||||||
hasPermission: boolean;
|
hasPermission: boolean;
|
||||||
|
loading?: boolean;
|
||||||
valueList: {
|
valueList: {
|
||||||
label: string;
|
label: string;
|
||||||
value: number | string;
|
value: number | string;
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="rate-content relative">
|
<a-spin class="w-full" :loading="props.loading">
|
||||||
<div class="relative flex h-full w-full items-center justify-center">
|
<div class="rate-content relative">
|
||||||
<a-tooltip
|
<div class="relative flex h-full w-full items-center justify-center">
|
||||||
v-if="props.rateConfig.tooltipText"
|
<a-tooltip
|
||||||
:mouse-enter-delay="500"
|
v-if="props.rateConfig.tooltipText"
|
||||||
:content="t(props.rateConfig.tooltipText || '')"
|
:mouse-enter-delay="500"
|
||||||
position="bottom"
|
:content="t(props.rateConfig.tooltipText || '')"
|
||||||
>
|
position="bottom"
|
||||||
<div class="tooltip-rate-tooltip"></div>
|
>
|
||||||
</a-tooltip>
|
<div class="tooltip-rate-tooltip"></div>
|
||||||
<MsChart :options="options" width="146px" />
|
</a-tooltip>
|
||||||
|
<MsChart :options="options" width="146px" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</a-spin>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -28,6 +30,7 @@
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
data: { name: string; value: number }[];
|
data: { name: string; value: number }[];
|
||||||
hasPermission: boolean;
|
hasPermission: boolean;
|
||||||
|
loading?: boolean;
|
||||||
rateConfig: {
|
rateConfig: {
|
||||||
name: string;
|
name: string;
|
||||||
color: string[];
|
color: string[];
|
||||||
|
|
|
@ -94,6 +94,8 @@
|
||||||
v-model:projectIds="item.projectIds"
|
v-model:projectIds="item.projectIds"
|
||||||
:type="item.key"
|
:type="item.key"
|
||||||
:item="item"
|
:item="item"
|
||||||
|
:status="projectLoadingStatus[item.projectIds[0]]"
|
||||||
|
:cover="requestResults.get(item.projectIds[0])"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
/>
|
/>
|
||||||
<ApiChangeList
|
<ApiChangeList
|
||||||
|
@ -119,7 +121,9 @@
|
||||||
<ApiCount
|
<ApiCount
|
||||||
v-else-if="item.key === WorkCardEnum.API_COUNT"
|
v-else-if="item.key === WorkCardEnum.API_COUNT"
|
||||||
v-model:projectIds="item.projectIds"
|
v-model:projectIds="item.projectIds"
|
||||||
|
:status="projectLoadingStatus[item.projectIds[0]]"
|
||||||
:item="item"
|
:item="item"
|
||||||
|
:cover="requestResults.get(item.projectIds[0])"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
/>
|
/>
|
||||||
<TestPlanCount
|
<TestPlanCount
|
||||||
|
@ -132,8 +136,8 @@
|
||||||
</div>
|
</div>
|
||||||
<NoData
|
<NoData
|
||||||
v-if="showNoData || !appStore.projectList.length"
|
v-if="showNoData || !appStore.projectList.length"
|
||||||
:no-res-permission="!appStore.projectList.length"
|
:no-res-permission="!defaultWorkList.length"
|
||||||
:all-screen="!!appStore.projectList.length"
|
:all-screen="!!defaultWorkList.length"
|
||||||
height="h-[calc(100vh-110px)]"
|
height="h-[calc(100vh-110px)]"
|
||||||
@config="cardSetting"
|
@config="cardSetting"
|
||||||
/>
|
/>
|
||||||
|
@ -162,10 +166,11 @@
|
||||||
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 { editDashboardLayout, getDashboardLayout } from '@/api/modules/workbench';
|
import { editDashboardLayout, getDashboardLayout, workApiCountCoverRage } 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 { sleep } from '@/utils';
|
||||||
import { getLocalStorage, setLocalStorage } from '@/utils/local-storage';
|
import { getLocalStorage, setLocalStorage } from '@/utils/local-storage';
|
||||||
|
|
||||||
import { SelectedCardItem, TimeFormParams } from '@/models/workbench/homePage';
|
import { SelectedCardItem, TimeFormParams } from '@/models/workbench/homePage';
|
||||||
|
@ -260,8 +265,43 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
// 用来存储每个请求的结果,key 是项目ID
|
||||||
initDefaultList();
|
const requestResults = ref(new Map());
|
||||||
|
// 用来存储已请求过的项目
|
||||||
|
const requestedIds = ref(new Set());
|
||||||
|
|
||||||
|
const projectLoadingStatus = ref<Record<string, boolean>>({});
|
||||||
|
|
||||||
|
const fetchProjectDetails = async (projectId: string) => {
|
||||||
|
try {
|
||||||
|
projectLoadingStatus.value[projectId] = true;
|
||||||
|
const result = await workApiCountCoverRage(projectId);
|
||||||
|
requestResults.value.set(projectId, result);
|
||||||
|
projectLoadingStatus.value[projectId] = false;
|
||||||
|
await sleep(300);
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
projectLoadingStatus.value[projectId] = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 针对项目id不重复的依次请求
|
||||||
|
async function requestQueue() {
|
||||||
|
const awaitType = [WorkCardEnum.API_COUNT, WorkCardEnum.API_CASE_COUNT, WorkCardEnum.SCENARIO_COUNT];
|
||||||
|
const queueList = defaultWorkList.value.filter((item) => awaitType.includes(item.key));
|
||||||
|
for (let i = 0; i < queueList.length; i++) {
|
||||||
|
const item = queueList[i];
|
||||||
|
const [projectId] = item.projectIds;
|
||||||
|
if (!requestedIds.value.has(projectId)) {
|
||||||
|
requestedIds.value.add(projectId);
|
||||||
|
fetchProjectDetails(projectId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
const defaultTime = getLocalStorage(`WORK_TIME_${userStore.id}`);
|
const defaultTime = getLocalStorage(`WORK_TIME_${userStore.id}`);
|
||||||
if (!defaultTime) {
|
if (!defaultTime) {
|
||||||
setLocalStorage(`WORK_TIME_${userStore.id}`, JSON.stringify(timeForm.value));
|
setLocalStorage(`WORK_TIME_${userStore.id}`, JSON.stringify(timeForm.value));
|
||||||
|
@ -272,6 +312,8 @@
|
||||||
rangeTime.value = [startTime, endTime];
|
rangeTime.value = [startTime, endTime];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
await initDefaultList();
|
||||||
|
requestQueue();
|
||||||
});
|
});
|
||||||
|
|
||||||
const time = ref({ ...timeForm.value });
|
const time = ref({ ...timeForm.value });
|
||||||
|
|
|
@ -48,7 +48,7 @@ export const colorMapConfig: Record<string, string[]> = {
|
||||||
[WorkCardEnum.REVIEW_CASE_COUNT]: ['#9441B1', '#00C261', '#D4D4D8', '#3370FF'],
|
[WorkCardEnum.REVIEW_CASE_COUNT]: ['#9441B1', '#00C261', '#D4D4D8', '#3370FF'],
|
||||||
[WorkCardEnum.TEST_PLAN_COUNT]: ['#9441B1', '#3370FF', '#00C261', '#D4D4D8'],
|
[WorkCardEnum.TEST_PLAN_COUNT]: ['#9441B1', '#3370FF', '#00C261', '#D4D4D8'],
|
||||||
[WorkCardEnum.PLAN_LEGACY_BUG]: ['#9441B1', '#3370FF', '#00C261', '#D4D4D8'],
|
[WorkCardEnum.PLAN_LEGACY_BUG]: ['#9441B1', '#3370FF', '#00C261', '#D4D4D8'],
|
||||||
[WorkCardEnum.BUG_COUNT]: ['#FFA200', '#00C261', '#D4D4D8'],
|
[WorkCardEnum.BUG_COUNT]: ['#FFA200', '#D4D4D8', '#00C261'],
|
||||||
[WorkCardEnum.HANDLE_BUG_BY_ME]: ['#9441B1', '#3370FF', '#00C261', '#D4D4D8'],
|
[WorkCardEnum.HANDLE_BUG_BY_ME]: ['#9441B1', '#3370FF', '#00C261', '#D4D4D8'],
|
||||||
[WorkCardEnum.CREATE_BY_ME]: ['#9441B1', '#3370FF', '#00C261', '#D4D4D8'],
|
[WorkCardEnum.CREATE_BY_ME]: ['#9441B1', '#3370FF', '#00C261', '#D4D4D8'],
|
||||||
[WorkCardEnum.API_COUNT]: ['#811FA3', '#00C261', '#3370FF', '#FFA1FF', '#EE50A3', '#FF9964', '#F9F871', '#C3DD40'],
|
[WorkCardEnum.API_COUNT]: ['#811FA3', '#00C261', '#3370FF', '#FFA1FF', '#EE50A3', '#FF9964', '#F9F871', '#C3DD40'],
|
||||||
|
@ -71,6 +71,7 @@ export function getCommonBarOptions(hasRoom: boolean, color: string[]): Record<s
|
||||||
enterable: true,
|
enterable: true,
|
||||||
axisPointer: {
|
axisPointer: {
|
||||||
type: 'shadow',
|
type: 'shadow',
|
||||||
|
axis: 'auto',
|
||||||
},
|
},
|
||||||
formatter(params: any) {
|
formatter(params: any) {
|
||||||
const html = `
|
const html = `
|
||||||
|
@ -81,7 +82,7 @@ export function getCommonBarOptions(hasRoom: boolean, color: string[]): Record<s
|
||||||
<div class="flex h-[18px] items-center justify-between">
|
<div class="flex h-[18px] items-center justify-between">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="mb-[2px] mr-[8px] h-[8px] w-[8px] rounded-sm" style="background:${item.color}"></div>
|
<div class="mb-[2px] mr-[8px] h-[8px] w-[8px] rounded-sm" style="background:${item.color}"></div>
|
||||||
<div class="one-line-text max-w-[120px]" style="color:#959598">${item.seriesName}</div>
|
<div class="one-line-text max-w-[100px]" style="color:#959598">${item.seriesName}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-[#323233] font-medium">${addCommasToNumber(item.value)}</div>
|
<div class="text-[#323233] font-medium">${addCommasToNumber(item.value)}</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -123,9 +124,14 @@ export function getCommonBarOptions(hasRoom: boolean, color: string[]): Record<s
|
||||||
},
|
},
|
||||||
yAxis: [
|
yAxis: [
|
||||||
{
|
{
|
||||||
type: 'log',
|
type: 'value',
|
||||||
name: t('workbench.homePage.unit'), // 设置单位
|
name: t('workbench.homePage.unit'), // 设置单位
|
||||||
position: 'left',
|
position: 'left',
|
||||||
|
axisLine: {
|
||||||
|
show: false,
|
||||||
|
onZero: false, // 禁止 Y 轴强制显示在 0 位置
|
||||||
|
},
|
||||||
|
offset: 0, // 第一个 Y 轴默认位置
|
||||||
nameTextStyle: {
|
nameTextStyle: {
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: '#AEAEB2', // 自定义字体大小和颜色
|
color: '#AEAEB2', // 自定义字体大小和颜色
|
||||||
|
@ -141,6 +147,7 @@ export function getCommonBarOptions(hasRoom: boolean, color: string[]): Record<s
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
min: 1,
|
min: 1,
|
||||||
|
max: 0,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
graphic: {
|
graphic: {
|
||||||
|
|
Loading…
Reference in New Issue