@alicloud/cloud-charts
Version:

356 lines (345 loc) • 20 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import React, { useState, useEffect, useMemo, useRef } from 'react';
import themes from '../../../themes';
import { PrefixName } from '../../../constants';
import { getStatistics, filterLegend, highlightLegend, clearHighlight } from '../../../common/chartRefs';
import { getItemData } from '../../../common/rectLegend';
import { customFormatter, getFormatConfig } from '../../../common/common';
import WidgetsTooltip from '../../../common/Tooltip';
import LegendMarker from '../../../common/LegendMarker';
import { getText } from '../../../ChartProvider';
import { calcTextWidth } from '../../../common/ellipsisLabel';
import "./index.css";
var prefix = PrefixName + "-table-legend";
export default function TableLegend(_ref) {
var _config$table2, _config$table2$custom, _widgetsCtx$legendSiz, _widgetsCtx$legendSiz2, _widgetsCtx$props$con, _widgetsCtx$props, _config$table4, _config$table6, _config$table8, _config$table9, _config$table10, _config$table11, _config$table12;
var config = _ref.config,
chart = _ref.chart,
_ref$legendItems = _ref.legendItems,
legendItems = _ref$legendItems === void 0 ? [] : _ref$legendItems;
// @ts-ignore
var widgetsCtx = chart.widgetsCtx;
var hoverable = config.hoverable,
clickable = config.clickable,
itemName = config.itemName,
useReverseChecked = config.useReverseChecked;
var _useState = useState(''),
activedItem = _useState[0],
setActivedItem = _useState[1];
var _useState2 = useState([]),
filteredItems = _useState2[0],
setFilteredItems = _useState2[1];
var legendField = (widgetsCtx === null || widgetsCtx === void 0 ? void 0 : widgetsCtx.legendField) || 'type';
var position = config.position.split('-')[0];
var statistics = useMemo(function () {
var _config$table;
return (config === null || config === void 0 ? void 0 : (_config$table = config.table) === null || _config$table === void 0 ? void 0 : _config$table.statistics) || [];
}, [config === null || config === void 0 ? void 0 : config.table]);
// 目前暂时对多重圆环进行特殊处理,待规则统一梳理后,整理数据类型
var dataType = widgetsCtx.chartName === 'G2MultiPie' ? 'treeNode' : 'common';
var statisticsRes = useMemo(function () {
return getStatistics(chart, statistics, legendField, dataType);
}, [chart, statistics, config, legendItems]);
var updateItems = useMemo(function () {
var newItems = legendItems;
if (dataType === 'treeNode') {
var _chart$options$data, _chart$options, _filterData$filter, _filterData$filter2;
var filterData = [].concat((_chart$options$data = chart === null || chart === void 0 ? void 0 : (_chart$options = chart.options) === null || _chart$options === void 0 ? void 0 : _chart$options.data) !== null && _chart$options$data !== void 0 ? _chart$options$data : []);
var firstDepthCount = (_filterData$filter = filterData.filter(function (sub) {
return sub.depth === 1;
})) === null || _filterData$filter === void 0 ? void 0 : _filterData$filter.length;
var secondDepthCount = (_filterData$filter2 = filterData.filter(function (sub) {
return sub.depth === 2;
})) === null || _filterData$filter2 === void 0 ? void 0 : _filterData$filter2.length;
// 增加特殊逻辑,如果目前包含2层以上,则只展示第一层数据
if (firstDepthCount > 0 && secondDepthCount > 0) {
filterData = filterData.filter(function (sub) {
return sub.depth === 1;
});
}
var filterDataIdList = filterData.map(function (sub) {
return sub.id;
});
newItems = newItems.filter(function (item) {
return filterDataIdList.includes(item.id);
});
newItems.map(function (item) {
var _ref2, _filterData$idx$value, _filterData$idx, _filterData$idx2;
var idx = filterData.findIndex(function (sub) {
return sub.id === item.id;
});
if (typeof item.marker === 'object') {
var _filterData$idx$color;
item.marker.dataFill = (_filterData$idx$color = filterData[idx].color) !== null && _filterData$idx$color !== void 0 ? _filterData$idx$color : null;
}
item.data = (_ref2 = (_filterData$idx$value = (_filterData$idx = filterData[idx]) === null || _filterData$idx === void 0 ? void 0 : _filterData$idx.value) !== null && _filterData$idx$value !== void 0 ? _filterData$idx$value : (_filterData$idx2 = filterData[idx]) === null || _filterData$idx2 === void 0 ? void 0 : _filterData$idx2.rawValue) !== null && _ref2 !== void 0 ? _ref2 : null;
});
legendItems.sort(function (a, b) {
return b.data - a.data;
});
}
return newItems;
}, [legendItems]);
// 表格列数
var columns = ((statistics === null || statistics === void 0 ? void 0 : statistics.length) || 0) + ((config === null || config === void 0 ? void 0 : (_config$table2 = config.table) === null || _config$table2 === void 0 ? void 0 : (_config$table2$custom = _config$table2.custom) === null || _config$table2$custom === void 0 ? void 0 : _config$table2$custom.length) || 0);
// legend宽高
var legendWidth = widgetsCtx === null || widgetsCtx === void 0 ? void 0 : (_widgetsCtx$legendSiz = widgetsCtx.legendSize) === null || _widgetsCtx$legendSiz === void 0 ? void 0 : _widgetsCtx$legendSiz[0];
var legendHeight = widgetsCtx === null || widgetsCtx === void 0 ? void 0 : (_widgetsCtx$legendSiz2 = widgetsCtx.legendSize) === null || _widgetsCtx$legendSiz2 === void 0 ? void 0 : _widgetsCtx$legendSiz2[1];
useEffect(function () {
setFilteredItems([]);
}, [config]);
useEffect(function () {
filterLegend(chart, function (value) {
return !filteredItems.includes(value);
}, legendField);
}, [filteredItems]);
var activeItem = function activeItem(itemName) {
highlightLegend(chart, function (value) {
return value === itemName;
}, legendField);
};
var clearActive = function clearActive() {
clearHighlight(chart);
};
useEffect(function () {
clearActive();
if (activedItem) {
activeItem(activedItem);
}
}, [activedItem]);
// 进位相关配置项
var chartConfig = (_widgetsCtx$props$con = widgetsCtx === null || widgetsCtx === void 0 ? void 0 : (_widgetsCtx$props = widgetsCtx.props) === null || _widgetsCtx$props === void 0 ? void 0 : _widgetsCtx$props.config) !== null && _widgetsCtx$props$con !== void 0 ? _widgetsCtx$props$con : {};
var formatConfig = useMemo(function () {
return getFormatConfig(chartConfig);
}, [chartConfig]);
// id -> 统计值的最终展示值 映射表
var valueMap = useMemo(function () {
var newMap = {};
// console.log('updateItems', updateItems, statisticsRes);
updateItems.map(function (legendItem, index) {
var _legendItem$id, _config$table3;
var name = legendItem.name;
var id = (_legendItem$id = legendItem.id) !== null && _legendItem$id !== void 0 ? _legendItem$id : name;
statistics === null || statistics === void 0 ? void 0 : statistics.forEach(function (statistic) {
var _statisticsRes$id;
var value = (_statisticsRes$id = statisticsRes[id]) === null || _statisticsRes$id === void 0 ? void 0 : _statisticsRes$id[statistic];
if (value || value === 0) {
if (config !== null && config !== void 0 && config.valueFormatter && typeof (config === null || config === void 0 ? void 0 : config.valueFormatter) === 'function') {
value = config === null || config === void 0 ? void 0 : config.valueFormatter(value, legendItem, index);
} else {
// value = formatValue(value, config?.decimal);
var customValueFormatter = null;
if (Array.isArray(formatConfig)) {
// 双轴
// @ts-ignore
var dataGroup = getItemData(name, widgetsCtx === null || widgetsCtx === void 0 ? void 0 : widgetsCtx.rawData, config === null || config === void 0 ? void 0 : config.dataType, widgetsCtx === null || widgetsCtx === void 0 ? void 0 : widgetsCtx.data);
customValueFormatter = (dataGroup === null || dataGroup === void 0 ? void 0 : dataGroup.yAxis) === 1 ? customFormatter(formatConfig[1]) : customFormatter(formatConfig[0]);
} else {
// 单轴
customValueFormatter = customFormatter(formatConfig);
}
if (customValueFormatter) {
value = customValueFormatter(value);
} else {
value = formatValue(value, config === null || config === void 0 ? void 0 : config.decimal);
}
}
} else {
value = '-';
}
if (!(id in newMap)) {
newMap[id] = {};
}
newMap[id][statistic] = value;
});
((config === null || config === void 0 ? void 0 : (_config$table3 = config.table) === null || _config$table3 === void 0 ? void 0 : _config$table3.custom) || []).forEach(function (customItem, index) {
var _customItem$value;
var title = customItem.title || "custom" + index;
var value = typeof (customItem === null || customItem === void 0 ? void 0 : customItem.value) === 'function' ? customItem.value(_extends({}, legendItem, statisticsRes[id])) : (_customItem$value = customItem === null || customItem === void 0 ? void 0 : customItem.value) !== null && _customItem$value !== void 0 ? _customItem$value : '';
if (!(id in newMap)) {
newMap[id] = {};
}
newMap[id][title] = value;
});
});
return newMap;
}, [updateItems, statistics, statisticsRes, config, formatConfig]);
// 根据每列的标题和数值计算每列的宽度
var widthMap = useMemo(function () {
var newMap = {};
Object.keys(valueMap).forEach(function (id) {
var statisticMap = valueMap[id];
Object.keys(statisticMap).forEach(function (statistic) {
var value = statisticMap[statistic].toString();
if (!(statistic in newMap) || newMap[statistic] < value.length) {
newMap[statistic] = value;
}
});
});
Object.keys(newMap).forEach(function (statistic) {
// 最小值40
newMap[statistic] = Math.max(Math.ceil(calcTextWidth(newMap[statistic])), 40);
});
return newMap;
}, [valueMap, config === null || config === void 0 ? void 0 : (_config$table4 = config.table) === null || _config$table4 === void 0 ? void 0 : _config$table4.custom]);
// 表格布局
var gridTemplate = useMemo(function () {
var _config$table5, _updateItems$length;
var res = columns > 0 ? ['8px minmax(80px, 40%)'].concat(statistics.map(function (statistic) {
return "minmax(" + widthMap[statistic] + "px, " + 60 / columns + "%)";
}), ((config === null || config === void 0 ? void 0 : (_config$table5 = config.table) === null || _config$table5 === void 0 ? void 0 : _config$table5.custom) || []).map(function (customItem, index) {
return "minmax(" + widthMap[customItem.title || "custom" + index] + "px, " + 60 / columns + "%)";
})).join(' 8px ') : '8px minmax(min(80px, 30%), 100%)';
// 当有纵向滚动条时,需要给加一列
if ((((_updateItems$length = updateItems === null || updateItems === void 0 ? void 0 : updateItems.length) !== null && _updateItems$length !== void 0 ? _updateItems$length : 0) + 1) * 20 > legendHeight) {
res += ' 8px';
}
return res;
}, [widthMap, statistics, config === null || config === void 0 ? void 0 : (_config$table6 = config.table) === null || _config$table6 === void 0 ? void 0 : _config$table6.custom, columns, updateItems === null || updateItems === void 0 ? void 0 : updateItems.legnth, legendHeight]);
// 表格最小宽度
var tableMinWidth = useMemo(function () {
var _config$table7, _updateItems$length2;
var res = 10 + 8 + 80;
statistics.forEach(function (statistic) {
res += 8 + widthMap[statistic];
});
((config === null || config === void 0 ? void 0 : (_config$table7 = config.table) === null || _config$table7 === void 0 ? void 0 : _config$table7.columns) || []).forEach(function (customItem, index) {
res += 8 + widthMap[customItem.title || "custom" + index];
});
if ((((_updateItems$length2 = updateItems === null || updateItems === void 0 ? void 0 : updateItems.length) !== null && _updateItems$length2 !== void 0 ? _updateItems$length2 : 0) + 1) * 20 > legendHeight) {
res += 8;
}
return res;
}, [widthMap, statistics, config === null || config === void 0 ? void 0 : (_config$table8 = config.table) === null || _config$table8 === void 0 ? void 0 : _config$table8.custom, columns, updateItems, legendHeight]);
return /*#__PURE__*/React.createElement("table", {
className: prefix + "-container",
style: _extends({
paddingLeft: position === 'right' ? 10 : 0,
minWidth: tableMinWidth
}, config === null || config === void 0 ? void 0 : (_config$table9 = config.table) === null || _config$table9 === void 0 ? void 0 : _config$table9.style)
}, columns > 0 && !(config !== null && config !== void 0 && (_config$table10 = config.table) !== null && _config$table10 !== void 0 && _config$table10.hideTitle) && /*#__PURE__*/React.createElement("thead", {
className: prefix + "-thead"
}, /*#__PURE__*/React.createElement("tr", {
className: prefix + "-tr " + prefix + "-legend-title",
style: {
gridTemplateColumns: gridTemplate
}
}, /*#__PURE__*/React.createElement("th", null), /*#__PURE__*/React.createElement("th", null), statistics === null || statistics === void 0 ? void 0 : statistics.map(function (statistic) {
var _widgetsCtx$context;
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("th", null), /*#__PURE__*/React.createElement("th", {
key: statistic
}, getText(statistic, widgetsCtx === null || widgetsCtx === void 0 ? void 0 : widgetsCtx.language, widgetsCtx === null || widgetsCtx === void 0 ? void 0 : (_widgetsCtx$context = widgetsCtx.context) === null || _widgetsCtx$context === void 0 ? void 0 : _widgetsCtx$context.locale)));
}), ((config === null || config === void 0 ? void 0 : (_config$table11 = config.table) === null || _config$table11 === void 0 ? void 0 : _config$table11.custom) || []).map(function (customItem, index) {
var _customItem$title;
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("th", null), /*#__PURE__*/React.createElement("th", {
key: "custom" + index
}, (_customItem$title = customItem === null || customItem === void 0 ? void 0 : customItem.title) !== null && _customItem$title !== void 0 ? _customItem$title : ''));
}))), /*#__PURE__*/React.createElement("tbody", {
className: prefix + "-tbody",
style: {
height: "calc(100% - " + (columns > 0 && !(config !== null && config !== void 0 && (_config$table12 = config.table) !== null && _config$table12 !== void 0 && _config$table12.hideTitle) ? 20 : 0) + "px)",
// 有横向滚动条时,需要加个padding
paddingBottom: legendWidth < tableMinWidth ? 4 : 0
}
}, updateItems.map(function (legendItem, index) {
var _legendItem$id2, _config$table13;
var name = legendItem.name,
marker = legendItem.marker;
var id = (_legendItem$id2 = legendItem.id) !== null && _legendItem$id2 !== void 0 ? _legendItem$id2 : name;
if (itemName) {
var _itemName$formatter;
name = itemName === null || itemName === void 0 ? void 0 : (_itemName$formatter = itemName.formatter) === null || _itemName$formatter === void 0 ? void 0 : _itemName$formatter.call(itemName, name, index, legendItem);
}
return /*#__PURE__*/React.createElement("tr", {
key: id,
className: prefix + "-tr " + prefix + "-legend-item " + (clickable ? 'pointer' : ''),
style: {
gridTemplateColumns: gridTemplate,
color: !filteredItems.includes(id) ? activedItem === id ? themes['widgets-legend-text-highlight'] : themes['widgets-legend-text-normal'] : themes['widgets-color-disable']
},
onMouseEnter: function onMouseEnter() {
if (hoverable && !filteredItems.includes(id)) {
setActivedItem(id);
}
},
onMouseLeave: function onMouseLeave() {
if (hoverable && !filteredItems.includes(id)) {
setActivedItem('');
}
},
onClick: function onClick(event) {
// 是否按Control
var hasControl = event.ctrlKey || event.metaKey;
if (clickable) {
if (!useReverseChecked && !hasControl || useReverseChecked && hasControl) {
// 正选
if ((filteredItems === null || filteredItems === void 0 ? void 0 : filteredItems.length) === (updateItems === null || updateItems === void 0 ? void 0 : updateItems.length) - 1 && !filteredItems.includes(id)) {
setFilteredItems([]);
} else {
setFilteredItems(updateItems.map(function (item) {
return item.id || item.name;
}).filter(function (legendName) {
return legendName !== id;
}));
}
} else {
// 反选
if ((filteredItems === null || filteredItems === void 0 ? void 0 : filteredItems.length) === (updateItems === null || updateItems === void 0 ? void 0 : updateItems.length) - 1 && !filteredItems.includes(id)) {
setFilteredItems([]);
} else if (filteredItems.includes(id)) {
setFilteredItems(function (pre) {
return pre.filter(function (p) {
return p !== id;
});
});
} else {
setFilteredItems(function (pre) {
return [].concat(pre, [id]);
});
}
}
}
}
}, /*#__PURE__*/React.createElement("td", {
className: prefix + "-marker"
}, /*#__PURE__*/React.createElement(LegendMarker, {
marker: marker,
disable: filteredItems.includes(id),
item: legendItem
})), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(LegendName, {
name: name
})), statistics === null || statistics === void 0 ? void 0 : statistics.map(function (statistic) {
var _valueMap$id;
var value = valueMap === null || valueMap === void 0 ? void 0 : (_valueMap$id = valueMap[id]) === null || _valueMap$id === void 0 ? void 0 : _valueMap$id[statistic];
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("td", null), /*#__PURE__*/React.createElement("td", {
className: prefix + "-statistics",
key: statistic
}, value));
}), ((config === null || config === void 0 ? void 0 : (_config$table13 = config.table) === null || _config$table13 === void 0 ? void 0 : _config$table13.custom) || []).map(function (customItem, index) {
var value = valueMap[id][(customItem === null || customItem === void 0 ? void 0 : customItem.title) || "custom" + index];
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("td", null), /*#__PURE__*/React.createElement("td", {
className: prefix + "-statistics",
key: "custom" + index
}, value));
}));
})));
}
function LegendName(_ref3) {
var _ref3$name = _ref3.name,
name = _ref3$name === void 0 ? '' : _ref3$name;
var ref = useRef(null);
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
ref: ref,
className: prefix + "-name"
}, name), /*#__PURE__*/React.createElement(WidgetsTooltip, {
ref: ref,
content: name
}));
}
/** 格式化数字 */
function formatValue(value, digits) {
if (digits === void 0) {
digits = 3;
}
return typeof value === 'number' ? value.toFixed(digits) : value.slice(0, digits + 2);
}