import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { SCATTER_CHART_TYPE, LINE_CHART_TYPE, TEXT_DATA_TYPE, DATE_DATA_TYPE, TIME_DATA_TYPE } from '../../../../shared/const'; import { ChartSetting, ChartAttr } from '../shared/analysis.model'; import { AnalysisService } from '../shared/analysis.service'; import { msToDate } from '../../../../shared/util'; @Component({ selector: 'analysis-chart-result', templateUrl: './analysis-chart-result.component.html', styleUrls: ['./analysis-chart-result.component.less'] }) export class AnalysisChartResultComponent implements OnInit { analysisId: number; analysisName: string; uuids = []; tableId: number; chartSetting: ChartSetting; currentAttrs: any[]; // 可选属性的数组 currentAttrsY = []; // 可选的y轴属性数组 lineNonTableResultCache = {}; // 曲线图非表格数据缓存 option = {}; xIndex: number; // 选中的x轴属性index yIds = []; // 选中的y轴属性id xAxis: any; yAxis: any; tooltip = { trigger: 'axis', axisPointer: { type: 'cross', lineStyle: { type: 'dashed', width: 1 } }, formatter: {} }; series = []; constructor( private analysisServ: AnalysisService, private activatedRoute: ActivatedRoute ) { } /** * 非表格属性添加option.series * @param {*} data * @param {*} option * @param {*} yIndex */ addLineNonTableOptionSeries(data, yIndex) { const currentX = this.currentAttrs[this.xIndex]; const xName = currentX.attributeName; let minX = this.xAxis.min, maxX = this.xAxis.max, minY = this.yAxis.min, maxY = this.yAxis.max; // const currentYs = getTickedAttributeIds(this.chartSettingAttrsY); try { for (let i of data[0].splice(0, data[0].length - 4)) { const yName = this.currentAttrsY.find(yAttr => yAttr.id === this.yIds[yIndex].id).attributeName; const lineName = data[1]; const lineData = []; for (let j of data) { const x = parseFloat(data[j][3]); const y = parseFloat(data[j][i + 4]); const recordName = data[j][1]; if (isNaN(minX) || minX > x) minX = x; if (isNaN(maxX) || maxX < x) maxX = x; if (isNaN(minY) || minY > y) minY = y; if (isNaN(maxY) || maxY < y) maxY = y; lineData.push([x, y, recordName]); } this.series.push({ name: `${xName}-${yName}`, type: 'line', symbol: 'none', lineStyle: { normal: { width: 1 } }, data: lineData, }); } // #3908 显示数据记录名称 this.tooltip.formatter = (points) => { let result = ''; points.forEach(point => { const value = point.value; const x = [TIME_DATA_TYPE, DATE_DATA_TYPE].indexOf(currentX.aType) > -1 ? msToDate(value[0]) : value[0]; const y = value[1]; result += `${point.marker}${point.seriesName}(${value[2]}):${x},${y}
`; }); return result; }; this.xAxis.name = xName; this.xAxis.min = Math.floor(minX); this.xAxis.max = Math.ceil(maxX); this.yAxis.min = Math.floor(minY); this.yAxis.max = Math.ceil(maxY); if ([TIME_DATA_TYPE, DATE_DATA_TYPE].indexOf(currentX.aType) > -1) this.xAxis.type = 'time'; } catch (err) { } } /** * 当x轴变化时,筛选出符合条件的y轴属性: * 1、曲线表格:y与x为同一表格下的数据 * 2、曲线非表格:y与x为非表格数据,y不能有日期数据类型 * 3、散点:y不能包含x * @param xAttr * @param yAttr * @param chartType */ checkYAttr(xAttr, yAttr, chartType) { if (chartType == LINE_CHART_TYPE && !xAttr.timeLine) { return yAttr.timeLine == xAttr.timeLine && xAttr.parentId == yAttr.parentId; } else if (chartType == LINE_CHART_TYPE && xAttr.timeLine) { return yAttr.timeLine == xAttr.timeLine && [TIME_DATA_TYPE, DATE_DATA_TYPE].indexOf(yAttr.aType) == -1; } else if (chartType == SCATTER_CHART_TYPE) { return yAttr.id != xAttr.id; } else return false; } /** * 根据id查找在数组中的序号 */ findIndex(id: number, arr: any[]) { arr.forEach((item, n) => { if (item.id === id) return n; }); return 0; } getAnalysisDetail() { this.analysisServ.getAnalysis(this.analysisId).subscribe(data => { // this.recordList = data.data.recordList || []; // this._displayData = this.recordList; this.analysisName = data.data.name; // this.analysisDescription = data.data.description; this.tableId = data.data.tableId; // this.dataBaseId = data.data.databaseId; this.chartSetting = data.data.chartSetting || {}; this.yIds = this.chartSetting.attributeIdsY.split(','); this.getChartAttr(); }); } getChartAttr() { this.analysisServ.getChartAttr(this.analysisId, this.tableId).subscribe(result => { // this.chartSettingAttrs = result; this.currentAttrs = this.chartSetting.chartType === LINE_CHART_TYPE ? result.data['12'] : result.data['1']; // this.xIndex = this.currentAttrs.find(attrX => attrX.id === this.chartSetting.attributeIdX); this.option = {}; this.updateX(); this.updateY(this.xIndex, true); }); } // initY() { // this.yIds = this.chartSetting.attributeIdsY.split(','); // } loadChartData(yIds?: any[]) { if (yIds.length === 0) alert('无法绘图'); this.yIds = yIds; const selectedX = this.currentAttrs[this.xIndex]; // 曲线图 if (this.chartSetting.chartType === LINE_CHART_TYPE) { // const selectedYs = getTickedAttributeIds(this.chartSettingAttrsY); // if (selectedYs.length == 0) { // renderWarn('请选择坐标轴!'); // } // 非表格属性 if (selectedX.timeLine) { this.loadLineNonTable(); // 表格属性 } else { this.loadLineTable(); } // 散点图 } else if (this.chartSetting.chartType == SCATTER_CHART_TYPE) { // var selectedYs_obj = searchArr(this.yId, this.chartSettingAttrsY); // loadScatter(currentX, selectedYs_obj); } } /** * 非表格数据需要对y属性依次请求,并对数据进行合并 * @param {*} dataSum 总共的数据 * @param {*} option * @param {*} yIndex 第几个y属性 */ loadLineNonTable(dataSum: any[] = [], yIndex: number = 0) { // var dataSum = arguments[0] ? arguments[0] : []; // var option = arguments[1] ? arguments[1] : angular.copy(this.option); // var yIndex = arguments[2] ? arguments[2] : 0; const selectedX = this.currentAttrs[this.xIndex]; // var currentYs = getTickedAttributeIds(this.chartSettingAttrsY); // y轴属性是否遍历完成 if (yIndex > this.yIds.length - 1) { // this.chartResultData.data = combineNonTableData(dataSum); this.renderEchart(); return; } // 有缓存就读取缓存 const cacheTemp = this.lineNonTableResultCache[`${this.uuids}-${selectedX.id}-${this.currentAttrsY[yIndex]}`]; if (cacheTemp) { this.addLineNonTableOptionSeries(cacheTemp, yIndex); this.loadLineNonTable(dataSum.concat(cacheTemp), yIndex + 1); return; } // 没有缓存就请求数据 this.analysisServ.getLineChartResult( this.analysisId, selectedX.id, this.currentAttrsY[yIndex], this.uuids ).subscribe(result => { this.lineNonTableResultCache[`${this.uuids}-${selectedX.id}-${this.currentAttrsY[yIndex]}`] = result.data; this.addLineNonTableOptionSeries(result.data, yIndex); this.loadLineNonTable(dataSum.concat(result.data), yIndex + 1); }); } loadLineTable() { const selectedX = this.currentAttrs[this.xIndex]; // var option = angular.copy(this.option); let minX, maxX, minY, maxY; this.series = []; this.analysisServ.getGraphChartResult( this.analysisId, selectedX.id, this.yIds, this.uuids ).subscribe(result => { // this.chartResultData.data = result.data; this.yIds.forEach(yId => { const xName = selectedX.attributeName; const yName = this.currentAttrsY.find(e => e.id === yId).attributeName; result.data.data.list.forEach(record => { const lineData = []; try { for (let point of record.childList) { const x = parseFloat(point.fieldList[this.xIndex].dValue); const y = parseFloat(point.fieldList[this.findIndex(yId, this.currentAttrs)].dValue); if (isNaN(x) || isNaN(y)) continue; if (isNaN(minX) || minX > x) minX = x; if (isNaN(maxX) || maxX < x) maxX = x; if (isNaN(minY) || minY > y) minY = y; if (isNaN(maxY) || maxY < y) maxY = y; lineData.push([x, y]); } } catch (err) { } this.series.push({ name: `${xName}-${yName}(${record.cnName})`, type: 'line', smooth: true, data: lineData, symbol: 'none', lineStyle: { normal: { width: 1 } }, }); }); const allUnits = selectedX.unitName ? `(${selectedX.unitName})` : ''; this.xAxis = { name: xName + allUnits, min: Math.floor(minX), max: Math.ceil(maxX) }; this.yAxis = { name: yName, min: Math.floor(minY), max: Math.ceil(maxY) }; }); const hasDataSeries = this.series.filter(points => points.data.length > 0); if (hasDataSeries.length === 0) alert('数据不足,无法绘图!'); this.series = [...this.series]; }); } // 重新赋值会触发渲染 renderEchart() { this.series = [...this.series]; } updateX() { this.currentAttrs.forEach((attr, index) => { if (attr.id === this.chartSetting.attributeIdX) { this.xIndex = index; } if ([TEXT_DATA_TYPE, DATE_DATA_TYPE].indexOf(attr.aType) > -1) { attr.disabled = true; } }); } updateY(xIndex: number, isFirst: boolean = false) { // var doRender = arguments[0] != undefined ? arguments[0] : true; // var doLoadY = arguments[1] != undefined ? arguments[1] : false; // const chartType = this.chartSetting.chartType; // curChartAttrX初始化是数字,此时要能识别。 // var xAttr = doRender ? this.curChartSettingAttrs[this.xIndex] : // typeof this.curChartAttrX == 'number' ? searchArr(this.curChartAttrX, this.curChartSettingAttrs) : this.curChartAttrX; this.xIndex = xIndex; const xAttr = { ...this.currentAttrs[xIndex] }; let firstAttrY: ChartAttr; // 找出符合条件的y轴属性 this.currentAttrsY = this.currentAttrs.filter(yAttr => { yAttr.disabled = xAttr.id === yAttr.id ? true : false; if (this.checkYAttr(xAttr, yAttr, this.chartSetting.chartType)) { // 默认显示的y轴属性 if (firstAttrY === undefined && yAttr.disabled === false) firstAttrY = yAttr; return true; } return false; }); // 保证currentAttrsY先在视图中渲染 setTimeout(_ => { this.yIds = isFirst ? this.chartSetting.attributeIdsY.split(',').map(e => parseInt(e)) : [firstAttrY.id]; this.loadChartData(this.yIds); }, 10); // this.currentAttrs.forEach(yAttr => { // if (this.checkYAttr(xAttr, yAttr, this.chartSetting.chartType)) { // this.chartSetting.attributeIdsY.split(',').forEach(selectedYId => { // if (yAttr.id === parseInt(selectedYId) && yAttr.id !== xAttr.id) { // this.yIds.push(yAttr.id); // } // }); // yAttr.disabled = xAttr.id === yAttr.id ? true : false; // this.currentAttrsY.push(yAttr); // } // }); // 散点图x轴属性与y轴属性相同时 // xAttr.id == this.yId ? this.yId = this.chartSettingAttrsY[0].id : void 0; // this.loadChartData(); } ngOnInit() { console.log(this.activatedRoute); this.uuids = this.activatedRoute.snapshot.queryParams.uuids; this.analysisId = parseInt(this.activatedRoute.snapshot.params.analysisId); this.getAnalysisDetail(); } }