vue若依集成C#的singalR接收实时数据

news/2024/9/20 18:30:54/文章来源:https://www.cnblogs.com/chenyangjava/p/18323826

要写一个实时监控页面,监控堆垛机实时状态以及线体上是否有载具、是否有任务、是否有告警。项目是若依前端,后端是Java接口。要跳过Java接口,直接对接C#的signalR推送数据。需要配置两个总接口地址,原先的Java总接口地址不能删。这里的signalR是Microsoft的sigalR,开始还搞错了,搞成了另一种signalR的.netCore的版本,package.json依赖包删掉,重来,重新安装Microsoft版本signalR版本。话不多说,直接上代码。

1.首先把signalR依赖包安装上

npm install @microsoft/signalr

2.配置新的C#端监控地址,在.env.development文件中添加地址

# 载具监控地址
VUE_APP_MONITRO_WCS_EQUIPMENT = 'http://XX.XXX.XX.XX:XXXXX'

在.env.production文件中添加地址,方便后面配置到nginx转发

# 载具监控地址
VUE_APP_MONITRO_WCS_EQUIPMENT = '/monitro-api'

3.index.vue监控页面引入signalR

import * as signalR from "@microsoft/signalr";
  //引入中央事件总线
  import bus from "@/assets/js/eventBus";

4.连接signalR接收数据

//接收wcs线体和堆垛机数据
    connect() {let url = `${process.env.VUE_APP_MONITRO_WCS_EQUIPMENT}/Equipment`;//本地开发版 singalR地址先写死  后期需要后端配置到nginx中// let url = `http://XX.XXX.XX.XX:XXXXX/Equipment`;// let token = store.getters.token.replace("Bearer ", "");
      let token;const builder = new signalR.HubConnectionBuilder();this.connection = builder.withUrl(url, {accessTokenFactory: () => token,}).withAutomaticReconnect({nextRetryDelayInMilliseconds: () => 60000,}) //断线重连
        .build();// 接收信息成功 线体this.connection.on("ReceiveMessage", (message) => {// console.log(message, "接收线体信息成功");//通过总线发送输送线实时任务bus.$emit("sendTransmissionLineByBus", message);if (message && message.length > 0) {//拼接接收到底所有线体集合for (let i = 0; i < message.length; i++) {this.conveyorUnitDtos = this.conveyorUnitDtos.concat(message[i].conveyorUnitDtos);}//删除所有线体集合arr中的重复对象var newArr = [];var arrId = [];for (var item of this.conveyorUnitDtos) {if (arrId.indexOf(item["id"]) == -1) {arrId.push(item["id"]);newArr.push(item);}}this.conveyorUnitDtos = newArr;if (this.conveyorUnitDtos.length > 0) {//线体告警数组var conveyorErrorArr = [];//线体告警隐藏位数组var conveyorErrorHiddenArr = [];//线体载具数组var conveyorGoodsArr = [];//线体载具隐藏位数组var conveyorGoodsHiddenArr = [];//线体载具任务数组var conveyorTaskNumArr = [];//线体载具任务编号ID数组var conveyorTaskNumIdArr = [];//线体载具任务隐藏位数组var conveyorTaskNumHiddenArr = [];this.conveyorUnitDtos.map((cObj, index) => {//conveyorGoods  1=无货、2=有货//conveyorTaskNum 任务号//conveyorError 0=无报警 其他=报警if (cObj.conveyorGoods == 2) {conveyorGoodsArr.push(cObj.id);} else {conveyorGoodsArr = conveyorGoodsArr.filter((item) => item != cObj.id);}// 任务号if (cObj.conveyorTaskNum != 0) {let cob = {id: cObj.id,conveyorTaskNum: cObj.conveyorTaskNum,};conveyorTaskNumArr.push(cob);conveyorTaskNumIdArr.push(cObj.id);} else {//
                let cob = {id: cObj.id,conveyorTaskNum: cObj.conveyorTaskNum,};//conveyorTaskNum等于0 已完成的任务 需要清空之前的任务数组值conveyorTaskNumArr = conveyorTaskNumArr.filter((val) => val.id !== cObj.id);conveyorTaskNumIdArr = conveyorTaskNumIdArr.filter((item) => item != cObj.id);}//告警if (cObj.conveyorError != 0) {conveyorErrorArr.push(cObj.id);} else {//已清除的告警 需要从之前的告警数组值清除conveyorErrorArr = conveyorErrorArr.filter((item) => item != cObj.id);}});//隐藏的线体载具conveyorGoodsHiddenArr = line_vehicle_Change(conveyorGoodsArr);//隐藏的线体告警conveyorErrorHiddenArr = line_error_Change(conveyorErrorArr);//隐藏的线体任务号conveyorTaskNumHiddenArr =line_taskNum_Change(conveyorTaskNumIdArr);//显示的线体载具和线体任务号for (let i = 0; i < conveyorGoodsArr.length; i++) {this.xtVehicle_arr[`xtVehicle_` + conveyorGoodsArr[i]] =xtVehicleGreen;}//隐藏的线体载具和线体任务号for (let i = 0; i < conveyorGoodsHiddenArr.length; i++) {this.xtVehicle_arr[`xtVehicle_` + conveyorGoodsHiddenArr[i]] = "";}//数组新增一条记录删除一条记录会更新domthis.xtVehicle_arr.push("xtVehicle");this.xtVehicle_arr.pop();//显示的线体任务号for (let i = 0; i < conveyorTaskNumArr.length; i++) {this.xtVehicle_task_arr[`xtVehicle_` + conveyorTaskNumArr[i].id + `_task`] = conveyorTaskNumArr[i].conveyorTaskNum;}//隐藏的线体任务号for (let i = 0; i < conveyorTaskNumHiddenArr.length; i++) {this.xtVehicle_task_arr[`xtVehicle_` + conveyorTaskNumHiddenArr[i].id + `_task`] = "";}//数组新增一条记录删除一条记录会更新domthis.xtVehicle_task_arr.push("xtVehicle_task");this.xtVehicle_task_arr.pop();//显示的线体告警for (let i = 0; i < conveyorErrorArr.length; i++) {this.xtAlarm_arr[`xtAlarm_` + conveyorErrorArr[i]] = xtAlarmRed;}//隐藏的线体告警for (let i = 0; i < conveyorErrorHiddenArr.length; i++) {this.xtAlarm_arr[`xtAlarm_` + conveyorErrorHiddenArr[i]] = "";}//数组新增一条记录删除一条记录会更新domthis.xtAlarm_arr.push("xtAlarm");this.xtAlarm_arr.pop();}}});// 接收信息成功 堆垛机this.connection.on("ReceiveStackerStk", (message) => {// console.log(message, "接收堆垛机信息成功");//通过总线发送堆垛机实时数据bus.$emit("sendPilerByBus", message);if (message && message.length > 0) {//1#堆垛机 2#堆垛机 3#堆垛机 4#堆垛机var num1ddjObj;var num2ddjObj;var num3ddjObj;var num4ddjObj;//1#虫卵库隐藏的列数var num1ddjObjForkHiddenColumn = [];//2#幼虫库隐藏的列数var num2ddjObjForkHiddenColumn = [];//3#成虫库隐藏的列数var num3ddjObjForkHiddenColumn = [];//4#成虫库隐藏的列数var num4ddjObjForkHiddenColumn = [];message.map((dObj, index) => {//1#堆垛机if (dObj.tunnelId == 1) {num1ddjObj = dObj;if (num1ddjObj) {//显示当前列 frontForkColumnif (num1ddjObj.frontForkColumn != 0) {this.yx_1hddj_arr[`yx_1hddj_` + num1ddjObj.frontForkColumn] =ddjGreen;} else {this.yx_1hddj_arr[yx_1hddj_2] = ddjGreen;}var element = num1ddjObj.frontForkColumn;//隐藏的1#虫卵库 列num1ddjObjForkHiddenColumn = piler_1_Change(element);//隐藏的1#虫卵库 列for (let i = 0; i < num1ddjObjForkHiddenColumn.length; i++) {this.yx_1hddj_arr[`yx_1hddj_` + num1ddjObjForkHiddenColumn[i]] = "";}//显示任务号//任务是什么动作 firstType// 1 -入 (入库) ;2 -出 (出库);3 -移 (移库任务) 4 -输送线用(目前堆垛机用不到);// 5 -转运(直出 移动 堆垛机 从头走到尾部) 0-无任务//单工位同时最多有一个任务号 双工位同时最多有两个任务号//堆垛机类型(1-虫卵库双工位 0-单工位 幼虫库成虫库单工位)//前插(单工位)frontTaskDto.wcsId -任务号//后插(双工位)backTaskDto.wcsId -任务号//任务号 任务类型+任务号组成var taskNumberStr;//前插var froTaskDto;//后插var baTaskDto;if (num1ddjObj.platform == 1) {froTaskDto = num1ddjObj.frontTaskDto;baTaskDto = num1ddjObj.backTaskDto;taskNumberStr =(froTaskDto.firstType == 1? "入:": froTaskDto.firstType == 2? "出:": froTaskDto.firstType == 3? "移:": froTaskDto.firstType == 4? "输送线用:": froTaskDto.firstType == 5? "转运:": "") + froTaskDto.wcsId;taskNumberStr =taskNumberStr +(baTaskDto.firstType == 1? "入:": baTaskDto.firstType == 2? "出:": baTaskDto.firstType == 3? "移:": baTaskDto.firstType == 4? "输送线用:": baTaskDto.firstType == 5? "转运:": "") +baTaskDto.wcsId;} else {froTaskDto = num1ddjObj.frontTaskDto;taskNumberStr =(froTaskDto.firstType == 1? "入:": froTaskDto.firstType == 2? "出:": froTaskDto.firstType == 3? "移:": froTaskDto.firstType == 4? "输送线用:": froTaskDto.firstType == 5? "转运:": "") + froTaskDto.wcsId;}//如果堆垛机有当前列 任务号显示在对应当前列位置上 没有当前列 就显示在堆垛机首个位置if (num1ddjObj.frontForkColumn != 0) {this.yx_1hddj_arr[`yx_1hddj_` + num1ddjObj.frontForkColumn + `_task`] = taskNumberStr;} else {this.yx_1hddj_arr[`yx_1hddj_` + 2 + `_task`] = taskNumberStr;}//隐藏的1#虫卵库 其他任务号for (let i = 0; i < num1ddjObjForkHiddenColumn.length; i++) {this.yx_1hddj_arr[`yx_1hddj_` + num1ddjObjForkHiddenColumn[i] + `_task`] = "";}}//数组新增一条记录删除一条记录会更新domthis.yx_1hddj_arr.push("1#");this.yx_1hddj_arr.pop();}//2#堆垛机if (dObj.tunnelId == 2) {num2ddjObj = dObj;if (num2ddjObj) {//显示当前列 frontForkColumnif (num2ddjObj.frontForkColumn != 0) {this.yx_2hddj_arr[`yx_2hddj_` + num2ddjObj.frontForkColumn] =ddjGreen;} else {this.yx_2hddj_arr[yx_1hddj_1] = ddjGreen;}var element = num2ddjObj.frontForkColumn;//隐藏的2#虫卵库 列num2ddjObjForkHiddenColumn = piler_2_Change(element);//隐藏的2#虫卵库 列for (let i = 0; i < num2ddjObjForkHiddenColumn.length; i++) {this.yx_2hddj_arr[`yx_2hddj_` + num2ddjObjForkHiddenColumn[i]] = "";}//任务号 任务类型+任务号组成var taskNumberStr;//前插var froTaskDto;//后插var baTaskDto;if (num2ddjObj.platform == 1) {froTaskDto = num2ddjObj.frontTaskDto;baTaskDto = num2ddjObj.backTaskDto;taskNumberStr =(froTaskDto.firstType == 1? "入:": froTaskDto.firstType == 2? "出:": froTaskDto.firstType == 3? "移:": froTaskDto.firstType == 4? "输送线用:": froTaskDto.firstType == 5? "转运:": "") + froTaskDto.wcsId;taskNumberStr =taskNumberStr +(baTaskDto.firstType == 1? "入:": baTaskDto.firstType == 2? "出:": baTaskDto.firstType == 3? "移:": baTaskDto.firstType == 4? "输送线用:": baTaskDto.firstType == 5? "转运:": "") +baTaskDto.wcsId;} else {froTaskDto = num2ddjObj.frontTaskDto;taskNumberStr =(froTaskDto.firstType == 1? "入:": froTaskDto.firstType == 2? "出:": froTaskDto.firstType == 3? "移:": froTaskDto.firstType == 4? "输送线用:": froTaskDto.firstType == 5? "转运:": "") + froTaskDto.wcsId;}//如果堆垛机有当前列 任务号显示在对应当前列位置上 没有当前列 就显示在堆垛机首个位置if (num2ddjObj.frontForkColumn != 0) {this.yx_2hddj_arr[`yx_2hddj_` + num2ddjObj.frontForkColumn + `_task`] = taskNumberStr;} else {this.yx_2hddj_arr[`yx_2hddj_` + 1 + `_task`] = taskNumberStr;}//隐藏的2#幼虫库 其他任务号for (let i = 0; i < num2ddjObjForkHiddenColumn.length; i++) {this.yx_2hddj_arr[`yx_2hddj_` + num2ddjObjForkHiddenColumn[i] + `_task`] = "";}}//数组新增一条记录删除一条记录会更新domthis.yx_2hddj_arr.push("2#");this.yx_2hddj_arr.pop();}//3#堆垛机if (dObj.tunnelId == 3) {num3ddjObj = dObj;if (num3ddjObj) {//显示当前列 frontForkColumnif (num3ddjObj.frontForkColumn != 0) {this.yx_3hddj_arr[`yx_3hddj_` + num3ddjObj.frontForkColumn] =ddjGreen;} else {this.yx_3hddj_arr[yx_3hddj_1] = ddjGreen;}var element = num3ddjObj.frontForkColumn;//隐藏的3#虫卵库 列num3ddjObjForkHiddenColumn = piler_3_Change(element);//隐藏的3#虫卵库 列for (let i = 0; i < num3ddjObjForkHiddenColumn.length; i++) {this.yx_3hddj_arr[`yx_3hddj_` + num3ddjObjForkHiddenColumn[i]] = "";}//任务号 任务类型+任务号组成var taskNumberStr;//前插var froTaskDto;//后插var baTaskDto;if (num3ddjObj.platform == 1) {froTaskDto = num3ddjObj.frontTaskDto;baTaskDto = num3ddjObj.backTaskDto;taskNumberStr =(froTaskDto.firstType == 1? "入:": froTaskDto.firstType == 2? "出:": froTaskDto.firstType == 3? "移:": froTaskDto.firstType == 4? "输送线用:": froTaskDto.firstType == 5? "转运:": "") + froTaskDto.wcsId;taskNumberStr =taskNumberStr +(baTaskDto.firstType == 1? "入:": baTaskDto.firstType == 2? "出:": baTaskDto.firstType == 3? "移:": baTaskDto.firstType == 4? "输送线用:": baTaskDto.firstType == 5? "转运:": "") +baTaskDto.wcsId;} else {froTaskDto = num3ddjObj.frontTaskDto;taskNumberStr =(froTaskDto.firstType == 1? "入:": froTaskDto.firstType == 2? "出:": froTaskDto.firstType == 3? "移:": froTaskDto.firstType == 4? "输送线用:": froTaskDto.firstType == 5? "转运:": "") + froTaskDto.wcsId;}//如果堆垛机有当前列 任务号显示在对应当前列位置上 没有当前列 就显示在堆垛机首个位置if (num3ddjObj.frontForkColumn != 0) {this.yx_3hddj_arr[`yx_3hddj_` + num3ddjObj.frontForkColumn + `_task`] = taskNumberStr;} else {this.yx_3hddj_arr[`yx_3hddj_` + 1 + `_task`] = taskNumberStr;}//隐藏的3#成虫库 其他任务号for (let i = 0; i < num3ddjObjForkHiddenColumn.length; i++) {this.yx_3hddj_arr[`yx_3hddj_` + num3ddjObjForkHiddenColumn[i] + `_task`] = "";}}//数组新增一条记录删除一条记录会更新domthis.yx_3hddj_arr.push("3#");this.yx_3hddj_arr.pop();}//4#堆垛机if (dObj.tunnelId == 4) {num4ddjObj = dObj;if (num4ddjObj) {//显示当前列 frontForkColumnif (num4ddjObj.frontForkColumn != 0) {this.yx_4hddj_arr[`yx_4hddj_` + num4ddjObj.frontForkColumn] =ddjGreen;} else {this.yx_4hddj_arr[yx_4hddj_1] = ddjGreen;}//数组新增一条记录删除一条记录会更新domthis.yx_4hddj_arr.push("4#");this.yx_4hddj_arr.pop();var element = num4ddjObj.frontForkColumn;//TODO//隐藏的4#虫卵库 列num4ddjObjForkHiddenColumn = piler_4_Change(element);//隐藏的4#虫卵库 列for (let i = 0; i < num4ddjObjForkHiddenColumn.length; i++) {this.yx_4hddj_arr[`yx_4hddj_` + num4ddjObjForkHiddenColumn[i]] = "";}//任务号 任务类型+任务号组成var taskNumberStr;//前插var froTaskDto;//后插var baTaskDto;if (num4ddjObj.platform == 1) {froTaskDto = num4ddjObj.frontTaskDto;baTaskDto = num4ddjObj.backTaskDto;taskNumberStr =(froTaskDto.firstType == 1? "入:": froTaskDto.firstType == 2? "出:": froTaskDto.firstType == 3? "移:": froTaskDto.firstType == 4? "输送线用:": froTaskDto.firstType == 5? "转运:": "") + froTaskDto.wcsId;taskNumberStr =taskNumberStr +(baTaskDto.firstType == 1? "入:": baTaskDto.firstType == 2? "出:": baTaskDto.firstType == 3? "移:": baTaskDto.firstType == 4? "输送线用:": baTaskDto.firstType == 5? "转运:": "") +baTaskDto.wcsId;} else {froTaskDto = num4ddjObj.frontTaskDto;taskNumberStr =(froTaskDto.firstType == 1? "入:": froTaskDto.firstType == 2? "出:": froTaskDto.firstType == 3? "移:": froTaskDto.firstType == 4? "输送线用:": froTaskDto.firstType == 5? "转运:": "") + froTaskDto.wcsId;}//如果堆垛机有当前列 任务号显示在对应当前列位置上 没有当前列 就显示在堆垛机首个位置if (num4ddjObj.frontForkColumn != 0) {this.yx_4hddj_arr[`yx_4hddj_` + num4ddjObj.frontForkColumn + `_task`] = taskNumberStr;} else {this.yx_4hddj_arr[yx_4hddj_1_task] = taskNumberStr;}//隐藏的4#成虫库 其他任务号for (let i = 0; i < num4ddjObjForkHiddenColumn.length; i++) {this.yx_4hddj_arr[`yx_4hddj_` + num4ddjObjForkHiddenColumn[i] + `_task`] = "";}}//数组新增一条记录删除一条记录会更新domthis.yx_4hddj_arr.push("4#");this.yx_4hddj_arr.pop();}});}});//自动重连成功后的处理this.connection.onreconnected((connectionId) => {console.log(connectionId, "自动重新连接成功");});// 监听关闭this.connection.onclose((res) => {console.log("监听关闭", res);});// 开始连接this.connection.start().then((res) => {// console.log("启动即时通信成功", res);
        }).catch((err) => {console.log(err);});},

5.index.vue中 mounted() 方法内初始化1号堆垛机数组、2号堆垛机数组、3号堆垛机数组、4号堆垛机数组、告警数组、载具数组、载具任务数组数据名称

以及数据内容。

 mounted() {this.initPanZoom();this.yx_1hddj_arr = [];this.yx_2hddj_arr = [];this.yx_3hddj_arr = [];this.yx_4hddj_arr = [];this.xtAlarm_arr = [];this.xtVehicle_arr = [];this.xtVehicle_task_arr = [];//初始化1#堆垛机 堆垛机列数组 任务数组 从3号位开始 到43号位结束 总共41个列位置(2号位为初始0位)for (let i = 2; i <= 43; i++) {if (i == 2) {this.yx_1hddj_arr[`yx_1hddj_` + i] = ddjGreen;this.yx_1hddj_arr[`yx_1hddj_` + i + `_task`] = "出:0";} else {this.yx_1hddj_arr[`yx_1hddj_` + i] = "";this.yx_1hddj_arr[`yx_1hddj_` + i + `_task`] = "";}}//初始化2#堆垛机 堆垛机列数组 任务数组 从2号位开始 到29号位结束 总共28个列位置(1号位为初始0位)for (let i = 1; i <= 29; i++) {if (i == 1) {this.yx_2hddj_arr[`yx_2hddj_` + i] = ddjGreen;this.yx_2hddj_arr[`yx_2hddj_` + i + `_task`] = "出:0";} else {this.yx_2hddj_arr[`yx_2hddj_` + i] = "";this.yx_2hddj_arr[`yx_2hddj_` + i + `_task`] = "";}}//初始化3#堆垛机 堆垛机列数组 任务数组 从2号位开始 到29号位结束 总共28个列位置(1号位为初始0位)for (let i = 1; i <= 29; i++) {if (i == 1) {this.yx_3hddj_arr[`yx_3hddj_` + i] = ddjGreen;this.yx_3hddj_arr[`yx_3hddj_` + i + `_task`] = "出:0";} else {this.yx_3hddj_arr[`yx_3hddj_` + i] = "";this.yx_3hddj_arr[`yx_3hddj_` + i + `_task`] = "";}}//初始化4#堆垛机 堆垛机列数组 任务数组 从2号位开始 到29号位结束 总共28个列位置 (1号位是初始0位)for (let i = 1; i <= 29; i++) {if (i == 1) {this.yx_4hddj_arr[`yx_4hddj_` + i] = ddjGreen;this.yx_4hddj_arr[`yx_4hddj_` + i + `_task`] = "出:0";} else {this.yx_4hddj_arr[`yx_4hddj_` + i] = "";this.yx_4hddj_arr[`yx_4hddj_` + i + `_task`] = "";}}//初始化线体载具 线体任务  线体告警// 1#虫卵库线体编号1001~1017 2#幼虫库线体编号1018~1040 (生成的线体编号数组中间有个别用不到的线体编号可以忽略)// 3#成虫库 4#成虫库 线体编号2001~2067for (let i = 1001; i <= 1040; i++) {this.xtVehicle_arr[`xtVehicle_` + i] = "";this.xtVehicle_task_arr[`xtVehicle_` + i + `_task`] = "";this.xtAlarm_arr[`xtAlarm_` + i] = "";}for (let i = 2001; i <= 2067; i++) {this.xtVehicle_arr[`xtVehicle_` + i] = "";this.xtVehicle_task_arr[`xtVehicle_` + i + `_task`] = "";this.xtAlarm_arr[`xtAlarm_` + i] = "";}},

6.在<script></script>标签内引入图片

//堆垛机 红
//料箱 笼框 载具
//告警
//堆垛机 绿
import ddjRed from "@/assets/images/svg/堆垛机02_红.png";
import ddjGreen from "@/assets/images/svg/堆垛机02_横向_绿.png";
import xtAlarmRed from "@/assets/images/svg/g告警数据.png";
import xtVehicleGreen from "@/assets/images/svg/linforma_料箱_绿 (2).png";

 

7.index.vue中引入了svg静态堆垛机和线体图,svg图可以拖拽无限放大缩小, 这里可以参考另我的一篇文章《svg可拖拽无限放大缩小》,

感兴趣的可以移步到文章链接查看详情,这里不做展开描述。

<template><div class="allbgc"><div class="contentwid"><!-- // 需要拖动的dom --><div ref="dom" @wheel="wheel"><div class="svgdiv"><svg id="vehicleMonitorId" ref="mysvg" data-name="vehicleMonitorName" xmlns="http://www.w3.org/2000/svg":viewBox="viewboxw"><!-- <title>二楼上层</title> --><g><ellipse class="st0" cx="39.2" cy="106" rx="28.5" ry="32" /><g><g><g><g><g><text transform="matrix(1.2 0 0 1 18.1001 119.2002)" class="st1 st2 st3">1#</text></g></g></g></g></g></g><!-- todo --><!-- 引入4号堆垛机货架 最后10列 19~28列 svg --><!-- <DdjHj /> --><!-- <g id="svgElement"  ></g> --><rect x="81.2" y="889.5" class="st4" width="608.7" height="60.7" /><rect x="81.1" y="890" class="st5" width="60.1" height="60.3" /><line class="st6" x1="81.1" y1="950.3" x2="141.2" y2="890" /><line class="st6" x1="81.1" y1="890" x2="141.2" y2="950.3" /><rect x="142" y="890" class="st5" width="60.1" height="60.3" /><line class="st6" x1="142" y1="950.3" x2="202.1" y2="890" /><line class="st6" x1="142" y1="890" x2="202.1" y2="950.3" /><rect x="202.9" y="890" class="st5" width="60.1" height="60.3" /><line class="st6" x1="202.9" y1="950.3" x2="263" y2="890" />

      </svg>
          <clipPath id="clippath"><rect class="cls-3" x="1729.9" y="837.4" width="45.7" height="35.9" /></clipPath></div></div></div>      

 8.数据刷刷的出来了,上图。

 

 9.补充:上图svg图可以无限放大缩小,图上有600、700个数据点,随意拖拽不卡顿。查看详情看笔者另一篇文章《svg可拖拽无限放大缩小》 

    文章链接:

 

参考文档:https://learn.microsoft.com/zh-cn/aspnet/core/signalr/javascript-client?view=aspnetcore-8.0&tabs=visual-studio

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/776054.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Zotero如何引用参考文献(尤其是如何能够自动识别中文文献)

一、软件及插件安装 首先进入zotero官网 Zotero | Your personal research assistant 点击下载下载安装zotero 6 for windows(我用的是windows)和zotero connector(我用的Edge浏览器,安装这个插件可以自动识别读取网页上的文献信息) 安装zotero后显示如下:安装好后在off…

P5017 [NOIP2018 普及组] 摆渡车

讲解 P5017 [NOIP2018 普及组] 摆渡车。考虑动态规划算法,使用前缀和,缩小转移范围来进行优化。思路: 考虑动态规划。 定义 \(dp_i\) 表示若有一班车在第 \(i\) 个时间出发所有人等待的时间,则状态转移方程为: \[dp_i = dp_j + \operatorname{get}(j+1,i)(j \le i - m) \]…

.NET 结果与错误处理利器 FluentResults

前言 在项目开发中,方法返回的结果(成功或失败)对我们开发来说很重要。传统方法,如通过异常来指示错误或使用特定的返回类型(如布尔值加输出参数),虽然有效,但可能缺乏直观性和灵活性。 FluentResults库应运而生,它以一种既流畅又富有表达力的方式,极大地优化了这一过…

c# chart缩放,局部放大问题

左键划选放大区域,右键恢复/// <summary>/// 初始化,传入要进行初始化的chart/// </summary>/// <param name="chart1"></param>public static void InitChart (System.Windows.Forms.DataVisualization.Charting.Chart chart1){//开启缩放…

Charles证书一年过去后怎么处理?

1、删除证书 windows--》设置--》搜索(管理证书)--》右键删除2、重置证书3、重新安装证书 安装完后重启charles

阿里云CentOS7.x ECS云盘在线扩容操作

说明这里只介绍如何在线扩容 操作系统:CentOS 7.x 以下操作实现给200G云盘扩容至300G;操作步骤 创建快照 找到需要扩容的云盘,创建快照,避免扩容出问题数据丢失,阿里云快照是收付费的,快照时长设置1天即可;操作比较简。磁盘创建快照创建快照配置截图(保留时间设置1天)…

【BUUCTF】AreUSerialz

【BUUCTF】AreUSerialz (反序列化) 题目来源 收录于:BUUCTF  网鼎杯 2020 青龙组 题目描述 根据PHP代码进行反序列化 <?phpinclude("flag.php");highlight_file(__FILE__);class FileHandler {protected $op;protected $filename;protected $content;fu…

什么情况下你能接受 996

要是有更高的工资或者更好的学习机会,你会自愿接受“996”吗?文中还有粉丝投稿面经的详解,赶快来看看吧。在当下的职场环境中,996 工作制一直是一个备受争议的话题。“996”是一种工作制度的代称,指的是工作日早上 9 点上班,晚上 9 点下班,中午和傍晚休息 1 小时(或不到…

el-progress 自定义线状进度条右边的文字

需要展示类似下面的效果 搜了很多slot的方式试了都不行,好像是因为我后面的文字太长了导致了换行,加上这边需要加其他的样式,最后干脆将原始的文字变成空的,自己写右边的文字加样式了<divstyle="margin: 10px 0 20px 0"v-for="item in deptdata":ke…

SemanticKernel/C#:检索增强生成(RAG)简易实践

本文介绍了基于SemanticKernel/C#的检索增强生成(RAG)简易实践。检索增强生成(RAG)是什么? RAG是“Reference-based Generative model with Attention”的缩写,也可以被称为“Retrieval-Augmented Generation”,是一种结合了检索技术和生成模型的方法,主要用于自然语言处理…

docker-compose搭建elk

一、准备检查自己的docker 和 docker-compose是否安装完毕,切换docker的镜像源二、安装本次安装的主要组件 包括es 、filebeat、kibana、logstash2.1 先配置组件的挂载点 2.2 配置各组件的相关配置文件es-->config---&g…

save-all-resources | 将指定页面的所有资源存到本地 | chrome插件推荐

save-all-resources https://chromewebstore.google.com/detail/save-all-resources/abpdnfjocnmdomablahdcfnoggeeiedb使用方法: F12 右边选择 ResourceSaver点击右边的 Save All Resources 按钮即可--------------------------------------------- 生活的意义就是你自己知道…