Commit f92508d1 authored by wanli's avatar wanli

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

parent 2c317d70
''' '''
Author: your name Author: your name
Date: 2021-06-29 19:24:32 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 LastEditors: Please set LastEditors
Description: In User Settings Edit Description: In User Settings Edit
FilePath: \evm-store\backend\controller\monitor.py FilePath: \evm-store\backend\controller\monitor.py
''' '''
from application.app import db from application.app import db
from models.device import DeviceModel
from models.monitorEvm import MonitorEvmModel from models.monitorEvm import MonitorEvmModel
from models.monitorImage import MonitorImageModel from models.monitorImage import MonitorImageModel
from models.monitorLvgl import MonitorLvglModel from models.monitorLvgl import MonitorLvglModel
from models.monitorSystem import MonitorSystemModel from models.monitorSystem import MonitorSystemModel
from models.monitorWatch import MonitorWatchModel from webcreator.log import logger
class SystemResource(object): class SystemResource(object):
def get(self): def get(self):
...@@ -58,7 +59,7 @@ class ImageResource(object): ...@@ -58,7 +59,7 @@ class ImageResource(object):
t = [] t = []
for a in array: for a in array:
a.update({ "watch": watch }) a.update({ "watch": watch })
t.append(**a) t.append(a)
db.session.execute(MonitorImageModel.__table__.insert(), t) db.session.execute(MonitorImageModel.__table__.insert(), t)
db.session.commit() db.session.commit()
...@@ -73,11 +74,11 @@ def insert_data(msg): ...@@ -73,11 +74,11 @@ def insert_data(msg):
# 先判断手表imei是否存在,不存在则先注册手表IMEI # 先判断手表imei是否存在,不存在则先注册手表IMEI
watch_id = -1 watch_id = -1
if msg.get("imei"): 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: if result:
watch_id = result.id watch_id = result.id
else: 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.add(result)
db.session.commit() db.session.commit()
watch_id = result.id watch_id = result.id
...@@ -99,7 +100,7 @@ def insert_data(msg): ...@@ -99,7 +100,7 @@ def insert_data(msg):
imageResource.post_array(msg.get("image"), watch_id) imageResource.post_array(msg.get("image"), watch_id)
def get_watch_list(): def get_watch_list():
result = MonitorWatchModel.query.all() result = DeviceModel.query.all()
tmp = [] tmp = []
for item in result: for item in result:
tmp.append({ tmp.append({
...@@ -158,7 +159,7 @@ def image_data(watch, start, end): ...@@ -158,7 +159,7 @@ def image_data(watch, start, end):
def get_monitor_list(watch, category, start, end): def get_monitor_list(watch, category, start, end):
# 判断watch是否存在 # 判断watch是否存在
w = MonitorWatchModel.query.filter(MonitorWatchModel.id==watch).first() w = DeviceModel.query.filter(DeviceModel.id==watch).first()
if not w: if not w:
return [] 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 #!/usr/bin/env python
# -*- coding: utf_8 -*- # -*- coding: utf_8 -*-
from datetime import datetime from datetime import datetime
from application.app import db from application.app import db
from models.monitorWatch import MonitorWatchModel from models.device import DeviceModel
from webcreator.log import logger from webcreator.log import logger
from webcreator.response import ResponseCode from webcreator.response import ResponseCode
...@@ -13,8 +21,8 @@ class MonitorWatchResource(object): ...@@ -13,8 +21,8 @@ class MonitorWatchResource(object):
def get(self, uuid, params): def get(self, uuid, params):
# handle business # handle business
filters = [MonitorWatchModel.is_delete==False, MonitorWatchModel.uuid==uuid] filters = [DeviceModel.is_delete==False, DeviceModel.uuid==uuid]
result = MonitorWatchModel.query.filter(*filters).first() result = DeviceModel.query.filter(*filters).first()
if result: if result:
return result, ResponseCode.HTTP_SUCCESS return result, ResponseCode.HTTP_SUCCESS
return None, ResponseCode.HTTP_NOT_FOUND return None, ResponseCode.HTTP_NOT_FOUND
...@@ -22,8 +30,8 @@ class MonitorWatchResource(object): ...@@ -22,8 +30,8 @@ class MonitorWatchResource(object):
def getList(self, params): def getList(self, params):
# handle business # handle business
logger.warn(params) logger.warn(params)
filters = [MonitorWatchModel.is_delete==False] filters = [DeviceModel.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) result = DeviceModel.query.filter(*filters).order_by(DeviceModel.create_at).paginate(params.get('page', 1), params.get('pageSize', 10), error_out=False)
if result: if result:
return result, ResponseCode.HTTP_SUCCESS return result, ResponseCode.HTTP_SUCCESS
...@@ -31,7 +39,7 @@ class MonitorWatchResource(object): ...@@ -31,7 +39,7 @@ class MonitorWatchResource(object):
def post(self, params, jwt={}): def post(self, params, jwt={}):
# handle business # 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: if result and result.is_delete:
result.is_delete = False result.is_delete = False
result.update_by = jwt.get("id", "") result.update_by = jwt.get("id", "")
...@@ -41,14 +49,14 @@ class MonitorWatchResource(object): ...@@ -41,14 +49,14 @@ class MonitorWatchResource(object):
elif result and result.is_delete == False: elif result and result.is_delete == False:
return False, ResponseCode.HTTP_INVAILD_REQUEST return False, ResponseCode.HTTP_INVAILD_REQUEST
result = MonitorWatchModel(**params) result = DeviceModel(**params)
db.session.add(result) db.session.add(result)
db.session.commit() db.session.commit()
return True, ResponseCode.HTTP_SUCCESS return True, ResponseCode.HTTP_SUCCESS
def put(self, uuid, params, jwt={}): def put(self, uuid, params, jwt={}):
# handle business # handle business
result = MonitorWatchModel.query.filter(MonitorWatchModel.uuid==uuid).first() result = DeviceModel.query.filter(DeviceModel.uuid==uuid).first()
if not result: if not result:
return None, ResponseCode.HTTP_NOT_FOUND return None, ResponseCode.HTTP_NOT_FOUND
...@@ -64,7 +72,7 @@ class MonitorWatchResource(object): ...@@ -64,7 +72,7 @@ class MonitorWatchResource(object):
def delete(self, uuid, jwt={}): def delete(self, uuid, jwt={}):
# handle business # handle business
result = MonitorWatchModel.query.filter(MonitorWatchModel.uuid==uuid).first() result = DeviceModel.query.filter(DeviceModel.uuid==uuid).first()
if not result: if not result:
return False, ResponseCode.HTTP_NOT_FOUND return False, ResponseCode.HTTP_NOT_FOUND
......
''' '''
Author: your name Author: your name
Date: 2021-06-15 17:40:09 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 LastEditors: Please set LastEditors
Description: In User Settings Edit Description: In User Settings Edit
FilePath: \evm-store\tools\resources\manager.py FilePath: \evm-store\tools\resources\manager.py
''' '''
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import signal
from tornado.wsgi import WSGIContainer from tornado.wsgi import WSGIContainer
from tornado.web import Application, FallbackHandler
from tornado.httpserver import HTTPServer from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop from tornado.ioloop import IOLoop
from flask_script import Manager from flask_script import Manager
from flask_migrate import Migrate from flask_migrate import Migrate
from application.app import create_app, db from application.app import create_app, db
from application.config import config from application.config import config
from views.monitor import DeviceMessageHandler, NotifyHandler, WatchHandler
# 根据配置初始化app # 根据配置初始化app
app = create_app(config) app = create_app(config)
migrate = Migrate(app, db) migrate = Migrate(app, db)
manager = Manager(app) manager = Manager(app)
class GracefulExit(SystemExit):
code = 1
def raise_graceful_exit(*args):
IOLoop.current().stop()
print("Gracefully shutdown", args)
raise GracefulExit()
@manager.command @manager.command
def run(): def run():
""" """
...@@ -39,7 +51,21 @@ def debug(): ...@@ -39,7 +51,21 @@ def debug():
To use: python3 manager.py debug To use: python3 manager.py debug
""" """
# app.logger.setLevel(logging.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__': if __name__ == '__main__':
manager.run() manager.run()
This diff is collapsed.
This diff is collapsed.
...@@ -15,22 +15,24 @@ ...@@ -15,22 +15,24 @@
"codemirror": "^5.59.2", "codemirror": "^5.59.2",
"core-js": "^3.9.0", "core-js": "^3.9.0",
"cropperjs": "^1.5.11", "cropperjs": "^1.5.11",
"echarts": "^5.1.2",
"js-cookie": "^2.2.1", "js-cookie": "^2.2.1",
"npm-check-updates": "^11.7.1", "npm-check-updates": "^11.7.1",
"numeral": "^2.0.6", "numeral": "^2.0.6",
"plyr": "^3.6.4", "plyr": "^3.6.4",
"vue": "^2.5.17", "vue": "^2.6.12",
"vue-cli": "^2.9.6", "vue-cli": "^2.9.6",
"vue-codemirror": "^4.0.6", "vue-codemirror": "^4.0.6",
"vue-grid-layout": "^2.3.12",
"vue-i18n": "^8.1.0", "vue-i18n": "^8.1.0",
"vue-router": "^3.0.1", "vue-router": "^3.0.1",
"vuex": "^3.0.1", "vuex": "^3.0.1",
"vuex-router-sync": "^5.0.0" "vuex-router-sync": "^5.0.0"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "^3.0.3", "@vue/cli-plugin-babel": "^3.3.0",
"@vue/cli-plugin-eslint": "^3.0.3", "@vue/cli-plugin-eslint": "^3.3.0",
"@vue/cli-service": "^3.0.3", "@vue/cli-service": "^3.3.0",
"babel-eslint": "^10.1.0", "babel-eslint": "^10.1.0",
"babel-plugin-import": "^1.9.1", "babel-plugin-import": "^1.9.1",
"eslint": "^7.30.0", "eslint": "^7.30.0",
......
/* /*
* @Author: your name * @Author: your name
* @Date: 2021-07-15 09:33:39 * @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 * @LastEditors: Please set LastEditors
* @Description: In User Settings Edit * @Description: In User Settings Edit
* @FilePath: \evm-store\tools\frontend\src\api\openapi.js * @FilePath: \evm-store\tools\frontend\src\api\openapi.js
*/ */
import request from "@/utils/request"; 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) { export function users(params) {
return request({ return request({
url: "https://randomuser.me/api", url: "https://randomuser.me/api",
......
import './index.less'; import "./index.less";
import ThemeColor from './ThemeColor'; import ThemeColor from "./ThemeColor";
import BlockChecbox from './BlockChecbox'; import BlockChecbox from "./BlockChecbox";
import Vue from 'vue';
import { Drawer, Modal, Divider, message } from "ant-design-vue"; import { Drawer, Modal, Divider, message } from "ant-design-vue";
import { mapGetters } from "vuex"; import { mapGetters } from "vuex";
const Body = { const Body = {
props:['title'], props: ["title"],
render: function render() { render: function render() {
var h = arguments[0]; var h = arguments[0];
const { $slots,title } = this const { $slots, title } = this;
return h('div', { style: { marginBottom: 24 } }, [h('h3', { 'class': 'title' }, title), $slots['default']]) 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;
if (key === 'layout') { Vue.use(Drawer)
nextState.contentWidth = value === 'topmenu' ? 'Fixed' : 'Fluid'; Vue.use(Modal)
}
// else if (key === 'fixedHeader' && !value) {
// nextState.autoHideHeader = false;
// }
// console.log(this.settings);
// console.log(nextState);
// this.$store.commit('global/UpdateDefaultSettings', this.s) const SettingDrawer = {
// this.$store.commit('global/UpdateDefaultSettings', nextState) // data: () => ({
// console.log(key); // primaryColor: "#42b983",
// console.log(value); // blockChecbox: "sidemenu"
// message.loading("正在编译主题!", 3); // }),
props: ["collapse"],
computed: {
...mapGetters({
settings: "global/settings",
}),
},
methods: {
changeSetting(key, value) {
const nextState = this.settings;
nextState[key] = value;
this.$store.dispatch('global/defaultSettings',true) if (key === "layout") {
}, nextState.contentWidth = value === "topmenu" ? "Fixed" : "Fluid";
togglerContent() { }
this.$parent.collapse = !this.collapse 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 render() {
const { primaryColor, layout, navTheme } = this.settings const { collapse } = this;
return ( const { primaryColor, layout, navTheme } = this.settings;
<Drawer return (
<Drawer
title="我是一个抽屉" title="我是一个抽屉"
placement="right" placement="right"
closable={false} closable={false}
onClose={this.togglerContent} onClose={this.togglerContent}
visible={collapse} visible={collapse}
width={300} width={300}
> >
<div class="setting-drawer content"> <div class="setting-drawer content">
<Body title={this.$t('app.setting.pagestyle')}> <Body title={this.$t("app.setting.pagestyle")}>
<BlockChecbox <BlockChecbox
list={[ list={[
{ {
key: 'dark', key: "dark",
url: 'https://gw.alipayobjects.com/zos/rmsportal/LCkqqYNmvBEbokSDscrm.svg', url:
title: this.$t('app.setting.pagestyle.dark'), "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', key: "light",
title: this.$t('app.setting.pagestyle.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)}} ]}
/> value={navTheme}
</Body> onChange={(e) => {
<Divider /> this.changeSetting("navTheme", e);
<ThemeColor }}
title={this.$t('app.setting.themecolor')} />
value={primaryColor} </Body>
onChange={e=>{this.changeSetting('primaryColor',e)}} <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')}> <Body title={this.$t("app.setting.navigationmode")}>
<BlockChecbox <BlockChecbox
list={[ list={[
{ {
key: 'sidemenu', key: "sidemenu",
url: 'https://gw.alipayobjects.com/zos/rmsportal/JopDzEhOqwOjeNTXkoje.svg', url:
title: this.$t('app.setting.sidemenu'), "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', key: "topmenu",
title: this.$t('app.setting.topmenu'), url:
style: {paddingLeft: '18px'} "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)}} ]}
/> value={layout}
</Body> onChange={(e) => {
this.changeSetting("layout", e);
}}
/>
</Body>
<Divider /> <Divider />
<p>其它设置</p> <p>其它设置</p>
</div> </div>
</Drawer> </Drawer>
) );
} },
} };
export default SettingDrawer export default SettingDrawer;
\ No newline at end of file
/*
* @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