Commit f92508d1 authored by wanli's avatar wanli

feat(资源监视器): 集成资源监视器功能

parent 2c317d70
'''
Author: your name
Date: 2021-06-29 19:24:32
LastEditTime: 2021-07-12 12:09:34
LastEditTime: 2021-07-20 01:18:45
LastEditors: Please set LastEditors
Description: In User Settings Edit
FilePath: \evm-store\backend\controller\monitor.py
'''
from application.app import db
from models.device import DeviceModel
from models.monitorEvm import MonitorEvmModel
from models.monitorImage import MonitorImageModel
from models.monitorLvgl import MonitorLvglModel
from models.monitorSystem import MonitorSystemModel
from models.monitorWatch import MonitorWatchModel
from webcreator.log import logger
class SystemResource(object):
def get(self):
......@@ -58,7 +59,7 @@ class ImageResource(object):
t = []
for a in array:
a.update({ "watch": watch })
t.append(**a)
t.append(a)
db.session.execute(MonitorImageModel.__table__.insert(), t)
db.session.commit()
......@@ -73,11 +74,11 @@ def insert_data(msg):
# 先判断手表imei是否存在,不存在则先注册手表IMEI
watch_id = -1
if msg.get("imei"):
result = MonitorWatchModel.query.filter_by(imei=msg.get("imei")).one_or_none()
result = DeviceModel.query.filter_by(imei=msg.get("imei")).one_or_none()
if result:
watch_id = result.id
else:
result = MonitorWatchModel.query.filter(MonitorWatchModel.imei==msg.get("imei")).one_or_none()
result = DeviceModel(imei=msg.get("imei"))
db.session.add(result)
db.session.commit()
watch_id = result.id
......@@ -99,7 +100,7 @@ def insert_data(msg):
imageResource.post_array(msg.get("image"), watch_id)
def get_watch_list():
result = MonitorWatchModel.query.all()
result = DeviceModel.query.all()
tmp = []
for item in result:
tmp.append({
......@@ -158,7 +159,7 @@ def image_data(watch, start, end):
def get_monitor_list(watch, category, start, end):
# 判断watch是否存在
w = MonitorWatchModel.query.filter(MonitorWatchModel.id==watch).first()
w = DeviceModel.query.filter(DeviceModel.id==watch).first()
if not w:
return []
......
'''
Author: your name
Date: 2021-07-15 09:33:39
LastEditTime: 2021-07-20 01:18:27
LastEditors: Please set LastEditors
Description: In User Settings Edit
FilePath: \evm-store\tools\build_out\controllers\monitorWatch.py
'''
#!/usr/bin/env python
# -*- coding: utf_8 -*-
from datetime import datetime
from application.app import db
from models.monitorWatch import MonitorWatchModel
from models.device import DeviceModel
from webcreator.log import logger
from webcreator.response import ResponseCode
......@@ -13,8 +21,8 @@ class MonitorWatchResource(object):
def get(self, uuid, params):
# handle business
filters = [MonitorWatchModel.is_delete==False, MonitorWatchModel.uuid==uuid]
result = MonitorWatchModel.query.filter(*filters).first()
filters = [DeviceModel.is_delete==False, DeviceModel.uuid==uuid]
result = DeviceModel.query.filter(*filters).first()
if result:
return result, ResponseCode.HTTP_SUCCESS
return None, ResponseCode.HTTP_NOT_FOUND
......@@ -22,8 +30,8 @@ class MonitorWatchResource(object):
def getList(self, params):
# handle business
logger.warn(params)
filters = [MonitorWatchModel.is_delete==False]
result = MonitorWatchModel.query.filter(*filters).order_by(MonitorWatchModel.create_at).paginate(params.get('page', 1), params.get('pageSize', 10), error_out=False)
filters = [DeviceModel.is_delete==False]
result = DeviceModel.query.filter(*filters).order_by(DeviceModel.create_at).paginate(params.get('page', 1), params.get('pageSize', 10), error_out=False)
if result:
return result, ResponseCode.HTTP_SUCCESS
......@@ -31,7 +39,7 @@ class MonitorWatchResource(object):
def post(self, params, jwt={}):
# handle business
result = MonitorWatchModel.query.filter(MonitorWatchModel.imei == params.get('imei')).first()
result = DeviceModel.query.filter(DeviceModel.imei == params.get('imei')).first()
if result and result.is_delete:
result.is_delete = False
result.update_by = jwt.get("id", "")
......@@ -41,14 +49,14 @@ class MonitorWatchResource(object):
elif result and result.is_delete == False:
return False, ResponseCode.HTTP_INVAILD_REQUEST
result = MonitorWatchModel(**params)
result = DeviceModel(**params)
db.session.add(result)
db.session.commit()
return True, ResponseCode.HTTP_SUCCESS
def put(self, uuid, params, jwt={}):
# handle business
result = MonitorWatchModel.query.filter(MonitorWatchModel.uuid==uuid).first()
result = DeviceModel.query.filter(DeviceModel.uuid==uuid).first()
if not result:
return None, ResponseCode.HTTP_NOT_FOUND
......@@ -64,7 +72,7 @@ class MonitorWatchResource(object):
def delete(self, uuid, jwt={}):
# handle business
result = MonitorWatchModel.query.filter(MonitorWatchModel.uuid==uuid).first()
result = DeviceModel.query.filter(DeviceModel.uuid==uuid).first()
if not result:
return False, ResponseCode.HTTP_NOT_FOUND
......
'''
Author: your name
Date: 2021-06-15 17:40:09
LastEditTime: 2021-06-30 18:09:51
LastEditTime: 2021-07-19 23:46:49
LastEditors: Please set LastEditors
Description: In User Settings Edit
FilePath: \evm-store\tools\resources\manager.py
'''
# -*- coding: utf-8 -*-
import signal
from tornado.wsgi import WSGIContainer
from tornado.web import Application, FallbackHandler
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from flask_script import Manager
from flask_migrate import Migrate
from application.app import create_app, db
from application.config import config
from views.monitor import DeviceMessageHandler, NotifyHandler, WatchHandler
# 根据配置初始化app
app = create_app(config)
migrate = Migrate(app, db)
manager = Manager(app)
class GracefulExit(SystemExit):
code = 1
def raise_graceful_exit(*args):
IOLoop.current().stop()
print("Gracefully shutdown", args)
raise GracefulExit()
@manager.command
def run():
"""
......@@ -39,7 +51,21 @@ def debug():
To use: python3 manager.py debug
"""
# app.logger.setLevel(logging.DEBUG)
app.run(debug=True, port=3000, host='127.0.0.1')
# app.run(debug=True, port=3000, host='127.0.0.1')
wsgi_app = WSGIContainer(app)
application = Application([
(r"/api/v1/evm_store/monitor", DeviceMessageHandler),
(r"/api/v1/evm_store/watch", WatchHandler),
(r"/ws/v1/notify", NotifyHandler),
(r'.*', FallbackHandler, dict(fallback=wsgi_app))
], **{ 'debug': True, })
application.listen(3000, address='127.0.0.1', xheaders=True)
# 主进程退出信号
signal.signal(signal.SIGINT, raise_graceful_exit)
signal.signal(signal.SIGTERM, raise_graceful_exit)
IOLoop.instance().start()
if __name__ == '__main__':
manager.run()
This diff is collapsed.
This diff is collapsed.
......@@ -15,22 +15,24 @@
"codemirror": "^5.59.2",
"core-js": "^3.9.0",
"cropperjs": "^1.5.11",
"echarts": "^5.1.2",
"js-cookie": "^2.2.1",
"npm-check-updates": "^11.7.1",
"numeral": "^2.0.6",
"plyr": "^3.6.4",
"vue": "^2.5.17",
"vue": "^2.6.12",
"vue-cli": "^2.9.6",
"vue-codemirror": "^4.0.6",
"vue-grid-layout": "^2.3.12",
"vue-i18n": "^8.1.0",
"vue-router": "^3.0.1",
"vuex": "^3.0.1",
"vuex-router-sync": "^5.0.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.0.3",
"@vue/cli-plugin-eslint": "^3.0.3",
"@vue/cli-service": "^3.0.3",
"@vue/cli-plugin-babel": "^3.3.0",
"@vue/cli-plugin-eslint": "^3.3.0",
"@vue/cli-service": "^3.3.0",
"babel-eslint": "^10.1.0",
"babel-plugin-import": "^1.9.1",
"eslint": "^7.30.0",
......
/*
* @Author: your name
* @Date: 2021-07-15 09:33:39
* @LastEditTime: 2021-07-19 20:05:01
* @LastEditTime: 2021-07-19 21:02:00
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \evm-store\tools\frontend\src\api\openapi.js
*/
import request from "@/utils/request";
export function getWatchList() {
return request({
url: "/api/v1/monitor/watch",
method: "get",
});
}
export function getMonitorData(params) {
return request({
url: "/api/v1/monitor",
method: "get",
params,
});
}
export function users(params) {
return request({
url: "https://randomuser.me/api",
......
import './index.less';
import ThemeColor from './ThemeColor';
import BlockChecbox from './BlockChecbox';
import "./index.less";
import ThemeColor from "./ThemeColor";
import BlockChecbox from "./BlockChecbox";
import Vue from 'vue';
import { Drawer, Modal, Divider, message } from "ant-design-vue";
import { mapGetters } from "vuex";
const Body = {
props:['title'],
render: function render() {
var h = arguments[0];
const { $slots,title } = this
return h('div', { style: { marginBottom: 24 } }, [h('h3', { 'class': 'title' }, title), $slots['default']])
}
}
const SettingDrawer = {
// data: () => ({
// primaryColor: "#42b983",
// blockChecbox: "sidemenu"
// }),
props: ["collapse"],
computed: {
...mapGetters({
settings: "global/settings",
}),
},
methods: {
changeSetting(key,value) {
const nextState = this.settings;
nextState[key] = value;
props: ["title"],
render: function render() {
var h = arguments[0];
const { $slots, title } = this;
return h("div", { style: { marginBottom: 24 } }, [
h("h3", { class: "title" }, title),
$slots["default"],
]);
},
};
if (key === 'layout') {
nextState.contentWidth = value === 'topmenu' ? 'Fixed' : 'Fluid';
}
// else if (key === 'fixedHeader' && !value) {
// nextState.autoHideHeader = false;
// }
// console.log(this.settings);
// console.log(nextState);
Vue.use(Drawer)
Vue.use(Modal)
// this.$store.commit('global/UpdateDefaultSettings', this.s)
// this.$store.commit('global/UpdateDefaultSettings', nextState)
// console.log(key);
// console.log(value);
// message.loading("正在编译主题!", 3);
const SettingDrawer = {
// data: () => ({
// primaryColor: "#42b983",
// blockChecbox: "sidemenu"
// }),
props: ["collapse"],
computed: {
...mapGetters({
settings: "global/settings",
}),
},
methods: {
changeSetting(key, value) {
const nextState = this.settings;
nextState[key] = value;
this.$store.dispatch('global/defaultSettings',true)
},
togglerContent() {
this.$parent.collapse = !this.collapse
}
if (key === "layout") {
nextState.contentWidth = value === "topmenu" ? "Fixed" : "Fluid";
}
else if (key === 'fixedHeader' && !value) {
nextState.autoHideHeader = false;
}
// console.log(this.settings);
// console.log(nextState);
this.$store.commit('global/UpdateDefaultSettings', this.s)
this.$store.commit('global/UpdateDefaultSettings', nextState)
console.log(key);
console.log(value);
message.loading("正在编译主题!", 3);
this.$store.dispatch("global/defaultSettings", true);
},
togglerContent() {
this.$parent.collapse = !this.collapse;
},
render() {
const { collapse } = this
const { primaryColor, layout, navTheme } = this.settings
return (
<Drawer
title="我是一个抽屉"
placement="right"
closable={false}
onClose={this.togglerContent}
visible={collapse}
width={300}
>
<div class="setting-drawer content">
<Body title={this.$t('app.setting.pagestyle')}>
<BlockChecbox
list={[
{
key: 'dark',
url: 'https://gw.alipayobjects.com/zos/rmsportal/LCkqqYNmvBEbokSDscrm.svg',
title: this.$t('app.setting.pagestyle.dark'),
},
{
key: 'light',
url: 'https://gw.alipayobjects.com/zos/rmsportal/jpRkZQMyYRryryPNtyIC.svg',
title: this.$t('app.setting.pagestyle.light'),
},
]}
value={navTheme}
onChange={e=>{this.changeSetting('navTheme',e)}}
/>
</Body>
<Divider />
<ThemeColor
title={this.$t('app.setting.themecolor')}
value={primaryColor}
onChange={e=>{this.changeSetting('primaryColor',e)}}
/>
},
render() {
const { collapse } = this;
const { primaryColor, layout, navTheme } = this.settings;
return (
<Drawer
title="我是一个抽屉"
placement="right"
closable={false}
onClose={this.togglerContent}
visible={collapse}
width={300}
>
<div class="setting-drawer content">
<Body title={this.$t("app.setting.pagestyle")}>
<BlockChecbox
list={[
{
key: "dark",
url:
"https://gw.alipayobjects.com/zos/rmsportal/LCkqqYNmvBEbokSDscrm.svg",
title: this.$t("app.setting.pagestyle.dark"),
},
{
key: "light",
url:
"https://gw.alipayobjects.com/zos/rmsportal/jpRkZQMyYRryryPNtyIC.svg",
title: this.$t("app.setting.pagestyle.light"),
},
]}
value={navTheme}
onChange={(e) => {
this.changeSetting("navTheme", e);
}}
/>
</Body>
<Divider />
<ThemeColor
title={this.$t("app.setting.themecolor")}
value={primaryColor}
onChange={(e) => {
this.changeSetting("primaryColor", e);
}}
/>
<Divider />
<Divider />
<Body title={this.$t('app.setting.navigationmode')}>
<BlockChecbox
list={[
{
key: 'sidemenu',
url: 'https://gw.alipayobjects.com/zos/rmsportal/JopDzEhOqwOjeNTXkoje.svg',
title: this.$t('app.setting.sidemenu'),
},
{
key: 'topmenu',
url: 'https://gw.alipayobjects.com/zos/rmsportal/KDNDBbriJhLwuqMoxcAr.svg',
title: this.$t('app.setting.topmenu'),
style: {paddingLeft: '18px'}
},
]}
value={layout}
onChange={e=>{this.changeSetting('layout',e)}}
/>
</Body>
<Body title={this.$t("app.setting.navigationmode")}>
<BlockChecbox
list={[
{
key: "sidemenu",
url:
"https://gw.alipayobjects.com/zos/rmsportal/JopDzEhOqwOjeNTXkoje.svg",
title: this.$t("app.setting.sidemenu"),
},
{
key: "topmenu",
url:
"https://gw.alipayobjects.com/zos/rmsportal/KDNDBbriJhLwuqMoxcAr.svg",
title: this.$t("app.setting.topmenu"),
style: { paddingLeft: "18px" },
},
]}
value={layout}
onChange={(e) => {
this.changeSetting("layout", e);
}}
/>
</Body>
<Divider />
<p>其它设置</p>
</div>
</Drawer>
)
}
}
export default SettingDrawer
\ No newline at end of file
<Divider />
<p>其它设置</p>
</div>
</Drawer>
);
},
};
export default SettingDrawer;
/*
* @Author: your name
* @Date: 2021-07-01 15:02:16
* @LastEditTime: 2021-07-19 20:38:32
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \evm-store\frontend\src\utils\eventBus.js
*/
import Vue from "vue";
import { getToken } from "@/utils/auth";
export const wsNotify = new WebSocket(
`ws://${window.location.hostname}:3000/ws/v1/notify`
);
window.wsNotify = wsNotify;
wsNotify.eventBus = new Vue();
let timer = null;
wsNotify.onopen = function (event) {
console.log("websocket is conneted!", event);
wsNotify.eventBus.$emit("open", event);
timer = setInterval(function() {
wsNotify.send(JSON.stringify({ type: 'heartbeat', ts: Date.now(), token: getToken() }))
}, 1000)
};
wsNotify.onmessage = function (event) {
var message = JSON.parse(event.data);
wsNotify.eventBus.$emit("message", message);
};
wsNotify.onerror = function (error) {
console.log(error);
wsNotify.eventBus.$emit("error", error);
if (timer) clearInterval(timer);
};
wsNotify.onclose = function (event) {
console.log("websocket is colosed!", event);
wsNotify.eventBus.$emit("close", event);
if (timer) clearInterval(timer);
};
/*
* @Author: your name
* @Date: 2021-04-14 14:12:19
* @LastEditTime: 2021-07-01 02:12:04
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \evm-store\frontend\src\utils\utils.js
*/
function formatNumber(n) {
n = n.toString();
return n[1] ? n : "0" + n;
}
export function getDateTime(datetime) {
var year = datetime.getFullYear();
var month = datetime.getMonth() + 1;
var day = datetime.getDate();
var hour = datetime.getHours();
var minute = datetime.getMinutes();
var second = datetime.getSeconds();
return [year, month, day, hour, minute, second].map(formatNumber);
}
export function formatDateTime(
datetime = [],
format = ["-", "-", " ", ":", ":"]
) {
let result = "";
datetime.forEach((d, i) => {
result += i < 5 ? d + format[i] : d;
});
return result;
}
export function getDateTimeString(datetime) {
if (!(datetime instanceof Date)) datetime = new Date(datetime);
datetime = getDateTime(datetime);
const format = ["-", "-", " ", ":", ":"];
let result = "";
datetime.forEach((d, i) => {
result += i < 5 ? d + format[i] : d;
});
return result;
}
<template>
<div :class="className" :style="{ height: height, width: width }" />
</template>
<script>
import * as echarts from "echarts";
require("echarts/theme/macarons"); // echarts theme
import resize from "./mixins/resize";
import { getDateTimeString } from "@/utils/utils";
import { wsNotify } from "@/utils/notify.js";
// function randomData() {
// now = new Date(+now + oneDay);
// value = value + Math.random() * 21 - 10;
// return {
// name: "EVM",
// value: [
// [now.getFullYear(), now.getMonth() + 1, now.getDate()].join("/") +
// " " +
// [now.getHours(), now.getMinutes() + 1, now.getSeconds()].join(":"),
// Math.round(value),
// ],
// };
// }
// const dataList = [];
// let now = +new Date(1997, 9, 3);
// const oneDay = 24 * 3600 * 1000;
// var value = Math.random() * 1000;
// for (var i = 0; i < 1000; i++) {
// dataList.push(randomData());
// }
const seriesData = {
heap_total_size: [],
heap_used_size: [],
stack_total_size: [],
stack_used_size: [],
};
export default {
mixins: [resize],
props: {
className: {
type: String,
default: "chart",
},
width: {
type: String,
default: "100%",
},
height: {
type: String,
default: "270px",
},
autoResize: {
type: Boolean,
default: true,
},
chartData: {
type: Object,
required: true,
},
},
data() {
return {
loading: null,
chart: null,
timer: null,
series: [
{
name: "heap_total_size",
type: "line",
max: "dataMax",
showSymbol: false,
emphasis: {
scale: false,
focus: "series",
blurScope: "coordinateSystem",
},
data: seriesData.heap_total_size,
},
{
name: "heap_used_size",
type: "line",
max: "dataMax",
showSymbol: false,
emphasis: {
focus: "series",
blurScope: "coordinateSystem",
},
data: seriesData.heap_used_size,
},
{
name: "stack_total_size",
type: "line",
max: "dataMax",
showSymbol: false,
emphasis: {
focus: "series",
blurScope: "coordinateSystem",
},
data: seriesData.stack_total_size,
},
{
name: "stack_used_size",
type: "line",
max: "dataMax",
showSymbol: false,
emphasis: {
focus: "series",
blurScope: "coordinateSystem",
},
data: seriesData.stack_used_size,
},
],
legendData: Object.keys(seriesData),
};
},
watch: {
chartData: {
deep: true,
handler(val) {
this.handleMessage(val);
},
},
},
mounted() {
this.$nextTick(() => {
this.initChart();
});
wsNotify.eventBus.$on("resize", () => {
if (this.chart) this.chart.resize()
});
},
beforeDestroy() {
if (!this.chart) {
return;
}
this.chart.dispose();
this.chart = null;
},
methods: {
cleanData() {
// 关闭从WebSocket接收数据
// 重置所有数据
Object.keys(seriesData).forEach((key) => {
seriesData[key] = [];
});
this.series.forEach((item) => {
item.data = [];
});
this.chart.setOption({ series: this.series });
},
handleMessage(data) {
if (!data || data.length == 0) this.cleanData()
// 这里面应该增加一个数组长度判断,当超过了多少个之后,弹出数组第一项,防止数组内存溢出
// seriesData[k].shift()
Object.keys(data).forEach((k) => {
var t = getDateTimeString(new Date());
if (k == "timestamp") t = data[k];
if (this.legendData.includes(k)) {
seriesData[k].push({
name: k,
value: [t, data[k]],
});
}
});
this.$nextTick(() => {
this.chart &&
this.chart.setOption({
series: this.series,
});
});
},
initChart() {
this.chart = echarts.init(this.$el, "macarons");
this.setOptions();
},
setOptions() {
this.chart.setOption({
title: {
text: "EVM",
},
xAxis: {
type: "time",
splitLine: {
show: false,
},
// data: xAxisTitle,
// boundaryGap: false,
// axisTick: {
// show: false,
// },
axisLabel: {
formatter: "{HH}:{mm}:{ss}",
},
},
yAxis: {
type: "value",
scale: true,
// boundaryGap: [0, "100%"],
// splitNumber: 10,
splitLine: {
show: false,
},
},
grid: {
left: 10,
right: 10,
bottom: 10,
top: 50,
containLabel: true,
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "cross",
animation: false,
},
// formatter: function (params) {
// params = params[0];
// console.log(params);
// var date = new Date(params.name);
// return (
// date.getDate() +
// "/" +
// (date.getMonth() + 1) +
// "/" +
// date.getFullYear() +
// " : " +
// params.value[1]
// );
// },
padding: [5, 10],
},
legend: {
data: this.legendData,
selected: {
heap_total_size: false,
stack_total_size: false,
stack_used_size: false,
},
},
series: this.series,
});
},
},
};
</script>
<template>
<div :class="className" :style="{ height: height, width: width }" />
</template>
<script>
import * as echarts from "echarts";
require("echarts/theme/macarons");
import resize from "./mixins/resize";
let chart = null
const seriesData = {
heap_total_size: [],
heap_used_size: [],
stack_total_size: [],
stack_used_size: [],
};
export default {
mixins: [resize],
props: {
className: {
type: String,
default: "chart",
},
width: {
type: String,
default: "100%",
},
height: {
type: String,
default: "350px",
},
autoResize: {
type: Boolean,
default: true,
},
dataList: {
type: Array,
required: false,
default: () => [],
},
},
data() {
return {
loading: null,
series: [
{
name: "heap_total_size",
type: "line",
max: "dataMax",
showSymbol: false,
emphasis: {
scale: false,
focus: "series",
blurScope: "coordinateSystem",
},
data: [],
},
{
name: "heap_used_size",
type: "line",
max: "dataMax",
showSymbol: false,
emphasis: {
focus: "series",
blurScope: "coordinateSystem",
},
data: [],
},
{
name: "stack_total_size",
type: "line",
max: "dataMax",
showSymbol: false,
emphasis: {
focus: "series",
blurScope: "coordinateSystem",
},
data: [],
},
{
name: "stack_used_size",
type: "line",
max: "dataMax",
showSymbol: false,
emphasis: {
focus: "series",
blurScope: "coordinateSystem",
},
data: [],
},
],
legendData: Object.keys(seriesData),
};
},
watch: {
dataList: {
deep: true,
handler(val) {
if (val.length > 0) this.handleData(val);
},
},
},
mounted() {
this.$nextTick(() => {
this.initChart();
});
},
beforeDestroy() {
if (!chart) {
return;
}
chart.clear();
chart.dispose();
},
methods: {
handleData(data) {
Object.keys(seriesData).forEach((key) => {
seriesData[key] = [];
});
this.series.forEach((item) => {
item.data = [];
});
// chart.setOption({ series: this.series });
data.forEach((item) => {
this.handleMessage(item);
});
let temp = Object.assign(this.series);
temp.forEach(item => {
if (Object.prototype.hasOwnProperty.call(seriesData, item.name)) {
item.data = seriesData[item.name]
}
});
this.series = temp;
this.$nextTick(() => {
chart &&
chart.setOption({
series: this.series,
});
});
},
handleMessage(data) {
Object.keys(data).forEach((k) => {
if (this.legendData.includes(k)) {
seriesData[k].push({
name: k,
value: [data.timestamp, data[k]],
});
}
});
},
initChart() {
chart = echarts.init(this.$el, "macarons");
this.setOptions();
},
setOptions() {
chart.setOption({
title: {
text: "EVM",
},
xAxis: {
type: "time",
splitLine: {
show: false,
},
// data: xAxisTitle,
// boundaryGap: false,
// axisTick: {
// show: false,
// },
axisLabel: {
formatter: "{HH}:{mm}:{ss}",
},
},
yAxis: {
type: "value",
scale: true,
splitLine: {
show: false,
},
},
// grid: {
// left: 10,
// right: 10,
// bottom: 20,
// top: 30,
// containLabel: true,
// },
tooltip: {
trigger: "axis",
axisPointer: {
type: "cross",
animation: false,
},
// formatter: function (params) {
// params = params[0];
// console.log(params);
// var date = new Date(params.name);
// return (
// date.getDate() +
// "/" +
// (date.getMonth() + 1) +
// "/" +
// date.getFullYear() +
// " : " +
// params.value[1]
// );
// },
padding: [5, 10],
},
legend: {
data: this.legendData,
},
series: this.series,
});
},
},
};
</script>
<template>
<div :class="className" :style="{ height: height, width: width }" />
</template>
<script>
import * as echarts from "echarts";
require("echarts/theme/macarons");
import resize from "./mixins/resize";
// import { getDateTimeString } from "@/utils/utils";
const seriesData = {
heap_total_size: [],
heap_used_size: [],
stack_total_size: [],
stack_used_size: [],
};
var data = [
["2000-06-05", 116],
["2000-06-06", 129],
["2000-06-07", 135],
["2000-06-08", 86],
["2000-06-09", 73],
["2000-06-10", 85],
["2000-06-11", 73],
["2000-06-12", 68],
["2000-06-13", 92],
["2000-06-14", 130],
["2000-06-15", 245],
["2000-06-16", 139],
["2000-06-17", 115],
["2000-06-18", 111],
["2000-06-19", 309],
["2000-06-20", 206],
["2000-06-21", 137],
["2000-06-22", 128],
["2000-06-23", 85],
["2000-06-24", 94],
["2000-06-25", 71],
["2000-06-26", 106],
["2000-06-27", 84],
["2000-06-28", 93],
["2000-06-29", 85],
["2000-06-30", 73],
["2000-07-01", 83],
["2000-07-02", 125],
["2000-07-03", 107],
["2000-07-04", 82],
["2000-07-05", 44],
["2000-07-06", 72],
["2000-07-07", 106],
["2000-07-08", 107],
["2000-07-09", 66],
["2000-07-10", 91],
["2000-07-11", 92],
["2000-07-12", 113],
["2000-07-13", 107],
["2000-07-14", 131],
["2000-07-15", 111],
["2000-07-16", 64],
["2000-07-17", 69],
["2000-07-18", 88],
["2000-07-19", 77],
["2000-07-20", 83],
["2000-07-21", 111],
["2000-07-22", 57],
["2000-07-23", 55],
["2000-07-24", 60],
];
var dateList = data.map(function (item) {
return item[0];
});
var valueList = data.map(function (item) {
return item[1];
});
export default {
mixins: [resize],
props: {
className: {
type: String,
default: "chart",
},
width: {
type: String,
default: "100%",
},
height: {
type: String,
default: "600px",
},
autoResize: {
type: Boolean,
default: true,
},
chartData: {
type: Array,
required: true,
},
},
data() {
return {
chart: null,
series: [
{
name: "heap_total_size",
type: "line",
showSymbol: false,
emphasis: {
scale: false,
focus: "series",
blurScope: "coordinateSystem",
},
data: seriesData.heap_total_size,
},
{
name: "heap_used_size",
type: "line",
showSymbol: false,
emphasis: {
focus: "series",
blurScope: "coordinateSystem",
},
data: seriesData.heap_used_size,
},
{
name: "stack_total_size",
type: "line",
showSymbol: false,
emphasis: {
focus: "series",
blurScope: "coordinateSystem",
},
data: seriesData.stack_total_size,
},
{
name: "stack_used_size",
type: "line",
showSymbol: false,
emphasis: {
focus: "series",
blurScope: "coordinateSystem",
},
data: seriesData.stack_used_size,
},
],
legendData: [
"heap_total_size",
"heap_used_size",
"stack_total_size",
"stack_used_size",
],
options: {
tooltip: {
trigger: "axis",
},
visualMap: [],
title: [],
xAxis: [],
yAxis: [],
grid: [],
series: []
},
};
},
watch: {
chartData: {
deep: true,
handler(val) {
this.handleMessage(val);
},
},
},
mounted() {
this.$nextTick(() => {
this.initChart();
});
},
beforeDestroy() {
if (!this.chart) {
return;
}
this.chart.dispose();
this.chart = null;
},
methods: {
handleMessage(data) {
console.log(data);
// Object.keys(data).forEach((k) => {
// if (this.legendData.includes(k))
// seriesData[k].push({
// name: k,
// value: [getDateTimeString(new Date()), data[k]],
// });
// });
this.$nextTick(() => {
// this.chart &&
// this.chart.setOption({
// series: this.series,
// });
});
},
initChart() {
this.chart = echarts.init(this.$el, "macarons");
this.setOptions();
},
initOption() {},
setOptions() {
this.chart.setOption({
// Make gradient line here
visualMap: [
{
show: false,
type: "continuous",
seriesIndex: 0,
min: 0,
max: 400,
},
{
show: false,
type: "continuous",
seriesIndex: 1,
dimension: 0,
min: 0,
max: dateList.length - 1,
},
],
title: [
{
left: "center",
text: "Gradient along the y axis",
},
{
top: "300px",
left: "center",
text: "Gradient along the x axis",
},
],
tooltip: {
trigger: "axis",
},
xAxis: [
{
data: dateList,
gridIndex: 0,
},
{
data: dateList,
gridIndex: 1,
},
],
yAxis: [
{
gridIndex: 0,
},
{
gridIndex: 1,
},
],
grid: [
{
bottom: "350px",
},
{
top: "350px",
},
],
series: [
{
type: "line",
showSymbol: false,
data: valueList,
xAxisIndex: 0,
yAxisIndex: 0,
},
{
type: "line",
showSymbol: false,
data: valueList,
xAxisIndex: 1,
yAxisIndex: 1,
},
],
});
},
},
};
</script>
<template>
<div :class="className" :style="{ height: height, width: width }" />
</template>
<script>
import * as echarts from "echarts";
require("echarts/theme/macarons"); // echarts theme
import resize from "./mixins/resize";
import { getDateTimeString } from "@/utils/utils";
import { wsNotify } from "@/utils/notify.js";
const seriesData = {
frag_pct: [],
free_biggest_size: [],
free_cnt: [],
free_size: [],
total_size: [],
used_cnt: [],
used_pct: [],
};
export default {
mixins: [resize],
props: {
className: {
type: String,
default: "chart",
},
width: {
type: String,
default: "100%",
},
height: {
type: String,
default: "270px",
},
autoResize: {
type: Boolean,
default: true,
},
chartData: {
type: Object,
required: true,
},
dataList: {
type: Array,
required: false,
default: () => [],
},
},
data() {
return {
chart: null,
series: [
{
name: "frag_pct",
type: "line",
showSymbol: false,
emphasis: {
scale: false,
focus: "series",
blurScope: "coordinateSystem",
},
data: seriesData.frag_pct,
},
{
name: "free_biggest_size",
type: "line",
showSymbol: false,
emphasis: {
focus: "series",
blurScope: "coordinateSystem",
},
data: seriesData.free_biggest_size,
},
{
name: "free_cnt",
type: "line",
showSymbol: false,
emphasis: {
focus: "series",
blurScope: "coordinateSystem",
},
data: seriesData.free_cnt,
},
{
name: "free_size",
type: "line",
showSymbol: false,
emphasis: {
focus: "series",
blurScope: "coordinateSystem",
},
data: seriesData.free_size,
},
{
name: "total_size",
type: "line",
showSymbol: false,
emphasis: {
focus: "series",
blurScope: "coordinateSystem",
},
data: seriesData.total_size,
},
{
name: "used_cnt",
type: "line",
showSymbol: false,
emphasis: {
focus: "series",
blurScope: "coordinateSystem",
},
data: seriesData.used_cnt,
},
{
name: "used_pct",
type: "line",
showSymbol: false,
emphasis: {
focus: "series",
blurScope: "coordinateSystem",
},
data: seriesData.used_pct,
},
],
legendData: [
"frag_pct",
"free_biggest_size",
"free_cnt",
"free_size",
"total_size",
"used_cnt",
"used_pct",
],
};
},
watch: {
chartData: {
deep: true,
handler(val) {
this.handleMessage(val);
},
},
dataList: {
deep: true,
handler(val) {
if (val.length > 0) this.handleData(val);
},
},
},
mounted() {
this.$nextTick(() => {
this.initChart();
});
wsNotify.eventBus.$on("resize", () => {
if (this.chart) this.chart.resize()
});
},
beforeDestroy() {
if (!this.chart) {
return;
}
this.chart.dispose();
this.chart = null;
},
methods: {
handleData(data) {
Object.keys(seriesData).forEach(key => {
seriesData[key] = []
});
this.series.forEach(item => {
item.data = []
});
this.chart.setOption({ series: this.series });
data.forEach((item) => {
this.handleMessage(item);
});
},
handleMessage(data) {
Object.keys(data).forEach((k) => {
var t = getDateTimeString(new Date());
if (k == "timestamp") t = data[k];
if (this.legendData.includes(k))
seriesData[k].push({
name: k,
value: [t, data[k]],
});
});
this.$nextTick(() => {
this.chart &&
this.chart.setOption({
series: this.series,
});
});
},
initChart() {
this.chart = echarts.init(this.$el, "macarons");
this.setOptions();
},
setOptions() {
this.chart.setOption({
title: {
text: "LVGL",
},
grid: {
left: 10,
right: 10,
bottom: 10,
top: 50,
containLabel: true,
},
xAxis: {
type: "time",
splitLine: {
},
axisLabel: {
formatter: "{HH}:{mm}:{ss}",
},
},
yAxis: {
type: "value",
// boundaryGap: [0, "100%"],
splitLine: {
},
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "cross",
animation: false,
},
padding: [5, 10],
},
legend: {
data: this.legendData,
selected: {
frag_pct: false,
free_biggest_size: false,
free_cnt: false,
free_size: false,
total_size: false,
},
},
series: this.series,
});
},
},
};
</script>
<template>
<div :class="className" :style="{ height: height, width: width }" />
</template>
<script>
import * as echarts from "echarts";
require("echarts/theme/macarons");
import resize from "./mixins/resize";
const seriesData = {
frag_pct: [],
free_biggest_size: [],
free_cnt: [],
free_size: [],
total_size: [],
used_cnt: [],
used_pct: [],
};
export default {
mixins: [resize],
props: {
className: {
type: String,
default: "chart",
},
width: {
type: String,
default: "100%",
},
height: {
type: String,
default: "350px",
},
autoResize: {
type: Boolean,
default: true,
},
dataList: {
type: Array,
required: false,
default: () => [],
},
},
data() {
return {
chart: null,
series: [
{
name: "frag_pct",
type: "line",
showSymbol: false,
emphasis: {
scale: false,
focus: "series",
blurScope: "coordinateSystem",
},
data: [],
},
{
name: "free_biggest_size",
type: "line",
showSymbol: false,
emphasis: {
focus: "series",
blurScope: "coordinateSystem",
},
data: [],
},
{
name: "free_cnt",
type: "line",
showSymbol: false,
emphasis: {
focus: "series",
blurScope: "coordinateSystem",
},
data: [],
},
{
name: "free_size",
type: "line",
showSymbol: false,
emphasis: {
focus: "series",
blurScope: "coordinateSystem",
},
data: [],
},
{
name: "total_size",
type: "line",
showSymbol: false,
emphasis: {
focus: "series",
blurScope: "coordinateSystem",
},
data: [],
},
{
name: "used_cnt",
type: "line",
showSymbol: false,
emphasis: {
focus: "series",
blurScope: "coordinateSystem",
},
data: [],
},
{
name: "used_pct",
type: "line",
showSymbol: false,
emphasis: {
focus: "series",
blurScope: "coordinateSystem",
},
data: [],
},
],
legendData: Object.keys(seriesData),
};
},
watch: {
dataList: {
deep: true,
handler(val) {
if (val.length > 0) this.handleData(val);
},
},
},
mounted() {
this.$nextTick(() => {
this.initChart();
});
},
beforeDestroy() {
if (!this.chart) {
return;
}
this.chart.dispose();
this.chart = null;
},
methods: {
handleData(data) {
Object.keys(seriesData).forEach(key => {
seriesData[key] = []
});
this.series.forEach(item => {
item.data = []
});
// this.chart.setOption({ series: this.series });
data.forEach((item) => {
this.handleMessage(item);
});
let temp = Object.assign(this.series);
temp.forEach(item => {
if (Object.prototype.hasOwnProperty.call(seriesData, item.name)) {
item.data = seriesData[item.name]
}
});
this.series = temp;
this.$nextTick(() => {
this.chart &&
this.chart.setOption({
series: this.series,
});
});
},
handleMessage(data) {
Object.keys(data).forEach((k) => {
if (this.legendData.includes(k))
seriesData[k].push({
name: k,
value: [data.timestamp, data[k]],
});
});
},
initChart() {
this.chart = echarts.init(this.$el, "macarons");
this.setOptions();
},
setOptions() {
this.chart.setOption({
title: {
text: "LVGL",
},
xAxis: {
type: "time",
splitLine: {
show: false,
},
axisLabel: {
formatter: "{HH}:{mm}:{ss}",
},
},
yAxis: {
type: "value",
splitLine: {
show: false,
},
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "cross",
animation: false,
},
padding: [5, 10],
},
legend: {
data: this.legendData,
},
series: this.series,
});
},
},
};
</script>
import { debounce } from '@/utils'
export default {
data() {
return {
$_sidebarElm: null,
$_resizeHandler: null
}
},
mounted() {
this.$_resizeHandler = debounce(() => {
if (this.chart) {
this.chart.resize()
}
}, 100)
this.$_initResizeEvent()
this.$_initSidebarResizeEvent()
},
beforeDestroy() {
this.$_destroyResizeEvent()
this.$_destroySidebarResizeEvent()
},
// to fixed bug when cached by keep-alive
// https://github.com/PanJiaChen/vue-element-admin/issues/2116
activated() {
this.$_initResizeEvent()
this.$_initSidebarResizeEvent()
},
deactivated() {
this.$_destroyResizeEvent()
this.$_destroySidebarResizeEvent()
},
methods: {
// use $_ for mixins properties
// https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
$_initResizeEvent() {
window.addEventListener('resize', this.$_resizeHandler)
},
$_destroyResizeEvent() {
window.removeEventListener('resize', this.$_resizeHandler)
},
$_sidebarResizeHandler(e) {
if (e.propertyName === 'width') {
this.$_resizeHandler()
}
},
$_initSidebarResizeEvent() {
this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
},
$_destroySidebarResizeEvent() {
this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment