refactor(工作台): 重构工作台首页项目概览和我创建的卡片调整人员概览交互调整

This commit is contained in:
xinxin.wu 2024-11-26 18:48:07 +08:00 committed by 刘瑞斌
parent 555f9845c4
commit 3723d803ad
5 changed files with 115 additions and 149 deletions

View File

@ -349,15 +349,6 @@ export default defineComponent(
} }
}); });
watch(
() => props.defaultAllSelect,
(val) => {
if (val) {
handleSelectAllChange(true);
}
}
);
// 检测全选状态变化,全选时需要覆盖选择器的输入框内容,展示文本 ‘全部’;非全选时则移除文本 ‘全部’ // 检测全选状态变化,全选时需要覆盖选择器的输入框内容,展示文本 ‘全部’;非全选时则移除文本 ‘全部’
watchEffect(() => { watchEffect(() => {
const innerDom = selectRef.value?.$el.nextElementSibling.querySelector('.arco-select-view-inner') as HTMLElement; const innerDom = selectRef.value?.$el.nextElementSibling.querySelector('.arco-select-view-inner') as HTMLElement;

View File

@ -20,7 +20,6 @@
> >
</MsSelect> </MsSelect>
<MsSelect <MsSelect
:key="props.refreshKey"
v-model:model-value="innerHandleUsers" v-model:model-value="innerHandleUsers"
:options="memberOptions" :options="memberOptions"
allow-clear allow-clear
@ -215,7 +214,8 @@
if (val) { if (val) {
innerProjectIds.value = [val]; innerProjectIds.value = [val];
} }
} },
{ immediate: true }
); );
watch( watch(

View File

@ -55,7 +55,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 { characterLimit } from '@/utils';
import type { import type {
ModuleCardItem, ModuleCardItem,
@ -63,9 +63,9 @@
SelectedCardItem, SelectedCardItem,
TimeFormParams, TimeFormParams,
} from '@/models/workbench/homePage'; } from '@/models/workbench/homePage';
import { WorkCardEnum, WorkOverviewEnum } from '@/enums/workbenchEnum'; import { WorkCardEnum } from '@/enums/workbenchEnum';
import { getColorScheme, getCommonBarOptions, handleNoDataDisplay } from '../utils'; import { getColorScheme, getCommonBarOptions, getSeriesData, handleNoDataDisplay } from '../utils';
const { t } = useI18n(); const { t } = useI18n();
@ -114,85 +114,26 @@
function handleData(detail: OverViewOfProject) { function handleData(detail: OverViewOfProject) {
// //
const tempAxisData = detail.xaxis.map((xAxisKey) => { cardModuleList.value = contentTabList
const data = contentTabList.find((e) => e.value === xAxisKey); .map((item) => {
return { return {
...data, ...item,
label: t(data?.label || ''), label: t(item.label),
count: detail.caseCountMap[xAxisKey as WorkOverviewEnum], count: detail.caseCountMap[item.value],
}; };
}); })
.filter((e) => Object.keys(detail.caseCountMap).includes(e.value as string));
cardModuleList.value = tempAxisData as ModuleCardItem[];
options.value = getCommonBarOptions(hasRoom.value, getColorScheme(detail.projectCountList.length)); options.value = getCommonBarOptions(hasRoom.value, getColorScheme(detail.projectCountList.length));
const { invisible, text } = handleNoDataDisplay(detail.xaxis, hasPermission.value); const { invisible, text } = handleNoDataDisplay(detail.xaxis, hasPermission.value);
options.value.graphic.invisible = invisible; options.value.graphic.invisible = invisible;
options.value.graphic.style.text = text; options.value.graphic.style.text = text;
// x // x
options.value.xAxis.data = cardModuleList.value.map((e) => e.label); options.value.xAxis.data = detail.xaxis.map((e) => characterLimit(e, 10));
let maxAxis = 5; const { maxAxis, data } = getSeriesData(detail.projectCountList);
options.value.series = data;
// data options.value.yAxis[0].max = maxAxis;
options.value.series = detail.projectCountList.map((item) => {
const countData: Record<string, any>[] = item.count.map((e) => {
return {
name: item.name,
value: e,
originValue: e,
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;
},
},
};
});
const itemMax = Math.max(...item.count);
maxAxis = Math.max(itemMax, maxAxis);
return {
name: item.name,
type: 'bar',
barWidth: 12,
legendHoverLink: true,
large: true,
itemStyle: {
borderRadius: [2, 2, 0, 0], //
},
z: 10,
data: countData,
barMinHeight: ((optionData: Record<string, any>[]) => {
optionData.forEach((itemValue: any, index: number) => {
if (itemValue.value === 0) optionData[index].value = null;
});
let hasZero = false;
for (let i = 0; i < optionData.length; i++) {
if (optionData[i].value === 0) {
hasZero = true;
break;
}
}
return hasZero ? 0 : 5;
})(countData),
};
});
options.value.yAxis[0].max = maxAxis < 100 ? 100 : maxAxis + 50;
} }
const showSkeleton = ref(false); const showSkeleton = ref(false);
const selectAll = computed(() => appStore.projectList.length === innerProjectIds.value.length); const selectAll = computed(() => appStore.projectList.length === innerProjectIds.value.length);

View File

@ -16,12 +16,10 @@
:search-keys="['name']" :search-keys="['name']"
class="!w-[200px]" class="!w-[200px]"
:prefix="t('workbench.homePage.project')" :prefix="t('workbench.homePage.project')"
@change="changeProject"
> >
</MsSelect> </MsSelect>
<MsSelect <MsSelect
:key="props.refreshKey"
v-model:model-value="innerHandleUsers" v-model:model-value="innerHandleUsers"
:options="memberOptions" :options="memberOptions"
allow-search allow-search
@ -58,14 +56,13 @@
import CardSkeleton from './cardSkeleton.vue'; import CardSkeleton from './cardSkeleton.vue';
import { workMemberViewDetail, workProjectMemberOptions } from '@/api/modules/workbench'; import { workMemberViewDetail, workProjectMemberOptions } from '@/api/modules/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 { characterLimit, sleep } from '@/utils'; import { characterLimit, sleep } from '@/utils';
import type { OverViewOfProject, SelectedCardItem, TimeFormParams } from '@/models/workbench/homePage'; import type { OverViewOfProject, SelectedCardItem, TimeFormParams } from '@/models/workbench/homePage';
import { getCommonBarOptions, handleNoDataDisplay } from '../utils'; import { getColorScheme, getCommonBarOptions, getSeriesData, handleNoDataDisplay } from '../utils';
const { t } = useI18n(); const { t } = useI18n();
const appStore = useAppStore(); const appStore = useAppStore();
@ -100,57 +97,18 @@
const memberOptions = ref<{ label: string; value: string }[]>([]); const memberOptions = ref<{ label: string; value: string }[]>([]);
const options = ref<Record<string, any>>({}); const options = ref<Record<string, any>>({});
const color = ['#811FA3', '#FFCA59', '#00C261', '#FFA1FF', '#F9F871', '#3370FF', '#F24F4F'];
function handleData(detail: OverViewOfProject) { function handleData(detail: OverViewOfProject) {
options.value = getCommonBarOptions(detail.xaxis.length >= 7, color); options.value = getCommonBarOptions(detail.xaxis.length >= 7, getColorScheme(7));
const { invisible, text } = handleNoDataDisplay(detail.xaxis, hasPermission.value); const { invisible, text } = handleNoDataDisplay(detail.xaxis, hasPermission.value);
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; const { maxAxis, data } = getSeriesData(detail.projectCountList);
// data options.value.series = data;
options.value.series = detail.projectCountList.map((item, sid) => { options.value.yAxis[0].max = maxAxis;
const countData: Record<string, any>[] = item.count.map((e) => {
return {
name: item.name,
value: e,
originValue: e,
};
});
const itemMax = Math.max(...item.count);
maxAxis = Math.max(itemMax, maxAxis);
return {
name: t(contentTabList[sid].label),
type: 'bar',
barWidth: 12,
legendHoverLink: true,
large: true,
itemStyle: {
borderRadius: [2, 2, 0, 0],
},
data: countData,
barMinHeight: ((optionData: Record<string, any>[]) => {
optionData.forEach((itemValue: any, index: number) => {
if (itemValue.value === 0) optionData[index].value = null;
});
let hasZero = false;
for (let i = 0; i < optionData.length; i++) {
if (optionData[i].value === 0) {
hasZero = true;
break;
}
}
return hasZero ? 0 : 5;
})(countData),
};
});
options.value.yAxis[0].max = maxAxis < 100 ? 100 : maxAxis + 50;
} }
const showSkeleton = ref(false); const showSkeleton = ref(false);
@ -187,21 +145,16 @@
label: e.name, label: e.name,
value: e.id, value: e.id,
})); }));
innerHandleUsers.value = innerHandleUsers.value.filter((id: string) =>
memberOptions.value.some((member) => member.value === id)
);
} }
const isInit = ref(true); const isInit = ref(true);
function changeProject() { function changeMember(value: string[]) {
innerHandleUsers.value = [];
nextTick(() => {
getMemberOptions();
initOverViewMemberDetail();
emit('change');
});
}
function changeMember() {
nextTick(() => { nextTick(() => {
initOverViewMemberDetail(); initOverViewMemberDetail();
innerHandleUsers.value = value;
emit('change'); emit('change');
}); });
} }
@ -241,19 +194,26 @@
onMounted(() => { onMounted(() => {
isInit.value = false; isInit.value = false;
initOverViewMemberDetail();
if (props.item.projectIds.length) { if (props.item.projectIds.length) {
getMemberOptions(); getMemberOptions();
} }
initOverViewMemberDetail();
}); });
watch([() => props.refreshKey, () => projectId.value], async () => { watch([() => props.refreshKey, () => projectId.value], async ([_key, newProjectId]) => {
await nextTick(); await nextTick();
initOverViewMemberDetail();
await sleep(50); if (newProjectId) {
innerHandleUsers.value = [];
emit('change');
}
if (props.item.projectIds.length) { if (props.item.projectIds.length) {
getMemberOptions(); getMemberOptions();
} }
await sleep(50);
initOverViewMemberDetail();
}); });
</script> </script>

View File

@ -1,17 +1,18 @@
import { cloneDeep } from 'lodash-es'; import { cloneDeep } from 'lodash-es';
import { toolTipConfig } from '@/config/testPlan'; import { toolTipConfig } from '@/config/testPlan';
import { commonRatePieOptions, defaultValueMap } from '@/config/workbench'; import { commonRatePieOptions, contentTabList, defaultValueMap } from '@/config/workbench';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
import { addCommasToNumber } from '@/utils'; import { addCommasToNumber } from '@/utils';
import { WorkCardEnum } from '@/enums/workbenchEnum'; import { WorkCardEnum } from '@/enums/workbenchEnum';
const { t } = useI18n(); const { t } = useI18n();
// 通用颜色配置 // TODO 通用颜色配置注: 目前柱状图只用到了7种色阶其他色阶暂时保留
const commonColorConfig: Record<number, string[]> = { const commonColorConfig: Record<number, string[]> = {
2: ['#783887', '#FFC14E'], 2: ['#783887', '#FFC14E'],
4: ['#783887', '#FFC14E', '#2DFCEF', '#3370FF'], 4: ['#783887', '#FFC14E', '#2DFCEF', '#3370FF'],
7: ['#811FA3', '#00C261', '#FF9964', '#50CEFB', '#EE50A3', '#3370FF', '#D34400'],
8: ['#783887', '#FFC14E', '#2DFCEF', '#3370FF', '#811FA3', '#00D1FF', '#FFA53D', '#00C261'], 8: ['#783887', '#FFC14E', '#2DFCEF', '#3370FF', '#811FA3', '#00D1FF', '#FFA53D', '#00C261'],
12: [ 12: [
'#AA4FBF', '#AA4FBF',
@ -55,6 +56,7 @@ const commonColorConfig: Record<number, string[]> = {
export function getColorScheme(dataLength: number): string[] { export function getColorScheme(dataLength: number): string[] {
if (dataLength <= 2) return commonColorConfig[2]; if (dataLength <= 2) return commonColorConfig[2];
if (dataLength <= 4) return commonColorConfig[4]; if (dataLength <= 4) return commonColorConfig[4];
if (dataLength <= 7) return commonColorConfig[7];
if (dataLength <= 8) return commonColorConfig[8]; if (dataLength <= 8) return commonColorConfig[8];
if (dataLength <= 12) return commonColorConfig[12]; if (dataLength <= 12) return commonColorConfig[12];
return commonColorConfig[13]; return commonColorConfig[13];
@ -543,3 +545,75 @@ export function handleUpdateTabPie(
options, options,
}; };
} }
export function getSeriesData(
projectCountList: {
id: string;
name: string;
count: number[];
}[]
) {
let maxAxis = 5;
const seriesData = projectCountList.map((item, sid) => {
const countData: Record<string, any>[] = item.count.map((e) => {
return {
name: t(contentTabList[sid].label),
value: e,
originValue: e,
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;
},
},
};
});
const itemMax = Math.max(...item.count);
maxAxis = Math.max(itemMax, maxAxis);
return {
name: t(contentTabList[sid].label),
type: 'bar',
barWidth: 12,
legendHoverLink: true,
large: true,
itemStyle: {
borderRadius: [2, 2, 0, 0],
},
data: countData,
barMinHeight: ((optionData: Record<string, any>[]) => {
optionData.forEach((itemValue: any, index: number) => {
if (itemValue.value === 0) optionData[index].value = null;
});
let hasZero = false;
for (let i = 0; i < optionData.length; i++) {
if (optionData[i].value === 0) {
hasZero = true;
break;
}
}
return hasZero ? 0 : 5;
})(countData),
};
});
return {
data: seriesData,
maxAxis: maxAxis < 100 ? 100 : maxAxis + 50,
};
}