新增单次解算缓存服务和页面控制类
- 新增 GnssSingleBufferService 服务类,用于持久化保存单次解算的结果 - 新增单次解算有关的页面控制类和前端页面
This commit is contained in:
parent
27783443c2
commit
905796a7ea
@ -3,16 +3,14 @@ package com.imdroid.sideslope.calc;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.imdroid.common.util.DataTypeUtil;
|
||||
import com.imdroid.common.util.ThreadManager;
|
||||
import com.imdroid.secapi.dto.GnssCalcData;
|
||||
import com.imdroid.secapi.dto.GnssCalcDataMapper;
|
||||
import com.imdroid.secapi.dto.GnssGroupCalc;
|
||||
import com.imdroid.secapi.dto.GnssGroupCalcMapper;
|
||||
import com.imdroid.secapi.dto.*;
|
||||
import com.imdroid.sideslope.bd.*;
|
||||
import com.imdroid.sideslope.message.D341LocationMessage;
|
||||
import com.imdroid.sideslope.sal.Device;
|
||||
import com.imdroid.sideslope.sal.DeviceService;
|
||||
import com.imdroid.sideslope.server.DeviceChannel;
|
||||
import com.imdroid.sideslope.server.OnlineChannels;
|
||||
import com.imdroid.sideslope.service.GnssSingleBufferService;
|
||||
import com.imdroid.sideslope.service.WarningService;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
@ -56,6 +54,9 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
|
||||
@Autowired
|
||||
GnssCalcDataMapper dataMapper;
|
||||
|
||||
@Autowired
|
||||
private GnssSingleBufferService gnssSingleDataService;
|
||||
|
||||
// 非线程安全,需加同步保护
|
||||
List<GnssGroupCalc> groupCalcList;
|
||||
|
||||
@ -121,21 +122,27 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
|
||||
|
||||
// 读取惯导
|
||||
Tilt tilt = message.getTilt();
|
||||
|
||||
if(tilt != null) {
|
||||
focusCalculator.addTilt(tilt);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("测站{}惯导单次解析结果:{}", deviceId,tilt);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// 延迟
|
||||
focusCalculator.addDelayMs(message.getPps());
|
||||
|
||||
|
||||
|
||||
// 单次b562
|
||||
double[] doubles = message.getB562_loc();//unit: mm
|
||||
if(doubles !=null) {
|
||||
focusCalculator.addXyz(doubles, message.getCreateTime());
|
||||
logger.info("测站{}的b562单次解析结果:{}", deviceId,Arrays.toString(doubles));
|
||||
|
||||
}
|
||||
|
||||
// 单次GGA
|
||||
@ -144,11 +151,39 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
|
||||
focusCalculator.addGGA(gga);
|
||||
logger.info("测站{}的gga单次解析结果:{},{},{},{}",deviceId,
|
||||
gga.getLongitude(), gga.getLatitude(), gga.getAltitude(), gga.getQuality());
|
||||
|
||||
|
||||
if(groupCalc.getVer() == 7 && focusCalculator.isJump()){
|
||||
logger.info("{}发生周跳",deviceId);
|
||||
hardResetDevice(deviceId);
|
||||
}
|
||||
}
|
||||
|
||||
// 保存单次解析的原始数据,受 loggingmode 字段控制
|
||||
GnssSingleData gnssSingleData = new GnssSingleData();
|
||||
gnssSingleData.setDeviceid(device.getDeviceId());
|
||||
gnssSingleData.setCreatetime(LocalDateTime.now());
|
||||
gnssSingleData.setModel(device.getModel());
|
||||
// 若是该设备开启了日志记录,则保存单次解析的数据
|
||||
if(device.getLoggingmode() == GnssDevice.LOGGING_MODE_FULL){
|
||||
if((device.getModel() == GnssDevice.MODEL_G505) && (doubles !=null)){
|
||||
gnssSingleData.setX(doubles[0]);
|
||||
gnssSingleData.setY(doubles[1]);
|
||||
gnssSingleData.setZ(doubles[2]);
|
||||
gnssSingleData.setStatus((int) doubles[3]);
|
||||
gnssSingleDataService.addData(gnssSingleData);
|
||||
}
|
||||
else if((device.getModel() == GnssDevice.MODEL_G510) && (gga !=null)){
|
||||
gnssSingleData.setX(gga.getLatitude());
|
||||
gnssSingleData.setY(gga.getLongitude());
|
||||
gnssSingleData.setZ(gga.getAltitude());
|
||||
gnssSingleData.setStatus(gga.getQuality());
|
||||
gnssSingleDataService.addData(gnssSingleData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -9,6 +9,7 @@ import com.imdroid.sideslope.message.D3F2StopIndicationMessage;
|
||||
import com.imdroid.sideslope.sal.Device;
|
||||
import com.imdroid.sideslope.sal.DeviceService;
|
||||
import com.imdroid.sideslope.service.DataPersistService;
|
||||
import com.imdroid.sideslope.service.GnssSingleBufferServiceImpl;
|
||||
import com.imdroid.sideslope.service.WarningService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -39,6 +40,9 @@ public class D3F2StopIndicationMessageExecutor implements Executor<D3F2StopIndic
|
||||
@Autowired
|
||||
WarningService warningService;
|
||||
|
||||
@Autowired
|
||||
GnssSingleBufferServiceImpl gnssSingleBufferService;
|
||||
|
||||
@Override
|
||||
public Void execute(D3F2StopIndicationMessage message) {
|
||||
|
||||
@ -63,6 +67,10 @@ public class D3F2StopIndicationMessageExecutor implements Executor<D3F2StopIndic
|
||||
LocalDateTime uploadTime = multiLineGNSSCalcService.checkUploadTime(
|
||||
device.getDeviceId(), device.getTenantId());
|
||||
dataPersistService.saveDeviceTrxStat(message, (uploadTime!=null), device);
|
||||
|
||||
// 保存缓存中的 GNSS 单次解析结果
|
||||
gnssSingleBufferService.flush();
|
||||
|
||||
// 通知beidou服务设备休眠
|
||||
try {
|
||||
beidouClient.onDeviceStop(deviceId, device.getTenantId());
|
||||
|
||||
@ -30,6 +30,7 @@ public class DbDeviceServiceImpl implements DeviceService {
|
||||
device.setTenantId(gnssDevice.getTenantid());
|
||||
device.setDeviceId(gnssDevice.getDeviceid());
|
||||
device.setDeviceType(gnssDevice.getDevicetype());
|
||||
device.setModel(gnssDevice.getModel());
|
||||
device.setParentId(gnssDevice.getParentid());
|
||||
device.setName(gnssDevice.getName());
|
||||
device.setProjectId(gnssDevice.getProject_id());
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
package com.imdroid.sideslope.service;
|
||||
|
||||
import com.imdroid.secapi.dto.GnssSingleData;
|
||||
|
||||
public interface GnssSingleBufferService {
|
||||
void addData(GnssSingleData data);
|
||||
void flush();
|
||||
void clear();
|
||||
int getBufferSize();
|
||||
}
|
||||
@ -0,0 +1,84 @@
|
||||
package com.imdroid.sideslope.service;
|
||||
|
||||
import com.imdroid.secapi.dto.GnssSingleData;
|
||||
import com.imdroid.secapi.dto.GnssSingleDataMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class GnssSingleBufferServiceImpl implements GnssSingleBufferService {
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
private final List<GnssSingleData> buffer = new ArrayList<>();
|
||||
|
||||
// BUFFER_SIZE 暂定此大小
|
||||
private static final int BUFFER_SIZE = 1024;
|
||||
// 资源锁
|
||||
private final Object lock = new Object();
|
||||
|
||||
@Autowired
|
||||
private GnssSingleDataMapper gnssDataMapper;
|
||||
|
||||
@Autowired
|
||||
private GnssSingleDataMapper gnssSingleDataMapper;
|
||||
|
||||
@Override
|
||||
public void addData(GnssSingleData data) {
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
synchronized (lock) {
|
||||
buffer.add(data);
|
||||
if (buffer.size() >= BUFFER_SIZE) {
|
||||
// 溢出时直接保存
|
||||
// 此处暂定,但很有必要引入一个线程来保存,避免阻塞主线程
|
||||
flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
synchronized (lock) {
|
||||
if (buffer.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
List<GnssSingleData> batchList = new ArrayList<>(buffer);
|
||||
buffer.clear();
|
||||
// 由于每秒写数据库操作频繁,这里采用批量保存的方式
|
||||
saveBatch(batchList);
|
||||
|
||||
logger.debug("批量插入{}条数据成功", batchList.size());
|
||||
} catch (Exception e) {
|
||||
logger.error("批量插入数据失败", e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void saveBatch(List<GnssSingleData> dataList) {
|
||||
for (GnssSingleData data : dataList) {
|
||||
gnssSingleDataMapper.insert(data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
synchronized (lock) {
|
||||
buffer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBufferSize() {
|
||||
synchronized(lock) {
|
||||
return buffer.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,95 @@
|
||||
package com.imdroid.beidou.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.imdroid.beidou.service.CommonExcelService;
|
||||
import com.imdroid.secapi.dto.GnssCalcData;
|
||||
import com.imdroid.secapi.dto.GnssCalcDataMapper;
|
||||
import com.imdroid.secapi.dto.GnssSingleData;
|
||||
import com.imdroid.secapi.dto.GnssSingleDataMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
@Controller
|
||||
public class GnssSingleDataController extends BasicController implements CommonExcelService<GnssSingleData, GnssSingleData> {
|
||||
|
||||
@Autowired
|
||||
GnssSingleDataMapper gnssSingleDataMapper;
|
||||
|
||||
final DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
|
||||
@RequestMapping("/page/gnss_single_data")
|
||||
public String gnssSingleData(Model m, HttpSession session){
|
||||
initModel(m, session);
|
||||
|
||||
return "/page/gnss_single_data";
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping("/gnss/data/list_single_data")
|
||||
@ResponseBody
|
||||
public JSONObject listData(HttpSession session, Integer page, Integer limit, String searchParams) {
|
||||
// 检查查询条件
|
||||
JSONObject search = null;
|
||||
if (searchParams != null) {
|
||||
search = (JSONObject) JSONObject.parse(searchParams);
|
||||
System.out.println(search);
|
||||
String deviceId = search.getString("deviceid");
|
||||
Integer freqency = search.getInteger("freqency");
|
||||
String begin = search.getString("dgt_.createtime");
|
||||
String end = search.getString("dlt_.createtime");
|
||||
|
||||
if(deviceId != null && !deviceId.isEmpty() && freqency!=0){
|
||||
Page pageable = new Page<>(page == null ? 1 : page, limit == null ? 10 : limit);
|
||||
|
||||
// 缺省按1小时采样,如果时间跨度较大,则按最多300条记录的采样率采样
|
||||
int sample = 6;
|
||||
|
||||
if(freqency == 2){
|
||||
LocalDateTime endTime = LocalDateTime.now();
|
||||
LocalDateTime beginTime = endTime.minusDays(30);
|
||||
if(begin!=null && !begin.isEmpty()){
|
||||
beginTime = LocalDateTime.parse(begin,df);
|
||||
}
|
||||
if(end!=null && !end.isEmpty()){
|
||||
endTime = LocalDateTime.parse(end,df);
|
||||
}
|
||||
Duration duration = Duration.between(beginTime, endTime);
|
||||
int hours = (int)duration.toHours();
|
||||
if(hours > 300) sample = hours*6/300;
|
||||
}
|
||||
Page<GnssSingleData> calcDataList = gnssSingleDataMapper.queryByDeviceId(pageable, deviceId,begin,end,sample);
|
||||
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("code", 0);
|
||||
jsonObject.put("msg", "");
|
||||
jsonObject.put("count", calcDataList.getTotal());
|
||||
jsonObject.put("data", calcDataList.getRecords());
|
||||
return jsonObject;
|
||||
}
|
||||
}
|
||||
|
||||
return this.pageList(session, page, limit, searchParams);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class<GnssSingleData> getEntityClass() {
|
||||
return GnssSingleData.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseMapper<GnssSingleData> getMapper() {
|
||||
return gnssSingleDataMapper;
|
||||
}
|
||||
}
|
||||
@ -53,6 +53,12 @@
|
||||
"icon": "fa fa-calculator",
|
||||
"target": "_self"
|
||||
},
|
||||
{
|
||||
"title": "单次解算记录",
|
||||
"href": "page/gnss_single_data",
|
||||
"icon": "fa fa-clipboard",
|
||||
"target": "_self"
|
||||
},
|
||||
{
|
||||
"title": "配置管理",
|
||||
"href": "",
|
||||
|
||||
@ -0,0 +1,249 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>单次解算记录</title>
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<link rel="stylesheet" href="../lib/layui-v2.6.3/css/layui.css" media="all">
|
||||
<link rel="stylesheet" href="../css/public.css" media="all">
|
||||
</head>
|
||||
<body>
|
||||
<div class="layuimini-container">
|
||||
<div class="layuimini-main">
|
||||
<fieldset class="table-search-fieldset">
|
||||
<legend>搜索信息</legend>
|
||||
<div style="margin: 10px 10px 10px 10px">
|
||||
<form class="layui-form layui-form-pane" action="" id="searchFrm">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">设备号</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="deviceid" id="input_deviceid" class="layui-input" style="position:absolute;z-index:2;width:85%;" value="" autocomplete="off">
|
||||
<select id="deviceid" lay-search="" lay-filter="device" >
|
||||
<option value="">全部</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">范围</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="dgt_createtime" autocomplete="off" id="ID-laydate-start-date" class="layui-input" placeholder="开始日期">
|
||||
</div>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="dlt_createtime" autocomplete="off" id="ID-laydate-end-date" class="layui-input" placeholder="结束日期">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">粒度</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="freqency" id="freqency" lay-search="">
|
||||
<option value="0">次</option>
|
||||
<option value="1">小时</option>
|
||||
<option value="2">自动</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-inline">
|
||||
<button type="submit" class="layui-btn layui-btn-primary" lay-submit lay-filter="data-search-btn"><i class="layui-icon"></i> 搜 索</button>
|
||||
<button type="submit" class="layui-btn layui-btn-primary" lay-submit lay-filter="data-export-btn"><i class="layui-icon"></i>导出</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div class="layui-tab layui-tab-card" lay-filter="data-tab">
|
||||
<ul class="layui-tab-title">
|
||||
<li class="layui-this">数据表格</li>
|
||||
<li>单个设备曲线</li>
|
||||
</ul>
|
||||
<div class="layui-tab-content">
|
||||
<div class="layui-tab-item layui-show">
|
||||
<table class="layui-hide" id="currentTableId" lay-filter="currentTableFilter"></table>
|
||||
</div>
|
||||
<div class="layui-tab-item">
|
||||
<div id="echarts-gnss" style="min-height:300px;padding: 10px"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/html" id="currentTableBar">
|
||||
<a class="layui-btn layui-btn-normal layui-btn-xs data-count-edit" lay-event="cmd">命令行</a>
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
<script src="../js/lay-module/echarts/echartsTheme.js" charset="utf-8"></script>
|
||||
<script src="../js/lay-module/echarts/echarts.js" charset="utf-8"></script>
|
||||
<script src="../lib/layui-v2.6.3/layui.js" charset="utf-8"></script>
|
||||
<script th:inline="javascript">
|
||||
layui.use(['form', 'table','laydate','element'], function () {
|
||||
var $ = layui.$,
|
||||
form = layui.form,
|
||||
table = layui.table,
|
||||
laydate = layui.laydate;
|
||||
var searchDeviceId = false;
|
||||
var echartsDevice = echarts.init(document.getElementById('echarts-gnss'), 'walden');
|
||||
var data_cols = [
|
||||
{field: 'deviceid', title: '设备号'},
|
||||
{field: 'createtime', title: '产生时间', width:'18%', templet: "<div>{{layui.util.toDateString(d.createtime, 'yyyy-MM-dd HH:mm:ss')}}</div>"},
|
||||
{field: 'x', title: '东'},
|
||||
{field: 'y', title: '北'},
|
||||
{field: 'z', title: '天'},
|
||||
{field: 'status', title: '状态'}
|
||||
];
|
||||
/**
|
||||
* 初始化表单,要加上,不然刷新部分组件可能会不加载
|
||||
*/
|
||||
form.render();
|
||||
|
||||
laydate.render({
|
||||
elem: '#ID-laydate-start-date',
|
||||
type: 'datetime'
|
||||
});
|
||||
laydate.render({
|
||||
elem: '#ID-laydate-end-date',
|
||||
type: 'datetime'
|
||||
});
|
||||
|
||||
table.render({
|
||||
elem: '#currentTableId',
|
||||
url: '/gnss/data/list_single_data',
|
||||
toolbar: '#toolbarDemo', //开启头部工具栏
|
||||
defaultToolbar: ['filter'],
|
||||
cols: [
|
||||
data_cols
|
||||
],
|
||||
limits: [20, 50, 100, 200, 300],
|
||||
limit: 20,
|
||||
page: true,
|
||||
skin: 'line',
|
||||
done: function (result, curr, count) {
|
||||
if(searchDeviceId){
|
||||
console.log(result.data);
|
||||
showChart(result.data)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 监听搜索操作
|
||||
form.on('submit(data-search-btn)', function (data) {
|
||||
var result = JSON.stringify(data.field);
|
||||
var deviceId = $('#input_deviceid').val();
|
||||
searchDeviceId = !isNaN(deviceId);
|
||||
//执行搜索重载
|
||||
table.reload('currentTableId', {
|
||||
page: {
|
||||
curr: 1
|
||||
}
|
||||
, where: {
|
||||
searchParams: result
|
||||
}
|
||||
}, 'data');
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// 监听导出操作
|
||||
form.on('submit(data-export-btn)', function (data) {
|
||||
var result = $('#searchFrm').serialize();
|
||||
var u = "/gnss/data/calc/export?" + result;
|
||||
window.open(u, "_blank");
|
||||
return false;
|
||||
});
|
||||
|
||||
form.on('select(device)', function (data) {
|
||||
//对select和input进行监控渲染
|
||||
if (data.value != "") {
|
||||
$("#input_deviceid").val(data.value);
|
||||
}
|
||||
});
|
||||
|
||||
//监听Tab切换,重新resize图表,否则显示不出来
|
||||
layui.element.on('tab(data-tab)', function(data){
|
||||
if (data.index == 1) {
|
||||
echartsDevice.resize();
|
||||
}
|
||||
});
|
||||
|
||||
function showChart(chartData){
|
||||
var sortedData = chartData.sort((a, b) => new Date(a.createtime) - new Date(b.createtime));
|
||||
// 处理数据
|
||||
var times = sortedData.map(item => {
|
||||
let date = new Date(item.createtime);
|
||||
return date.toLocaleTimeString();
|
||||
});
|
||||
var xValues = sortedData.map(item => item.x);
|
||||
var yValues = sortedData.map(item => item.y);
|
||||
var zValues = sortedData.map(item => item.z);
|
||||
|
||||
// 图表配置
|
||||
var option = {
|
||||
title: {
|
||||
text: 'GNSS 单次解记录',
|
||||
left: 'center'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
formatter: function(params) {
|
||||
let result = params[0].name + '<br/>';
|
||||
params.forEach(param => {
|
||||
result += param.seriesName + ': ' +
|
||||
param.value.toFixed(2) + '<br/>';
|
||||
});
|
||||
return result;
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
data: ['X坐标', 'Y坐标', 'Z坐标'],
|
||||
top: '30px'
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: times,
|
||||
axisLabel: {
|
||||
rotate: 45
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
formatter: '{value}'
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'X坐标',
|
||||
type: 'line',
|
||||
data: xValues,
|
||||
smooth: true,
|
||||
},
|
||||
{
|
||||
name: 'Y坐标',
|
||||
type: 'line',
|
||||
data: yValues,
|
||||
smooth: true,
|
||||
},
|
||||
{
|
||||
name: 'Z坐标',
|
||||
type: 'line',
|
||||
data: zValues,
|
||||
smooth: true,
|
||||
}
|
||||
]
|
||||
};
|
||||
echartsDevice.setOption(option);
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
x
Reference in New Issue
Block a user