123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- <template>
- <div style="width: 100%; height: 500px">
- <!-- 条件渲染日期范围选择器 -->
- <el-date-picker
- v-if="chartData.xaixs === '时间'"
- v-model="dateRange"
- type="daterange"
- align="right"
- unlink-panels
- range-separator="至"
- start-placeholder="开始日期"
- end-placeholder="结束日期"
- @change="onDateRangeChange"
- size="mini"
- style="margin: 20px 0 0 0"
- ></el-date-picker>
- <div
- v-loading="loading"
- :id="`plotDivBox-${index}`"
- style="width: 100%; height: 450px"
- >
- <el-empty v-if="isError" description="请求失败"></el-empty>
- </div>
- </div>
- </template>
- <script>
- import Plotly from "plotly.js-dist";
- import axios from "axios";
- import { myMixin } from "@/mixins/chartRequestMixin";
- export default {
- mixins: [myMixin],
- props: {
- fileAddr: {
- default: "",
- type: String,
- },
- index: {
- type: String,
- },
- setUpImgData: {
- default: () => [],
- type: Array,
- },
- },
- data() {
- return {
- chartData: {},
- dateRange: [], // 用于存储选中的日期范围
- loading: false,
- isError: false,
- };
- },
- watch: {
- setUpImgData: {
- handler(newType) {
- this.drawBoxPlot();
- },
- deep: true,
- },
- dateRange: {
- handler(newRange) {
- this.drawBoxPlot(); // 日期范围变化时重新绘制图表
- },
- deep: true,
- },
- },
- mounted() {
- console.log(this.fileAddr, "fileAddr 连接");
- this.getData();
- },
- methods: {
- async getData() {
- if (this.fileAddr !== "") {
- try {
- this.loading = true;
- this.cancelToken = axios.CancelToken.source();
- const resultChartsData = await axios.get(this.fileAddr, {
- cancelToken: this.cancelToken.token,
- });
- this.chartData = resultChartsData.data;
- this.loading = false;
- this.isError = false;
- this.drawBoxPlot(); // 数据加载完成后绘制图表
- } catch (error) {
- this.loading = false;
- this.isError = true;
- }
- }
- },
- // 处理日期范围变化
- onDateRangeChange() {
- this.drawBoxPlot(); // 日期变化时重新绘制图表
- },
- // 判断时间戳是否在选择的日期范围内
- isInDateRange(timestamp) {
- const [startDate, endDate] = this.dateRange;
- if (!startDate || !endDate) return true;
- const date = new Date(timestamp);
- return date >= new Date(startDate) && date <= new Date(endDate);
- },
- // 判断xData是否为日期格式
- isDateType(xData) {
- if (xData) {
- const firstTimestamp = xData[0];
- return !isNaN(Date.parse(firstTimestamp)); // 判断是否是有效日期
- } else {
- return false;
- }
- },
- // 过滤数据
- filterData(group) {
- const filteredXData = [];
- const filteredYData = [];
- const filteredMedians = group.medians ? { x: [], y: [] } : null;
- if (this.isDateType(group.xData)) {
- group.xData.forEach((timestamp, index) => {
- if (this.isInDateRange(timestamp)) {
- filteredXData.push(timestamp);
- filteredYData.push(group.yData[index]);
- if (filteredMedians && this.isInDateRange(group.medians.x[index])) {
- filteredMedians.x.push(group.medians.x[index]);
- filteredMedians.y.push(group.medians.y[index]);
- }
- }
- });
- } else {
- filteredXData.push(...group.xData);
- filteredYData.push(...group.yData);
- if (group.medians) {
- filteredMedians.x.push(...group.medians.x);
- filteredMedians.y.push(...group.medians.y);
- }
- }
- return {
- ...group,
- xData: filteredXData,
- yData: filteredYData,
- medians: filteredMedians,
- };
- },
- // 绘制箱线图
- drawBoxPlot() {
- if (!this.chartData.data || this.loading) return; // 如果数据为空或正在加载则不绘制
- const chartData = this.chartData.data[0];
- const filteredData = this.filterData(chartData);
- const trace = {
- x: filteredData.xData,
- y: filteredData.yData,
- type: "box",
- marker: {
- color: "#263649",
- },
- line: {
- width: 0.8, // 这里设置线条粗细(默认是 2)
- },
- boxpoints: false,
- boxmean: false,
- name: filteredData.title,
- fillcolor: "#458EF7", // 设置箱线图填充颜色,带透明度
- hovertemplate:
- `${this.chartData.xaixs}:` +
- ` %{x} <br> ` +
- `${this.chartData.yaixs}:` +
- "%{y} <br>",
- };
- let trace2 = {};
- if (filteredData.medians && filteredData.medians.x.length > 0) {
- trace2 = {
- x: filteredData.medians.x,
- y: filteredData.medians.y,
- mode: "markers",
- marker: {
- color: "#406DAB",
- size: 3,
- },
- name: `${filteredData.title} - 中位点`,
- type: "scatter",
- };
- }
- const layout = {
- title: {
- text: filteredData.title,
- font: {
- size: 16,
- weight: "bold",
- },
- },
- xaxis: {
- title: this.chartData.xaixs,
- tickmode: "array",
- type: "category", // 让 Y 轴按类别均匀分布
- gridcolor: "rgb(255,255,255)",
- tickcolor: "rgb(255,255,255)",
- backgroundcolor: "#e5ecf6",
- },
- yaxis: {
- title: this.chartData.yaixs,
- gridcolor: "rgb(255,255,255)",
- tickcolor: "rgb(255,255,255)",
- backgroundcolor: "#e5ecf6",
- },
- showlegend: false,
- plot_bgcolor: "#e5ecf6",
- gridcolor: "#fff",
- bgcolor: "#e5ecf6", // 设置背景颜色
- };
- if (
- this.chartData.xaixs === "机组" ||
- this.chartData.xaixs === "机组名称"
- ) {
- layout.xaxis.tickvals = [...new Set(filteredData.xData)];
- layout.xaxis.ticktext = [...new Set(filteredData.xData)];
- }
- const getChartSetUp = (axisTitle) => {
- return this.setUpImgData.find((item) => item.text.includes(axisTitle));
- };
- const xChartSetUp = getChartSetUp(layout.xaxis.title);
- if (xChartSetUp) {
- layout.xaxis.dtick = xChartSetUp.dtick;
- layout.xaxis.range = [xChartSetUp.min, xChartSetUp.max];
- }
- const yChartSetUp = getChartSetUp(layout.yaxis.title);
- if (yChartSetUp) {
- layout.yaxis.dtick = yChartSetUp.dtick;
- layout.yaxis.range = [yChartSetUp.min, yChartSetUp.max];
- }
- this.$nextTick(() => {
- const plotDiv = document.getElementById(`plotDivBox-${this.index}`);
- if (plotDiv) {
- Plotly.newPlot(plotDiv, [trace, trace2], layout);
- }
- });
- },
- },
- };
- </script>
- <style scoped>
- /* 可根据需要自定义样式 */
- </style>
|