<template>
<div>
<div class="chart-table-box">
<div class="pie-box">
<div id="echarts" ref="chartDom" class="chart-body"></div>
<div class="sixText" @click="openDialog">
<div class="sixtext-number">
<p class="total-asset-num-span">
{{ showList.total || showList.total === 0 ? showList.total : '--' }}
</p>
<p>{{ showList.title }}</p>
</div>
</div>
</div>
<div class="lenged-box">
<div class="header-box">
<div
v-for="(item, index) in showList.header"
:key="index"
class="header"
>
<el-tooltip
class="box-item"
effect="dark"
:content="item.label"
placement="top-end"
>
{{ item.label }}
</el-tooltip>
</div>
</div>
<div class="list-box">
<div v-for="(item, index) in showList.list" :key="index" class="list">
<el-tooltip
class="box-item"
effect="dark"
:content="item.name"
placement="top-end"
>
<div class="list-item">
<div class="name-icon" :style="{ backgroundColor: getColor(index) }"></div>
<span class="name-title">{{ item.name }}</span>
</div>
</el-tooltip>
<div class="list-item list-value">
{{ item.value }}
</div>
<div v-if="item.num || item.num===0" class="list-item list-num">
{{ item.num }}
</div>
<!-- 新增设备数量和配件数量 -->
<div v-if="item.equipmentCount || item.equipmentCount === 0" class="list-item list-num">
{{ item.equipmentCount }}
</div>
<div v-if="item.componentCount || item.componentCount === 0" class="list-item list-num">
{{ item.componentCount }}
</div>
</div>
</div>
</div>
</div>
</div>
<PopupTable
v-model:page-size="page.pageSize"
v-model:page-no="page.pageNo"
:dialog-visible="dialogVisible"
:dialog-title="dialogTitle"
:dialog-columns="dialogColumns"
:dialog-data="dialogData"
:total="page.total"
:loading="loading"
@refresh="openDialog"
></PopupTable>
</template>
<script lang="ts" setup>
import { ref, defineProps, defineEmits, watch, computed, nextTick } from 'vue';
import * as echarts from 'echarts';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
import PopupTable from './PopupTable';
import { queryOfflineAssetInfo } from '@/apis/dcPhysicalAPIS';
import { usePropertyMetricsManager } from '@/application/core/infra-layout/composables/usePropertyMetricsManager';
import { useMapLevelDataManager } from '@/application/core/infra-layout/composables/useMapLevelDataManager';
const propertyMetricsManager = usePropertyMetricsManager();
const mapLevelDataManagerStore = useMapLevelDataManager();
const mapLevelDataManager = computed(() => mapLevelDataManagerStore);
const mapLevelCode = computed(() => mapLevelDataManager.value.getMapLevelCode());
const currentSelectOption = computed(() => {
const { areaCode, cityCode, campusCode, dcCode, roomBuilding, floorCode } = mapLevelCode.value;
return [areaCode, cityCode, campusCode, dcCode, roomBuilding, floorCode].filter(Boolean);
});
const props = defineProps({
dataList: {
type: Object,
default: () => {
},
},
currentTab: {
type: String,
default: 'inventoryDiscrepancy',
},
});
const loading = ref(false);
const emit = defineEmits(['update']);
const colorList = [
'#c23531',
'#2f4554',
'#61a0a8',
'#d48265',
'#749f83',
'#ca8622',
'#bda29a',
'#6e7074',
'#546570',
'#c4ccd3',
];
const getColor = (index: number) => colorList[index % colorList.length];
// 获取echart挂载的DOM节点
const chartDom = ref();
// 使用 computed 自动同步 props 到本地响应式数据
const showList = computed(() => props.dataList);
let myChart = null;
const option = {
title: {
zlevel: 0,
text: '',
left: '50%',
top: '50%',
textAlign: 'center',
textStyle: {
fontSize: 12,
rich: {
value: {
fontWeight: 'bold',
lineHeight: 30,
fontSize: 18,
},
name: {
fontWeight: 'normal',
color: '#626879',
},
},
},
},
tooltip: {
trigger: 'item',
position: 'right',
formatter: '{b} : {c} ({d}%)',
},
color: colorList,
series: [
{
name: '',
type: 'pie',
radius: ['50%', '60%'],
center: ['50%', '50%'],
avoidLabelOverlap: false,
label: {
show: false,
position: 'center',
formatter: '',
},
emphasis: {
label: {
show: true,
fontSize: 12,
fontWeight: 'bold',
},
},
labelLine: {
show: false,
},
data: [],
},
],
};
const drawChart = () => {
let myChart = (echarts as any).init(chartDom.value);
myChart.clear();
let seriesData = [];
showList.value &&
showList.value &&
showList.value.list &&
showList.value.list.forEach(item => {
let obj = {
name: item.name,
value: item.value,
};
seriesData.push(obj);
});
option.series[0].data = seriesData;
myChart.setOption(option);
};
watch(
() => props.dataList,
() => {
nextTick(() => {
drawChart();
});
},
{ immediate: true, deep: true },
);
// 弹窗相关
const dialogVisible = ref(false);
const dialogTitle = ref('');
const dialogColumns = ref([]);
const dialogData = ref([]);
const page = ref({
pageNo: 1,
pageSize: 10,
total: 0,
});
// 处理多选
const handleCondition = condition => {
const multipleNames = [...propertyMetricsManager.multipleNames].map(i => i.value);
const cityMultipleNames = [...propertyMetricsManager.multipleNames].map(i => i.name);
if (!multipleNames.length) {
return;
}
if (['China', 'Abroad', 'global'].includes(mapLevelDataManager.value.level)) {
Reflect.set(condition.value, 'area', cityMultipleNames);
}
if (mapLevelDataManager.value.level === 'area') {
Reflect.set(condition.value, 'city', cityMultipleNames);
}
if (mapLevelDataManager.value.level === 'city') {
Reflect.set(condition.value, 'campusCode', multipleNames);
}
if (mapLevelDataManager.value.level === 'campus') {
Reflect.set(condition.value, 'buildingCode', multipleNames);
}
};
const getDetailCondition = condition => {
if (mapLevelCode.value.country === 'China') {
Reflect.set(condition.value, 'country', '中国');
} else if (mapLevelCode.value.country === 'Abroad') {
Reflect.set(condition.value, 'country', '海外');
} else {
Reflect.set(condition.value, 'country', '');
}
};
// 单选
const getDetailReflect = condition => {
if (currentSelectOption.value && currentSelectOption.value.length) {
if (mapLevelDataManager.value.level === 'area') {
Reflect.set(condition.value, 'area', [currentSelectOption.value[0]]);
} else if (mapLevelDataManager.value.level === 'city') {
let city = '';
for (let item of mapLevelDataManager.value.campusData) {
if (item.city_code === currentSelectOption.value[1]) {
city = item.city;
}
}
Reflect.set(condition.value, 'city', [city]);
} else if (mapLevelDataManager.value.level === 'campus') {
Reflect.set(condition.value, 'campusCode', [currentSelectOption.value[2]]);
} else if (mapLevelDataManager.value.level === 'dc') {
Reflect.set(condition.value, 'dcCode', [currentSelectOption.value[3]]);
Reflect.set(condition.value, 'building', currentSelectOption.value[4]);
} else {
}
} else {
Reflect.set(condition.value, 'area', []);
Reflect.set(condition.value, 'city', []);
Reflect.set(condition.value, 'campusCode', []);
Reflect.set(condition.value, 'dcCode', []);
Reflect.set(condition.value, 'building', '');
}
};
const fetchData = async(type: string, columns: any[]) => {
dialogColumns.value = columns;
const condition = ref({});
getDetailCondition(condition);
getDetailReflect(condition);
handleCondition(condition);
const params = {
condition: condition.value,
pageNo: page.value.pageNo,
pageSize: page.value.pageSize,
type,
};
try {
const res = await queryOfflineAssetInfo(params);
dialogData.value = res?.data || [];
page.value.total = res?.total || 0;
} catch (error) {
dialogData.value = [];
}
};
const openDialog = async(pageNo = 1) => {
dialogVisible.value = true;
loading.value = true;
page.value.pageNo = pageNo;
const { currentTab } = props;
switch (currentTab) {
case 'noSecurityAgreement':
dialogTitle.value = '无保全协议详情';
await fetchData('no_preservation_agreement', [
{ title: t('日期'), field: 'date', width: 150, visible: true },
{ title: t('国家'), field: 'country', width: 120, visible: true },
{ title: t('区域'), field: 'area', width: 120, visible: true },
{ title: t('城市'), field: 'city', width: 120, visible: true },
{ title: t('园区编码'), field: 'campusCode', width: 120, visible: true },
{ title: t('园区名称'), field: 'campusName', width: 130, visible: true },
{ title: t('DC编码'), field: 'dcCode', width: 130, visible: true },
{ title: t('楼栋(DC)'), field: 'dcName', width: 130, visible: true },
{ title: t('DC全称'), field: 'dcFullName', width: 130, visible: true },
{ title: t('保全协议'), field: 'preservationAgreement', width: 130, visible: true },
{ title: t('云业务子类型'), field: 'cloudServiceSubtype', width: 130, visible: true },
{ title: t('状态'), field: 'status', width: 130, visible: true },
{ title: t('业务标签'), field: 'businessLabel', width: 130, visible: true },
{ title: t('业务类型'), field: 'businessType', width: 130, visible: true },
{ title: t('数据中心类型'), field: 'dcType', width: 130, visible: true },
{ title: t('所属用户组'), field: 'userGroup', width: 130, visible: true },
{ title: t('L2资产管理员'), field: 'levelTwoAssetManager', width: 130, visible: true },
{ title: t('描述'), field: 'desc', width: 130, visible: true },
]);
break;
case 'solutionNotCovered':
dialogTitle.value = '未覆盖解决方案详情';
await fetchData('no_solution', [
{ title: t('日期'), field: 'date', width: 150, visible: true },
{ title: t('国家'), field: 'country', width: 120, visible: true },
{ title: t('区域'), field: 'area', width: 120, visible: true },
{ title: t('城市'), field: 'city', width: 120, visible: true },
{ title: t('园区编码'), field: 'campusCode', width: 120, visible: true },
{ title: t('园区名称'), field: 'campusName', width: 130, visible: true },
{ title: t('DC编码'), field: 'dcCode', width: 130, visible: true },
{ title: t('楼栋(DC)'), field: 'dcName', width: 130, visible: true },
{ title: t('DC全称'), field: 'dcFullName', width: 130, visible: true },
{ title: t('所在大楼'), field: 'building', width: 130, visible: true },
{ title: t('楼层'), field: 'floor', width: 130, visible: true },
{ title: t('房间简称/别名'), field: 'room', width: 130, visible: true },
{ title: t('房间编码'), field: 'roomCode', width: 130, visible: true },
{ title: t('房间名称'), field: 'roomName', width: 130, visible: true },
{ title: t('状态'), field: 'status', width: 130, visible: true },
{ title: t('解决方案状态'), field: 'solutionStatus', width: 130, visible: true },
{ title: t('库房类型'), field: 'warehouseType', width: 130, visible: true },
{ title: t('库房方案'), field: 'warehouseSolution', width: 130, visible: true },
{ title: t('库房方案状态'), field: 'warehouseSolutionStatus', width: 130, visible: true },
{ title: t('设备资产总数'), field: 'equipmentTotalCount', width: 130, visible: true },
{ title: t('配件资产总数'), field: 'componentTotalCount', width: 130, visible: true },
{ title: t('场地类型'), field: 'machineRoomType', width: 130, visible: true },
{ title: t('所属大区'), field: 'region', width: 130, visible: true },
{ title: t('所在省/州'), field: 'province', width: 130, visible: true },
{ title: t('云服务分类'), field: 'cloudServiceCategory', width: 130, visible: true },
{ title: t('面积'), field: 'placeArea', width: 130, visible: true },
{ title: t('是否有资产'), field: 'haveAsset', width: 130, visible: true },
]);
break;
case 'solutionDeployment':
dialogTitle.value = '解决方案部署中详情';
await fetchData('solution_deploying', [
{ title: t('日期'), field: 'date', width: 150, visible: true },
{ title: t('国家'), field: 'country', width: 120, visible: true },
{ title: t('区域'), field: 'area', width: 120, visible: true },
{ title: t('城市'), field: 'city', width: 120, visible: true },
{ title: t('园区编码'), field: 'campusCode', width: 120, visible: true },
{ title: t('园区名称'), field: 'campusName', width: 130, visible: true },
{ title: t('DC编码'), field: 'dcCode', width: 130, visible: true },
{ title: t('楼栋(DC)'), field: 'dcName', width: 130, visible: true },
{ title: t('DC全称'), field: 'dcFullName', width: 130, visible: true },
{ title: t('所在大楼'), field: 'building', width: 130, visible: true },
{ title: t('楼层'), field: 'floor', width: 130, visible: true },
{ title: t('房间简称/别名'), field: 'room', width: 130, visible: true },
{ title: t('房间编码'), field: 'roomCode', width: 130, visible: true },
{ title: t('房间名称'), field: 'roomName', width: 130, visible: true },
{ title: t('状态'), field: 'status', width: 130, visible: true },
{ title: t('解决方案状态'), field: 'solutionStatus', width: 130, visible: true },
{ title: t('库房类型'), field: 'warehouseType', width: 130, visible: true },
{ title: t('库房方案'), field: 'warehouseSolution', width: 130, visible: true },
{ title: t('库房方案状态'), field: 'warehouseSolutionStatus', width: 130, visible: true },
{ title: t('设备资产总数'), field: 'equipmentTotalCount', width: 130, visible: true },
{ title: t('配件资产总数'), field: 'componentTotalCount', width: 130, visible: true },
{ title: t('场地类型'), field: 'machineRoomType', width: 130, visible: true },
{ title: t('所属大区'), field: 'region', width: 130, visible: true },
{ title: t('所在省/州'), field: 'province', width: 130, visible: true },
{ title: t('云服务分类'), field: 'cloudServiceCategory', width: 130, visible: true },
{ title: t('面积'), field: 'placeArea', width: 130, visible: true },
{ title: t('是否有资产'), field: 'haveAsset', width: 130, visible: true },
]);
break;
default:
dialogVisible.value = false; // 防止非法 tab 打开弹窗
}
};
</script>
<style lang="less" scoped>
.chart-table-box {
width: 100%;
height: 100%;
display: flex;
font-size: 14px;
height: 250px;
.pie-box {
position: relative;
width: 174px;
height: 250px;
.chart-body {
width: 174px;
height: 250px;
}
.sixText {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
color: #606266;
font-size: 12px;
cursor: pointer;
.total-asset-num-span {
font-size: 16px;
color: #000;
font-weight: 600;
}
}
}
.lenged-box {
padding: 20px 5px 20px 10px;
width: calc(100% - 174px);
height: 100%;
float: left;
align-content: center;
.header-box {
display: flex;
.header {
flex: 1;
color: #606266;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: right;
&:first-child {
text-align: left;
}
}
}
.list-box {
overflow-y: auto;
max-height: calc(100% - 40px);
.list {
display: flex;
line-height: 24px;
justify-content: space-between;
.list-item {
width: 33%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.name-icon {
height: 8px;
width: 8px;
display: inline-block;
border-radius: 5px;
margin-right: 4px;
}
.name-title {
margin-left: 4px;
}
}
.list-num {
color: #606266;
text-align: right;
}
.list-value {
padding-right: 20px;
text-align: right;
}
}
}
}
}
.dark {
.chart-table-box {
.pie-box {
.sixText {
color: #dfe1e6;
.total-asset-num-span {
color: #dfe1e6;
}
}
}
.lenged-box {
.header-box {
.header {
color: #dfe1e6;
}
}
.list-box {
.list {
.list-num {
color: #dfe1e6;
}
}
}
}
}
}
:deep(.el-dialog) {
display: block !important;
z-index: 9999;
}
</style>
还是传参页数那里有问题,再查看一下代码