vue2动态实现多Y轴echarts图表,及节点点击事件

作者:四月_h日期:2025/10/3

父组件

1<template>
2  <div class="app-container">
3    <div class="content">
4      <el-form
5        :model="echartsqueryParams"
6        ref="echartsqueryForm"
7        :inline="true"
8      >
9        <el-form-item label="号" prop="furnaceNumber">
10          <el-select
11            v-model="echartsqueryParams.furnaceNumber"
12            placeholder="请选择"
13            style="width: 150px"
14          >
15            <el-option
16              v-for="item in deviceOptions"
17              :key="item"
18              :label="item"
19              :value="item"
20            >
21            </el-option>
22          </el-select>
23        </el-form-item>
24        <el-form-item label="日期">
25          <el-date-picker
26            v-model="timeData"
27            popper-class="noClear"
28            size="small"
29            value-format="yyyy-MM-dd HH:mm:ss"
30            type="datetimerange"
31            range-separator="-"
32            start-placeholder="开始日期"
33            end-placeholder="结束日期"
34            :clearable="false"
35            @change="handleChange"
36          ></el-date-picker>
37        </el-form-item>
38        <el-form-item label="真空">
39          <el-input
40            style="width: 150px"
41            v-model="csValue"
42            placeholder="请输入"
43            type="number"
44            @blur="inputChange"
45          />
46        </el-form-item>
47        <el-form-item label="时间间隔" prop="interval">
48          <el-select
49            v-model="echartsqueryParams.interval"
50            placeholder="请选择"
51            style="width: 150px"
52          >
53            <el-option
54              v-for="item in options"
55              :key="item.value"
56              :label="item.label"
57              :value="item.value"
58            >
59            </el-option>
60          </el-select>
61        </el-form-item>
62        <el-form-item>
63          <el-button
64            icon="el-icon-printer"
65            type="primary"
66            @click="ceshi = !ceshi"
67            size="mini"
68            >打印</el-button
69          >
70          <el-button
71            type="primary"
72            icon="el-icon-search"
73            size="mini"
74            @click="handleQuery_echarts"
75            >搜索</el-button
76          >
77          <el-button
78            icon="el-icon-refresh"
79            size="mini"
80            @click="resetQuery_echarts"
81            >重置</el-button
82          >
83        </el-form-item>
84      </el-form>
85      <div>
86        <el-checkbox-group
87          v-model="checkedCities"
88          @change="handleCheckedCitiesChange"
89        >
90          <el-checkbox v-for="city in cities" :label="city" :key="city">{{
91            city
92          }}</el-checkbox>
93        </el-checkbox-group>
94      </div>
95      <div style="margin-bottom: 15px"></div>
96      <div
97        v-loading="echartsLoading"
98        style="width: 100%; height: calc(100% - 40px - 60px)"
99      >
100        <moreyaxis
101          v-if="axiosData.length > 0"
102          :legend="legend"
103          :axiosData="axiosData"
104          :yaxiosData="yaxios"
105          :serios="serios"
106          :colors="colors"
107          :gridRIght="gridRIght"
108        ></moreyaxis>
109        <el-empty description="暂无数据" v-else></el-empty>
110      </div>
111    </div>
112    <!-- 打印内容 -->
113    <el-dialog
114      class="dialogPrint"
115      title="请确认打印内容"
116      :visible.sync="ceshi"
117      style="height: 90vh"
118    >
119      <div id="printMe" style="width: 100%">
120        <div style="width: 1px; height: 1px"></div>
121        <div v-if="echartsList.nodeTimes.length > 0">
122          <div style="display: flex">
123            <p style="margin: 0; margin-right: 20px">
124              号:{{ echartsqueryParams.furnaceNumber }}
125            </p>
126            <p style="margin: 0; margin-right: 20px">
127              开始时间:{{ echartsList.nodeTimes[0] }}
128            </p>
129            <p style="margin: 0">
130              结束时间:{{
131                echartsList.nodeTimes[Number(echartsList.nodeTimes.length) - 1]
132              }}
133            </p>
134          </div>
135          <ul
136            style="
137              padding: 0;
138              display: grid;
139              grid-template-columns: repeat(4, 1fr);
140              grid-column-gap: 10px;
141              grid-row-gap: 10px;
142            "
143          >
144            <li v-for="(item, index) in echartsList.series" :key="index">
145              <p
146                style="
147                  width: 100%;
148                  border: 1px solid #f9f9f9;
149                  padding: 10px;
150                  margin: 0;
151                "
152              >
153                <span
154                  style="border-left: 3px solid #4068e0; padding-left: 5px"
155                  >{{ item.name }}</span
156                >
157              </p>
158              <div style="display: flex">
159                <p
160                  style="
161                    font-size: 12px;
162                    margin: 0;
163                    width: 50%;
164                    border: 1px solid #f9f9f9;
165                    border-top: none;
166                    padding: 10px;
167                  "
168                >
169                  开始{{ item.name.substring(item.name.length - 2) }}{{
170                    item.values[0]
171                  }}{{ item.unit }}
172                </p>
173                <p
174                  style="
175                    font-size: 12px;
176                    margin: 0;
177                    width: 50%;
178                    border: 1px solid #f9f9f9;
179                    border-top: none;
180                    padding: 10px;
181                  "
182                >
183                  结束{{ item.name.substring(item.name.length - 2) }}{{
184                    item.values[Number(item.values.length) - 1]
185                  }}{{ item.unit }}
186                </p>
187              </div>
188            </li>
189          </ul>
190        </div>
191        <div style="width: 100%; height: 500px" v-if="axiosData.length > 0">
192          <moreyaxis
193            style="width: 100%; height: 500px"
194            :legend="legend"
195            :axiosData="axiosData"
196            :yaxiosData="yaxios"
197            :serios="serios"
198            :colors="colors"
199            :gridRIght="gridRIght"
200          ></moreyaxis>
201        </div>
202      </div>
203
204      <div slot="footer">
205        <el-button @click="ceshi = false">取 消</el-button>
206        <el-button type="primary" v-print="printObj">确 定</el-button>
207      </div>
208    </el-dialog>
209  </div>
210</template>
211<script>
212import moreyaxis from "@/views/echarts/moreyaxis.vue";
213import { echartsData } from "@/api/collocation/records";
214export default {
215  components: { moreyaxis },
216  data() {
217    return {
218      deviceOptions: [28030002, 13020101, 28030003, 13020100],
219      ceshi: false,
220      // 图表参数
221      start: true,
222      echartsList: {
223        nodeTimes: [],
224        series: [],
225      },
226      echartsLoading: true,
227      colors: ["#6488FE", "#FF6F6F", "#FEE177", "#2AF0CF", "#08BE87"],
228      legend: [],
229      axiosData: [],
230      serios: [],
231      yaxios: [],
232      // 查询参数
233      echartsqueryParams: {
234        startTime: null,
235        endTime: null,
236        interval: 30,
237        id: null,
238        // limit: 200,
239        furnaceNumber: null,
240      },
241      timeData: [],
242      options: [
243        {
244          label: "十秒",
245          value: 10,
246        },
247        {
248          label: "三十秒",
249          value: 30,
250        },
251        {
252          label: "一分钟",
253          value: 60,
254        },
255        {
256          label: "五分钟",
257          value: 300,
258        },
259        {
260          label: "十分钟",
261          value: 600,
262        },
263        {
264          label: "十五分钟",
265          value: 900,
266        },
267        {
268          label: "半小时",
269          value: 1800,
270        },
271        {
272          label: "一小时",
273          value: 3600,
274        },
275      ],
276      printObj: {
277        id: "printMe",
278        popTitle: "记录",
279        closeCallback: this.closeCallback,
280      },
281      detailsTable: [],
282      gridRIght: 0,
283      csValue: null,
284      cities: [],
285      cityOptions: [],
286      checkAll: false,
287      isIndeterminate: true,
288      checkedCities: [],
289      data: {},
290    };
291  },
292  methods: {
293    handleChange(value) {
294      if (value) {
295        const start = new Date(value[0]);
296        const end = new Date(value[1]);
297
298        if (end - start > 24 * 60 * 60 * 1000) {
299          this.$message.error("结束时间不能大于开始时间一天");
300          this.timeData = null; // 清空选择
301        }
302      }
303    },
304    // 设备列表
305    deviceData() {
306      listDevice().then((res) => [console.log(res)]);
307    },
308    handleCheckedCitiesChange(value) {
309      this.echartsSerios(this.data.series);
310    },
311    // 导出
312    handleExport_echarts() {},
313    // 图表搜索
314    handleQuery_echarts() {
315      this.echartsLoading = true;
316      this.echartsDataList();
317    },
318    // 图表重置
319    resetQuery_echarts() {
320      this.updateCurrentTime();
321      this.echartsLoading = true;
322      this.echartsqueryParams.interval = null;
323      this.echartsDataList();
324    },
325    // 图表数据解析
326    echartsDataList(row) {
327      this.echartsqueryParams.startTime = this.timeData[0];
328      this.echartsqueryParams.endTime = this.timeData[1];
329      echartsData(this.echartsqueryParams).then((res) => {
330        this.data = res.data;
331        this.checkedCities = this.data.series.map((i) => i.name);
332        this.cityOptions = this.data.series.map((i) => i.name);
333        this.cities = this.data.series.map((i) => i.name);
334        this.axiosData = this.data.nodeTimes;
335        this.legend = this.data.series.map((i) => i.name);
336        this.echartsLoading = false;
337        this.echartsList = JSON.parse(JSON.stringify(this.data));
338        this.echartsList.series = this.echartsList.series.filter(
339          (item) => item.name !== "真空"
340        );
341        this.echartsSerios(this.data.series);
342      });
343    },
344    echartsSerios(data) {
345      this.serios = data.map((i, index) => {
346        const name = {
347          name: i.name,
348          type: "line",
349          yAxisIndex: index,
350          data: i.values,
351          unit: i.unit,
352          z: 5,
353          zLevel: 5,
354          symbolSize: 10,
355          label: {
356            show: true,
357            color: "#999999", // 标签文字颜色
358            fontSize: 12, // 标签文字大小
359            fontWeight: 400,
360            avoidLabelOverlap: true,
361            overlap: false,
362            formatter: function (params) {
363              if (params.dataIndex % 4 === 0) {
364                return params.value;
365              } else {
366                return ""; // 不显示标签以避免重叠
367              }
368            },
369          },
370        };
371        if (i.name === "真空" && this.csValue != 0) {
372          name.markLine = {
373            data: [{ type: "average", name: i.name, yAxis: this.csValue }],
374          };
375        }
376        return name;
377      });
378
379      let currentOffset = 0; // 总体的偏移量
380      let nameLengthOffset = 0;
381      this.yaxios = data.map((i, index) => {
382        nameLengthOffset = i.name.length * 20; // 名称长度偏移量
383        const name = {
384          type: "value",
385          name: i.name,
386          position: "right",
387          alignTicks: true,
388          offset: currentOffset,
389          axisLine: {
390            show: true,
391            lineStyle: {
392              color: this.colors[index % this.colors.length],
393            },
394          },
395          axisLabel: {
396            formatter: "{value}" + i.unit,
397          },
398          axisTick: {
399            show: true,
400          },
401        };
402
403        // 判断哪个轴不显示
404        if (this.checkedCities.indexOf(i.name) > -1) {
405          name.show = true;
406        } else {
407          name.show = false;
408          nameLengthOffset = nameLengthOffset - i.name.length * 20;
409        }
410        if (i.yAxisMin != null) {
411          name.min = i.yAxisMin;
412        }
413
414        if (i.yAxisMax != null) {
415          name.max = i.yAxisMax;
416        }
417
418        currentOffset += nameLengthOffset; // 更新偏移量
419        return name;
420      });
421
422      this.gridRIght = currentOffset - nameLengthOffset / 2; // 更新网格右侧偏移量
423    },
424    updateCurrentTime() {
425      const now = new Date();
426      const year = now.getFullYear();
427      const month = String(now.getMonth() + 1).padStart(2, "0");
428      const day = String(now.getDate()).padStart(2, "0");
429      const hours = String(now.getHours()).padStart(2, "0");
430      const minutes = String(now.getMinutes()).padStart(2, "0");
431      const seconds = String(now.getSeconds()).padStart(2, "0");
432      // 获取前一个小时的时间
433      const previousHour = new Date(now.getTime() - 3600000); // 3600000 毫秒 = 1 小时
434      const previousYear = previousHour.getFullYear();
435      const previousMonth = String(previousHour.getMonth() + 1).padStart(
436        2,
437        "0"
438      );
439      const previousDay = String(previousHour.getDate()).padStart(2, "0");
440      const previousHours = String(previousHour.getHours()).padStart(2, "0");
441      const previousMinutes = String(previousHour.getMinutes()).padStart(
442        2,
443        "0"
444      );
445      const previousSeconds = String(previousHour.getSeconds()).padStart(
446        2,
447        "0"
448      );
449      this.$set(this, "timeData", [
450        `${previousYear}-${previousMonth}-${previousDay} ${previousHours}:${previousMinutes}:${previousSeconds}`,
451        `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`,
452      ]);
453
454      // this.echartsqueryParams.furnaceNumber = 13020100;
455      // this.timeData = ["2025-09-08 00:00:00", "2025-09-08 00:03:00"];
456    },
457    inputChange(value) {
458      this.echartsDataList();
459    },
460  },
461  created() {
462    this.echartsqueryParams.furnaceNumber = this.deviceOptions[0];
463    this.updateCurrentTime();
464  },
465  mounted() {
466    this.echartsDataList();
467  },
468};
469</script>
470<style lang="scss" scoped>
471ul li {
472  list-style: none;
473}
474.app-container {
475  width: 100%;
476  height: calc(100vh - 100px);
477  .content {
478    width: 100%;
479    height: 100%;
480    overflow: auto;
481  }
482}
483::v-deep .el-dialog {
484  width: 80vw !important;
485  border-radius: 8px;
486  margin-bottom: 0;
487  margin-top: 5vh !important;
488  display: flex;
489  flex-direction: column;
490  max-height: calc(90vh - 100px);
491  overflow: hidden;
492  box-sizing: border-box;
493  .el-dialog__header {
494    padding-top: 14px;
495  }
496  .el-dialog__body {
497    margin: 0 20px 20px 20px;
498    padding: 0;
499    overflow: auto;
500  }
501}
502@media print {
503  @page {
504    size: auto;
505    // margin: 3mm;
506  }
507}
508</style>
509
510

子组件

1<template>
2  <div ref="chartRef" style="width: 100%; height: 100%"></div>
3</template>
4
5<script>
6import * as echarts from "echarts";
7
8export default {
9  name: "moreyaxis",
10  props: {
11    legend: {
12      type: Array,
13      default: () => [],
14    },
15    axiosData: {
16      type: Array,
17      default: () => [],
18    },
19    yaxiosData: {
20      type: Array,
21      default: () => [],
22    },
23    serios: {
24      type: Array,
25      default: () => [],
26    },
27    colors: {
28      type: Array,
29      default: () => [],
30    },
31    gridRIght: {
32      type: Number,
33      default: () => 0,
34    },
35  },
36  data() {
37    return {
38      chartInstance: null,
39      selectedPoints: [], // 用于存储选中的节点
40    };
41  },
42  watch: {
43    yaxiosData: {
44      deep: true,
45      handler() {
46        this.selectedPoints = [];
47        this.destroyChart();
48        this.initChart();
49      },
50    },
51  },
52  mounted() {
53    if (this.serios.length > 0) {
54      this.initChart();
55    }
56    this.setupResizeObserver();
57  },
58  beforeDestroy() {
59    if (this.chartInstance) {
60      this.chartInstance.dispose();
61    }
62  },
63  methods: {
64    initChart() {
65      if (!this.chartInstance) {
66        this.chartInstance = echarts.init(this.$refs.chartRef);
67      }
68      let currentData = null; //
69      const option = {
70        color: this.colors,
71        tooltip: {
72          trigger: "axis",
73          axisPointer: {
74            type: "cross",
75          },
76          textStyle: {
77            fontSize: 10,
78          },
79          // triggerOn: "click",
80          alwaysShowContent: false, // 关键:永久显示
81          enterable: false,
82          show: true, // 默认不显示
83        },
84        dataZoom: [
85          {
86            type: "inside",
87          },
88        ],
89        grid: {
90          top: "60px",
91          left: "40px",
92          bottom: "40px",
93          right: this.gridRIght + "px",
94        },
95        legend: {
96          data: this.legend,
97          top: 0,
98        },
99        xAxis: [
100          {
101            boundaryGap: false,
102            type: "category",
103            axisTick: {
104              alignWithLabel: true,
105            },
106            data: this.axiosData,
107            axisLabel: {
108              formatter: function (params) {
109                var newParamsName = "";
110                var paramsNameNumber = params.length;
111                var provideNumber = 10;
112                var rowNumber = Math.ceil(paramsNameNumber / provideNumber);
113                for (let row = 0; row < rowNumber; row++) {
114                  newParamsName +=
115                    params.substring(
116                      row * provideNumber,
117                      (row + 1) * provideNumber
118                    ) + "\n";
119                }
120                return newParamsName;
121              },
122              color: "#999",
123            },
124          },
125        ],
126        yAxis: this.yaxiosData,
127        series: this.serios,
128        graphic: {
129          elements: this.selectedPoints.map((point) => ({
130            type: "group",
131            children: [
132              {
133                z: 10,
134                zLevel: 10,
135                type: "rect",
136                shape: { width: 140, height: 90 },
137                style: {
138                  fill: "#FFF",
139                  // stroke: "#666", // 边框颜色
140                  // lineWidth: 1, // 边框宽度
141                  shadowBlur: 5, // 阴影模糊度
142                  shadowColor: "#666", // 阴影颜色
143                  shadowOffsetX: 2, // 阴影水平偏移
144                  shadowOffsetY: 2, // 阴影垂直偏移
145                  padding: ["10px", "5px"],
146                },
147              },
148              {
149                type: "text",
150                z: 10,
151                zLevel: 10,
152                style: {
153                  text: this.formatTooltipContent(point),
154                  fill: "#999",
155                  fontSize: 12,
156                  textBaseline: "middle",
157                  padding: [10, 0, 0, 0],
158                },
159                position: [10, 0],
160              },
161            ],
162            position: [point.x, point.y],
163            draggable: true,
164          })),
165        },
166      };
167      this.chartInstance.setOption(option);
168
169      // 监听点击事件
170      this.chartInstance.on("click", (params) => {
171        if (params.componentType === "series") {
172          const existingPoint = this.selectedPoints.find(
173            (point) =>
174              point.seriesName === params.seriesName &&
175              point.dataIndex === params.dataIndex
176          );
177          if (existingPoint) {
178            this.selectedPoints = this.selectedPoints.filter(
179              (point) =>
180                point.seriesName !== params.seriesName ||
181                point.dataIndex !== params.dataIndex
182            );
183          } else {
184            this.selectedPoints.push({
185              seriesIndex: params.seriesIndex,
186              name: params.name,
187              seriesName: params.seriesName,
188              value: params.value,
189              x: params.event.offsetX,
190              y: params.event.offsetY,
191              dataIndex: params.dataIndex,
192            });
193          }
194          // this.selectedPoints.forEach((item) => {
195          //   this.chartInstance.dispatchAction({
196          //     type: "showTip",
197          //     // 系列的 index,在 tooltip 的 trigger 为 axis 的时候可选。
198          //     seriesIndex: item.seriesIndex,
199          //     // 数据项的 index,如果不指定也可以通过 name 属性根据名称指定数据项
200          //     dataIndex: item.dataIndex,
201          //   });
202          // });
203
204          this.destroyChart();
205          this.initChart();
206        }
207      });
208    },
209    formatTooltipContent(point) {
210      // 格式化 tooltip 内容,显示多个轴的数据
211      let content = `${this.axiosData[point.dataIndex]}\n`;
212      this.serios.forEach((series) => {
213        if (series.data[point.dataIndex] !== undefined) {
214          content += `${series.name}: ${series.data[point.dataIndex]}${
215            series.unit
216          }\n`;
217        }
218      });
219      return content;
220    },
221    destroyChart() {
222      if (this.chartInstance) {
223        this.chartInstance.dispose();
224        this.chartInstance = null;
225      }
226    },
227    setupResizeObserver() {
228      const resizeObserver = new ResizeObserver((entries) => {
229        for (let entry of entries) {
230          if (entry.target === this.$refs.chartRef) {
231            if (this.chartInstance) {
232              this.chartInstance.resize();
233            }
234          }
235        }
236      });
237      resizeObserver.observe(this.$refs.chartRef);
238    },
239  },
240};
241</script>
242
243<style scoped>
244/* 添加一些样式 */
245</style>
246

源代码记录


vue2动态实现多Y轴echarts图表,及节点点击事件》 是转载文章,点击查看原文


相关推荐


神经网络中的损失函数:常见类型与应用场景(代码演示)
fyakm2025/10/2

在神经网络的世界里,损失函数是一个非常重要的概念。它就像是一个“裁判”,能够衡量模型预测结果与真实结果之间的差距。通过了解损失函数的常见类型和应用场景,我们可以根据不同的需求选择合适的损失函数,从而避免因损失函数选择不合理导致的模型性能不佳问题。接下来,我们就一起深入了解一下损失函数的相关知识,并通过Python代码来演示不同损失函数的计算和效果。 目录 损失函数的类型和应用场景均方误差损失函数(Mean Squared Error, MSE)交叉熵损失函数(Cross - Entro


《Local_Pdf_Chat_RAG 深度学习笔记:PDF 本地化对话的 RAG 原理与实践》
Bug Spray2025/10/2

在处理本地 PDF 文档的智能对话需求时,很多人会面临 “云端依赖泄露隐私”“开源项目部署门槛高” 的问题 —— 而 GitHub 上的 Local_Pdf_Chat_RAG 项目,恰好以 “本地化部署 + RAG 技术” 为核心,解决了 PDF 文档的高效检索与自然语言对话难题。近期我系统学习了这个项目,从环境搭建、代码核心模块拆解,到实际场景测试与调优,踩过不少新手常见的坑,也总结了一套可复用的实践经验。因此整理这份学习笔记,一方面记录自己的技术成长,另一方面希望能帮到同样想入门 “本地 P


【mdBook】7.2 替代后端
liuyuan7710/2/2025

如果我们不需要指定字数统计后端的完整名称/路径,是因为 mdbook 会尝试按照约定推断程序的名称。foo后端的可执行文件通常称为mdbook-foo,并在book.toml中有相关的条目。要明确告诉 mdbook 调用什么命令,可以使用command虽然这个示例是人为设计的,但希望它能足够展示如何为 mdbook 创建替代后端。本章开头提到的现有后端应该作为实际如何完成的良好示例,因此请随时浏览源代码或提出问题。


JavaScript中国手机号校验
蜚鸣9/30/2025

中国手机号校验方法摘要:中国手机号为11位数字,常见号段包括移动(134-139等)、联通(130-132等)、电信(133等)和虚拟运营商(170/171)。校验方法包括:1)基础正则校验(/^1[3-9]\d{9}$/);2)精确号段校验;3)号段数组比对法。建议采用前端简单校验+后端严格验证+短信验证的完整流程。国际号码可使用/^+?[1-9]\d{1,14}$/进行通用校验。(150字)


ZooKeeper详解
三坛海会大神5559/30/2025

Zookeeper从设计模式角度来理解:是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,Zookeeper就将负责通知已经在Zookeeper上注册的那些观察者做出相应的反应。它的设计目的是简化分布式系统的管理,保证多个节点之间的数据一致性和协调工作。对于已经存在Leader的情况,机器试图去选举Leader时,会被告知当前服务器的Leader信息,对于该机器来说,仅仅需要和 Leader机器建立连接,并进行状态同步即可。


豆包怎么部署到本地?一文读懂AI工具的本地化安装全流程
Nightowls__2025/10/4

在数据自主性与即时响应需求的双重推动下,AI 模型的本地部署成为众多企业和个人用户的追求,豆包作为热门 AI 模型,其本地部署也备受关注。豆包本地部署在哪里?又该如何实现高效且安全的本地化运行呢? 一、为什么要本地部署豆包? 在数据自主性与即时响应需求的双重推动下,AI模型的本地部署逐渐成为企业及个人用户优化服务、保障隐私的关键策略。对于豆包这一主流AI模型而言,本地部署具有显著的优势: 满足多元场景需求:不同行业和领域对AI模型的应用需求千差万别,本地部署豆包能够确保模型在复杂网


QPS和TPS的区别,在实际项目中,如何准确测量和监控QPS和TPS?
IT橘子皮2025/10/5

QPS(Queries Per Second,每秒查询率)和TPS(Transactions Per Second,每秒事务数)是衡量系统性能的两个关键指标,虽然常被混淆,但存在以下核心区别: 1. ​定义与范围​ ​QPS​:表示服务器每秒能响应的查询次数,通常用于衡量特定查询服务器(如DNS、数据库)的处理能力。例如,一次页面加载可能触发多次查询(如HTML、CSS、JS请求),每个查询均计入QPS。 ​TPS​:表示每秒完成的事务数量。一个事务涵盖客户端请求、服务器内部处理及响应的完整流


Python 的 UDP 编程
hubenchang05152025/10/6

#Python 的 UDP 编程 用户数据报协议(User Datagram Protocol) 是一个 无连接、非可靠 的传输层协议,和 TCP 并列,是互联网中最常见的协议之一。 UDP 程序不存在连接,只需要绑定自身地址并收发数据即可。下面是一个示例,它创建了两个 socket,从一个向另一个发送数据。 import socket # 创建 UDP socket sock1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock2


一个基于 ASP.NET Core 的开源、模块化、多租户应用框架和内容管理系统
追逐时光者2025/10/8

前言 今天大姚给大家分享一个基于 ASP.NET Core 的开源、模块化、多租户应用框架和内容管理系统:OrchardCore。 项目介绍 OrchardCore 是一个开源的(BSD-3-Clause license)、模块化的、支持多租户的应用程序框架,使用 ASP.NET Core 构建。同时,它也是一个基于该框架的内容管理系统(CMS)。 DotNetGuide编程学院 DotNetGuide编程学院是一个专注于C#/.NET/.NET Core学习、工作、面试干货和实战教程分享的知识


JDK8 新特性 - Stream 流详解
chirrupy_hamal2025/10/9

文章目录 一、认识 Stream二、Stream 的常用方法1、如何获取 Stream 流2、Stream 流常见的中间方法2.3、Stream 流常见的终结方法 一、认识 Stream 二、Stream 的常用方法 1、如何获取 Stream 流 2、Stream 流常见的中间方法 代码简化 s -> s.getName() Studet::getName 代码简化 2.3、Stream 流常见的终结方法 报错

首页编辑器站点地图

Copyright © 2025 聚合阅读

License: CC BY-SA 4.0