提交系统管理web端代码

This commit is contained in:
lixiaoyuan
2025-07-18 09:09:30 +08:00
parent 7b3f32f334
commit 387237c81c
74 changed files with 1997 additions and 918 deletions

View File

@@ -0,0 +1,454 @@
/* 自定义滚动条样式 */
div::-webkit-scrollbar {
width: 12px;
}
div::-webkit-scrollbar-thumb {
background-color: #08536e60;
border-radius: 4px;
}
div::-webkit-scrollbar-track {
background-color: #60606060;
}
/******************************************************************************************************/
.dt-container {
color: white;
font-size: 14px;
padding-left: 0px;
}
/* div.dt-container .dt-paging {
margin-top: 10px;
} */
.dt-paging {
color: white;
margin-left: 0px;
}
div.dt-container .dt-paging .dt-paging-button {
line-height: 28px;
/* width: 32px; */
padding: 0 0px 0 0;
border: 1px solid white;
margin-right: 5px;
padding: 0 10px 0 10px;
}
div.dt-container .dt-paging .dt-paging-button.disabled,
div.dt-container .dt-paging .dt-paging-button.disabled:hover,
div.dt-container .dt-paging .dt-paging-button.disabled:active {
color: white !important;
border: 1px solid gray;
}
div.dt-container .dt-paging .dt-paging-button.current {
background: linear-gradient(to bottom, #1c797a 0%, #1c797a 100%);
}
div.dt-container .dt-paging .dt-paging-button.current:hover {
background: linear-gradient(to bottom, #1c797a 0%, #1c797a 100%);
}
div.dt-container .dt-paging .dt-paging-button:hover {
color: white !important;
border: 1px solid #111;
background-color: #111;
/* Chrome,Safari4+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111));
/* Chrome10+,Safari5.1+ */
background: -webkit-linear-gradient(top, #585858 0%, #111 100%);
/* FF3.6+ */
background: -moz-linear-gradient(top, #585858 0%, #111 100%);
/* IE10+ */
background: -ms-linear-gradient(top, #585858 0%, #111 100%);
/* Opera 11.10+ */
background: -o-linear-gradient(top, #585858 0%, #111 100%);
/* W3C */
background: linear-gradient(to bottom, #1c797a 0%, #1c797a 100%);
}
.mydt-ext {
display: flex;
flex-direction: row;
align-items: center;
margin-top: 10px;
/* justify-content: flex-start; */
}
.mydt-ext .item {
margin-right: 30px;
}
/******************************************************************************************************/
/* table {
border: solid 2px #1c797a;
font-weight: bold;
color: white;
width: 100%;
text-align: center;
border-collapse: separate;
border-spacing: 0;
}
tr,
th {
height: 60px;
border-right: solid 1px gray;
border-bottom: solid 1px gray;
}
table thead {
background-color: #125c70;
height: 20px;
}
table thead tr {
font-size: 14px;
height: 20px;
}
table thead tr th {
height: 20px;
border-right: solid 1px gray;
border-bottom: solid 1px gray;
}
table tbody tr {
height: 24px;
font-size: 13px;
font-weight: bold;
}
table tbody tr td {
height: 24px;
border-right: solid 1px gray;
border-bottom: solid 1px gray;
} */
/*
td:last-child,
th:last-child {
border-right-color: transparent;
}
td.details-control {
background: url('../assets/details_open.png') no-repeat center center;
cursor: pointer;
}
tr.shown td.details-control {
background: url('../assets/details_close.png') no-repeat center center;
}
*/
#flex-sample {
display: flex;
/* 排列方向 flex-direction: row | row-reverse | column | column-reverse */
flex-direction: column;
/* 换行方式 flex-wrap: nowrap(不换行) | wrap换行第一行在上面 | wrap-reverse换行第一行在下面 */
flex-wrap: nowrap;
/* 是flex-direction属性和flex-wrap属性的简写形式默认值为row nowrap */
flex-flow: column nowrap;
/* 主轴上的对齐方式 justify-content: flex-start | flex-end | center | space-between | space-around */
justify-content: center;
align-items: stretch;
/* flex-start | flex-end | center | baseline | stretch */
align-content: flex-start;
/* flex-start | flex-end | center | space-between | space-around | stretch */
}
.mypanelstat {
/* width: 100%; */
height: calc(90vh - 130px);
background-color: #052f4d;
/* margin-top: 10px; */
/* padding: 10px 10px 10px 10px; */
border-radius: 12px;
}
.mask {
position: fixed;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
font-size: 16px;
/* IE9以下不支持rgba模式 */
background-color: rgba(0, 0, 0, 0.3);
/* 兼容IE8及以下 */
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#7f000000, endColorstr=#7f000000);
/* 显示: block 不显示none overlay.style.display = 'block' */
display: none;
}
/* 弹出框主体 */
.pop {
background-color: #e0e0e0;
min-width: 200px;
max-width: 600px;
height: 300px;
border-radius: 10px;
margin: 200px auto;
text-align: center;
/* overflow: hidden; */
}
/* 弹出框的标题 */
.pop_title {
font-size: 28px;
font-weight: 1000;
height: 50px;
line-height: 50px;
background-color: #909090;
border-radius: 10px 10px 0 0;
/* border-bottom: solid 2px #8080ff; */
}
/* 弹出框的内容 */
.pop_content {
height: 50px;
line-height: 50px;
padding: 15px 20px;
color: #198754;
}
/* 弹出框的按钮栏 */
.pop_btn {
padding-bottom: 10px;
}
/* 弹出框的按钮 */
.pop_btn button {
color: #778899;
width: 40%;
height: 40px;
cursor: pointer;
border: solid 1px #cccccc;
border-radius: 5px;
margin: 5px 10px;
color: #ffffff;
background-color: #337ab7;
}
.myrow {
color: white;
display: flex;
flex-direction: row;
align-content: flex-start;
}
.mycol {
color: white;
display: flex;
flex-direction: column;
}
.myblock {
background-color: chocolate;
width: 50px;
height: 50px;
margin: 10px 0px 0px 10px;
}
.mycardbtn {
background-color: #07486f;
border-radius: 10px;
margin: 0 10px 10px 10px;
padding: 10px 10px 10px 10px;
}
.mycardbtn-active {
background-color: #1d6466;
border-radius: 10px;
margin: 0 10px 10px 10px;
padding: 10px 10px 10px 10px;
border: 2px solid #01b7d1;
}
.mycardbtn:hover {
background-color: #1d6466;
cursor: pointer;
}
.mycard {
background-color: #08365b;
width: 220px;
height: 340px;
border-radius: 10px;
margin: 10px 0px 0px 10px;
padding: 10px;
position: relative;
}
.mycard-param {
display: flex;
margin-top: 3px;
font-size: 14px;
margin-left: 10px;
}
.mycard-param-key {
font-weight: bold;
color: #a6b8dd;
width: 70px;
}
.mycard-param-text {
font-weight: bold;
color: white;
}
.status-ok {
background-color: green;
width: 14px;
height: 14px;
border-radius: 7px;
}
.status-err {
background-color: red;
width: 14px;
height: 14px;
border-radius: 7px;
}
.text-ok {
color: green;
}
.text-err {
color: red;
}
.mychart {
background-color: #30303030;
}
.mypanel {
width: 100%;
height: 200px;
background-color: #052f4d;
border-radius: 8px;
padding: 10px 10px 10px 10px;
margin: 0px 0px 10px 0px;
overflow: hidden;
}
.mypanel-title {
height: 30px;
font-size: 16px;
font-weight: 1000;
color: #63c4d8;
}
.myline-l {
/* 前 5px 红色, 5px 后剩余部分透明 */
background: linear-gradient(#21ffd2, #21ffd2) left 2px / 5px 100% no-repeat;
padding-left: 16px;
height: 20px;
}
.myline-b {
background: linear-gradient(to right, #09c8d3ff, transparent) bottom / 100% 3px no-repeat;
padding-bottom: 5px;
}
.myline-lb {
/* 左侧 5px + 底部 3px 渐变透明 */
background:
linear-gradient(#21ffd2, #21ffd2) left 3px / 5px calc(100% - 12px) no-repeat,
linear-gradient(to right, #09c8d3ff, transparent) bottom / 100% 3px no-repeat;
padding-bottom: 5px;
padding-left: 16px;
padding-top: 0px;
}
.label-bkg {
border-radius: 5px;
background-color: #a0a0a010;
float: left;
/* margin-right: 10px; */
}
.label-key {
/* border: solid 1px white; */
width: 100%;
height: 50%;
font-size: 14px;
font-weight: 1000;
color: white;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
}
.label-val-lg {
/* border: solid 1px white; */
width: 65%;
height: 50%;
font-size: 36px;
color: #4dd7f0;
float: left;
display: flex;
justify-content: flex-end;
align-items: flex-end;
text-align: right;
}
.label-val {
/* border: solid 1px white; */
width: 65%;
height: 50%;
font-size: 20px;
color: #4dd7f0;
float: left;
display: flex;
justify-content: flex-end;
align-items: flex-end;
}
.label-tail {
/* border: solid 1px white; */
padding-left: 10px;
width: 35%;
height: 45%;
font-size: 16px;
font-weight: 1000;
color: white;
display: flex;
justify-content: left;
align-items: flex-end;
}
#maskTest {
position: absolute;
z-index: 1;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
}
.page {
padding: 5px 8px 5px 8px;
}
.btn-default {
background-color: #a5a5a5;
}
.btn-default:hover {
background-color: #858585;
}

Binary file not shown.

View File

@@ -0,0 +1,238 @@
var G = {
user: { username: '' },
loadPage: function (pagename) {
while (1) {
var script = document.querySelector("script[id='mytempfile']")
if (!script) break
script.remove()
}
var file = 'assets/html/pages/' + pagename + '.html'
G.cppNative.readFile(file).then(function (text) {
// 加载 html 页面内容文件
document.getElementById('mypage').innerHTML = text
// 加载 js 脚本文件
var jsUrl = './pages/' + pagename + '.js'
var element = document.createElement('script')
element.src = jsUrl + '?t=' + new Date().getTime()
element.async = false // 脚本按照加载先后顺序处理
element.setAttribute('id', 'mytempfile')
document.body.appendChild(element)
})
},
switchSetStatus: function (id1, id2, checked, callback) {
document.getElementById(id2).checked = !(document.getElementById(id1).checked = checked)
if (callback) callback(checked)
},
switchGetStatus: function (id) { return document.getElementById(id).checked },
initTable: function (id, info) {
if (info.table) {
info.table.ajax.reload()
return;
}
var tableOption = G.tableGetOption()
tableOption.columns = info.columns
tableOption.ajax = function (req, callback, settings) {
G.cppNative.log('lxy=== table ajax start')
if (info.query) {
info.query(1, 10).then(res => {
var result = []
res.data.forEach(function (item, index) {
var rowData = []
info.header.forEach(function (key, index) { rowData.push(item[key]) })
result.push(rowData)
})
G.cppNative.log("table ajax: " + JSON.stringify(result))
callback({ draw: req.draw, recordsTotal: result.length, recordsFiltered: result.length, data: result })
})
} else {
callback({ draw: req.draw, recordsTotal: 0, recordsFiltered: 0, data: [] })
}
}
// 初始化表格
info.table = $('#' + id + 'Table').DataTable(tableOption)
G.cppNative.log('lxy=== table init end')
//$('div.gotopage').html('<b style="color:#7f8fa4">跳转至 </b><input id="searchNumber" style="width:80px"/><b style="color:#7f8fa4;"> 页</b>')
},
updateTableData: function (queryFunc, params) {
if (queryFunc) {
}
},
cppCall: function (id) {
var cppfunc = G.cppNative[id]
if (cppfunc) {
G.cppNative.log('call cpp function [' + id + ']')
cppfunc()
} else {
G.cppNative.log('call cpp function [' + id + '] error: not exist')
}
},
cppSignal: function (id, callback) {
var signal = G.cppNative[id]
if (signal) {
G.cppNative.log('cpp signal [' + id + '] ')
signal.connect(callback)
} else {
G.cppNative.log('cpp signal [' + id + '] error: not exist')
}
},
initForm: function (id, funcPopConfirm) {
var form = document.getElementById(id + 'Form')
var formBtnOk = document.getElementById(id + 'FormOk')
if (form && formBtnOk) {
// 监听表单的输入事件,检查表单的必填项是否完成输入,如果未完成,则确认按钮不可用
form.addEventListener('input', function () { formBtnOk.disabled = !form.checkValidity() })
// 编辑弹窗的确定按钮监听点击事件
formBtnOk.addEventListener('click', function () { if (funcPopConfirm) { funcPopConfirm(id) } })
}
},
showElement: function (id, visible) {
var elemt = document.getElementById(id)
if (elemt) { elemt.style.display = visible ? 'block' : 'none' }
},
popSetParams: function (id, keys, rowdata, callback) {
keys.forEach(function (key, index) {
var val = ''
if (rowdata && rowdata.length > index) { val = rowdata[index] }
if (key == 'is_open') {
G.switchSetStatus(id + 'Form_on', id + 'Form_off', parseInt(val))
} else {
var myval = (callback) ? callback(id, key, val) : val
// 回调函数返回 undefined 时, 不需要设置参数值
if (myval != undefined) {
val = myval
var element = $('#' + id + 'Form_' + key)
if (element) {
if (element.prop("tagName") == "SELECT" && val == '') {
element.get(0).selectedIndex = 0;
} else {
element.val(val)
}
}
}
}
})
},
popGetParams: function (id, keys, rowdata, callback) {
var params = {}
keys.forEach(function (key, index) {
var val
if (key == 'is_open') {
val = G.switchGetStatus(id + 'Form_on') ? '1' : '0'
} else {
var myval = callback ? callback(id, key) : undefined
val = myval != undefined ? myval : $('#' + id + 'Form_' + key).val()
}
if (rowdata) {
if (rowdata.length > index && val != rowdata[index]) { params[key] = val }
} else {
if (val != '') { params[key] = val }
}
})
G.cppNative.log('POP get params id=' + id + ', params=' + JSON.stringify(params))
return params
},
popSetParamReadonly: function (id, key, isReadonly) {
$('#' + id + 'Form_' + key).attr('readonly', isReadonly)
},
tableGetOption: function () {
return {
data: [],
columns: [],
bSort: false,
scollY: "600px",
//aLengthMenu: [10, 20, 50, 100], //设置每页显示数据条数的下拉选项
//displayLength: 5, //每页初始显示最大记录数量
// 设置表格t、分页数据条数l、搜索框f、表格信息i、分页p、加载信息r
dom: 'rt<"mydt-ext"p<"item"<"gotopage">><"item"i><"item"f>>',
language: {
emptyTable: '无数据',
lengthMenu: '每页显示 _MENU_ 条记录',
zeroRecords: '对不起,查询不到任何相关数据',
info: '共有 _TOTAL_ 条记录', // '当前显示 _START_ 到 _END_ 条,共 _TOTAL_ 条记录',
infoEmpty: '共 0 页',
infoFiltered: '数据表中共为 _MAX_ 条记录)',
processing: '正在加载中...',
search: '结果中搜索',
paginate: {
previous: '上一页', next: '下一页', first: '首页', last: '尾页'
},
},
columnDefs: [{ targets: '_all', className: 'dt-head-left' }, { targets: '_all', className: 'dt-body-left' }],
//serverSide: true,
processing: false,
ajax: function (req, callback, settings) {
// 查询服务器获取数据, 同时获取总数据条数
callback({ draw: req.draw, recordsTotal: 0, recordsFiltered: 0, data: [] })
},
createdRow: function (row, data, dataIndex) {
if (dataIndex % 2 === 0) {
//$(row).css('background-color', '#ff000010')
} else {
//$(row).css('background-color', '#00ff0010')
}
$(row).on('mouseenter', function () {
//if (curEditRow && myTableApi.row(curEditRow).index() == myTableApi.row($(this)).index()) return
$(this).css('background-color', '#ff808050') // 高亮颜色
})
$(row).on('mouseleave', function () {
//if (curEditRow && myTableApi.row(curEditRow).index() == myTableApi.row($(this)).index()) return
$(this).css('background-color', '') // 恢复默认
})
},
}
},
clickSubpageBtn: function (id) {
if (G.curSubpageId == id) return
if (G.curSubpageId) {
var oldBtn = document.getElementById(G.curSubpageId + 'Btn')
if (oldBtn) { oldBtn.className = 'btn btn-primary' }
var oldSubpage = $('#' + G.curSubpageId)
if (oldSubpage) { oldSubpage.hide() }
}
if (id) {
var curBtn = document.getElementById(id + 'Btn')
if (curBtn) { curBtn.className = 'btn btn-success btn-lg' }
var curSubpage = $('#' + id)
if (curSubpage) { curSubpage.show() }
}
G.curSubpageId = id
},
getRandDataDay: function (a, b, n) {
var data = []
var t0 = Date.parse('2025-03-01 00:00:00')
if (!n) { n = 24 }
var step = 86400 / n
var y = a;
for (var i = 0; i < n; ++i) {
// data[i] = { x: t0 + i * step * 1000, y: Math.sin(i * 0.1) * (n - m) }
y = Math.floor((y + RAND(0, 50) - 25) * 100) / 100
data[i] = { x: t0 + i * step * 1000, y: y }
}
return data
}
}
function RAND(a, b) {
return a + Math.random() * (b - a)
}

View File

@@ -204,7 +204,7 @@ function initEchartCurve(id, seriesItems) {
option.legend.data = seriesItems
option.series = []
seriesItems.forEach(item => {
option.series.push({ name: item, type: 'line', smooth: true, symbolSize: 0, data: [] })
option.series.push({ name: item, type: 'line', smooth: false, symbolSize: 0, data: [] })
})
echart.setOption(option)
return echart

View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>光储充站控系统</title>
</head>
<body>
</body>
</html>

View File

@@ -3,680 +3,232 @@
<head>
<meta charset="UTF-8" />
<title>光储充站控系统</title>
<script src="./libs/jquery/jquery-3.7.1.min.js"></script>
<link rel="stylesheet" href="./libs/DataTables-2.1.8/css/dataTables.dataTables.css" />
<script src="./libs/DataTables-2.1.8/js/dataTables.js"></script>
<link rel="stylesheet" href="./libs/bootstrap-5.3.3-dist/css/bootstrap.min.css" />
<script src="./libs/bootstrap-5.3.3-dist/js/bootstrap.min.js"></script>
<script src="./libs/bootstrap-5.3.3-dist/js/bootstrap.bundle.min.js"></script>
<link rel="stylesheet" href="./libs/DataTables-2.1.8/css/dataTables.dataTables.css" />
<script src="./libs/DataTables-2.1.8/js/dataTables.js"></script>
<script src="./libs/echarts/echarts.min.js"></script>
<script src="./js/qwebchannel.js"></script>
<script src="./js/myecharts.js"></script>
<script src="./js/common.js"></script>
<link rel="stylesheet" href="./css/mystyle.css" />
<style>
@font-face {
font-family: 优设标题黑;
src: url(./font/优设标题黑.ttf);
}
body {
background-image: url('../ui/bkg01.png');
background-size: 100% 100%;
background-attachment: fixed;
}
div {
user-select: none;
}
a {
display: inline-block;
/* 添加间距,使链接之间不会紧贴 */
padding-right: 8px;
color: #ffffff;
/* color: #ffffff; */
}
table {
font-size: 16px;
font-weight: bold;
color: white;
width: 100%;
text-align: center;
border-collapse: separate;
border-spacing: 0;
border: solid 2px #1c797a;
font-size: 14px;
color: white;
/* font-weight: bold; */
/* width: 100%; */
/* text-align: center; */
/* border-collapse: separate; */
/* border-spacing: 0; */
}
table thead {
background-color: #125c70;
}
table thead tr {
height: 32px;
/* border: solid 2px red; */
table tbody {
/* font-size: 13px; */
}
table thead tr th {
tr th {
border-right: solid 1px gray;
border-bottom: solid 1px gray;
}
table tbody tr {
height: 32px;
font-size: 13px;
font-weight: bold;
}
table tbody tr td {
border-right: solid 1px gray;
border-bottom: solid 1px gray;
}
td:last-child,
th:last-child {
border-right-color: transparent;
}
.dt-container {
color: white;
}
.dt-paging {
color: white;
}
td.details-control {
background: url('../assets/details_open.png') no-repeat center center;
cursor: pointer;
}
tr.shown td.details-control {
background: url('../assets/details_close.png') no-repeat center center;
}
.table-ext {
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
margin-top: 10px;
}
.table-ext .item {
margin: 0px 20px 0px 10px;
}
#flex-sample {
display: flex;
/* 排列方向 flex-direction: row | row-reverse | column | column-reverse */
flex-direction: column;
/* 换行方式 flex-wrap: nowrap(不换行) | wrap换行第一行在上面 | wrap-reverse换行第一行在下面 */
flex-wrap: nowrap;
/* 是flex-direction属性和flex-wrap属性的简写形式默认值为row nowrap */
flex-flow: column nowrap;
/* 主轴上的对齐方式 justify-content: flex-start | flex-end | center | space-between | space-around */
justify-content: center;
align-items: stretch;
/* flex-start | flex-end | center | baseline | stretch */
align-content: flex-start;
/* flex-start | flex-end | center | space-between | space-around | stretch */
}
.mypanelstat {
width: 100%;
height: calc(90vh - 130px);
background-color: #052f4d;
/* margin-top: 10px; */
/* padding: 10px 10px 10px 10px; */
border-radius: 12px;
}
.mask {
position: fixed;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
font-size: 16px;
/* IE9以下不支持rgba模式 */
background-color: rgba(0, 0, 0, 0.3);
/* 兼容IE8及以下 */
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#7f000000, endColorstr=#7f000000);
/* 显示: block 不显示none overlay.style.display = 'block' */
display: none;
}
/* 弹出框主体 */
.pop {
background-color: #e0e0e0;
min-width: 200px;
max-width: 600px;
height: 300px;
border-radius: 10px;
margin: 200px auto;
text-align: center;
/* overflow: hidden; */
}
/* 弹出框的标题 */
.pop_title {
font-size: 28px;
font-weight: 1000;
height: 50px;
line-height: 50px;
background-color: #909090;
border-radius: 10px 10px 0 0;
/* border-bottom: solid 2px #8080ff; */
}
/* 弹出框的内容 */
.pop_content {
height: 50px;
line-height: 50px;
padding: 15px 20px;
color: #198754;
}
/* 弹出框的按钮栏 */
.pop_btn {
padding-bottom: 10px;
}
/* 弹出框的按钮 */
.pop_btn button {
color: #778899;
width: 40%;
height: 40px;
cursor: pointer;
border: solid 1px #cccccc;
border-radius: 5px;
margin: 5px 10px;
color: #ffffff;
background-color: #337ab7;
}
myrow {
color: white;
display: flex;
flex-direction: row;
align-content: flex-start;
}
mycolumn {
color: white;
display: flex;
flex-direction: column;
}
.myrow {
color: white;
display: flex;
flex-direction: row;
align-content: flex-start;
}
.mycolumn {
color: white;
display: flex;
flex-direction: column;
width: 100%;
}
.myblock {
background-color: chocolate;
width: 50px;
height: 50px;
margin: 10px 0px 0px 10px;
}
.mycardbtn {
background-color: #07486f;
border-radius: 10px;
margin: 0 10px 10px 10px;
padding: 10px 10px 10px 10px;
}
.mycardbtn-active {
background-color: #1d6466;
border-radius: 10px;
margin: 0 10px 10px 10px;
padding: 10px 10px 10px 10px;
border: 2px solid #01b7d1;
}
.mycardbtn:hover {
background-color: #1d6466;
cursor: pointer;
}
.mycard {
background-color: #08365b;
width: 300px;
height: 280px;
border-radius: 10px;
margin: 10px 0px 0px 10px;
padding: 10px;
}
.mycard-param {
display: flex;
font-size: 16px;
margin-left: 20px;
}
.mycard-param-title {
font-weight: 200;
color: #a6b8dd;
width: 70px;
}
.mycard-param-text {
font-weight: 500;
margin-left: 10px;
color: white;
}
.mychart {
background-color: #30303030;
}
.mypanel {
width: 100%;
height: 200px;
background-color: #07253f;
border-radius: 8px;
padding: 10px 10px 10px 10px;
margin: 0px 0px 10px 0px;
overflow: hidden;
}
.mypanel .mypanel-icon {
width: 5px;
height: 24px;
background-color: #21ffd2;
float: left;
}
.mypanel .mypanel-title {
height: 24px;
margin-left: 15px;
font-size: 16px;
font-weight: 1000;
color: #63c4d8;
}
.mypanel-title {
height: 24px;
margin-left: 15px;
font-size: 16px;
font-weight: 1000;
color: #63c4d8;
}
.mypanel .mypanel-line {
margin-top: 5px;
margin-bottom: 0px;
width: 100%;
height: 2px;
background: linear-gradient(to right, #21ffd2ff, #21ffd200);
}
.label-bkg {
border-radius: 5px;
background-color: #a0a0a010;
float: left;
/* margin-right: 10px; */
}
.label-key {
/* border: solid 1px white; */
width: 100%;
height: 50%;
font-size: 16px;
font-weight: 1000;
color: white;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
}
.label-val-lg {
/* border: solid 1px white; */
width: 65%;
height: 50%;
font-size: 36px;
color: #4dd7f0;
float: left;
display: flex;
justify-content: flex-end;
align-items: flex-end;
text-align: right;
}
.label-val {
/* border: solid 1px white; */
width: 65%;
height: 50%;
font-size: 20px;
color: #4dd7f0;
float: left;
display: flex;
justify-content: flex-end;
align-items: flex-end;
}
.label-tail {
/* border: solid 1px white; */
padding-left: 10px;
width: 35%;
height: 45%;
font-size: 16px;
font-weight: 1000;
color: white;
display: flex;
justify-content: left;
align-items: flex-end;
}
#maskTest {
position: absolute;
z-index: 1;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
}
.page {
padding: 5px 8px 5px 8px;
}
.dt-container {
color: white;
}
div.dt-container .dt-paging .dt-paging-button {
line-height: 32px;
width: 32px;
padding: 0 0px 0 0;
border: 1px solid white;
margin-right: 10px;
}
div.dt-container .dt-paging .dt-paging-button.disabled,
div.dt-container .dt-paging .dt-paging-button.disabled:hover,
div.dt-container .dt-paging .dt-paging-button.disabled:active {
color: white !important;
border: 1px solid gray;
}
div.dt-container .dt-paging .dt-paging-button.current {
background: linear-gradient(to bottom, #1c797a 0%, #1c797a 100%);
}
div.dt-container .dt-paging .dt-paging-button.current:hover {
background: linear-gradient(to bottom, #1c797a 0%, #1c797a 100%);
}
div.dt-container .dt-paging .dt-paging-button:hover {
color: white !important;
border: 1px solid #111;
background-color: #111;
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111));
/* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #585858 0%, #111 100%);
/* Chrome10+,Safari5.1+ */
background: -moz-linear-gradient(top, #585858 0%, #111 100%);
/* FF3.6+ */
background: -ms-linear-gradient(top, #585858 0%, #111 100%);
/* IE10+ */
background: -o-linear-gradient(top, #585858 0%, #111 100%);
/* Opera 11.10+ */
background: linear-gradient(to bottom, #1c797a 0%, #1c797a 100%);
/* W3C */
/* min-height: 20px; */
/* line-height: 20px; */
/* height: 30px; */
/* border-right: solid 1px gray; */
/* border-bottom: solid 1px gray; */
border: solid 1px gray;
}
</style>
<script>
var G = {
loadPage: function (pagename) {
while (1) {
var script = document.querySelector("script[id='mytempfile']")
if (!script) break
script.remove()
}
var file = 'assets/html/pages/' + pagename + '.html'
G.cppNative.readFile(file).then(function (text) {
// 加载 html 页面内容文件
document.getElementById('mypage').innerHTML = text
// 加载 js 脚本文件
var jsUrl = './pages/' + pagename + '.js'
var element = document.createElement('script')
element.src = jsUrl + '?t=' + new Date().getTime()
element.async = false // 脚本按照加载先后顺序处理
element.setAttribute('id', 'mytempfile')
document.body.appendChild(element)
})
},
switchSetStatus: function (id1, id2, isOn, callback) {
var switch1 = document.getElementById(id1)
var switch2 = document.getElementById(id2)
switch2.checked = !(switch1.checked = isOn)
if (callback) callback(isOn)
},
switchGetStatus: function (id) { return document.getElementById(id).checked },
initTable: function (id, info) {
if (info.table) {
info.table.ajax.reload()
return;
}
var tableOption = G.tableGetOption()
tableOption.columns = info.columns
tableOption.ajax = function (req, callback, settings) {
if (info.query) {
info.query(1, 10).then(res => {
var result = []
res.data.forEach(function (item, index) {
var rowData = []
info.header.forEach(function (key, index) { rowData.push(item[key]) })
result.push(rowData)
})
G.cppNative.log("table ajax: " + JSON.stringify(result))
callback({ draw: req.draw, recordsTotal: result.length, recordsFiltered: result.length, data: result })
})
} else {
callback({ draw: req.draw, recordsTotal: 0, recordsFiltered: 0, data: [] })
}
}
// 初始化表格
info.table = $('#' + id + 'Table').DataTable(tableOption)
$('div.gotopage').html(
'<b style="color:#7f8fa4">跳转至 </b><input id="searchNumber" style="width:80px"/><b style="color:#7f8fa4;"> 页</b>'
)
},
initForm: function (id, funcPopConfirm) {
var form = document.getElementById(id + 'Form')
var formBtnOk = document.getElementById(id + 'FormOk')
if (form && formBtnOk) {
// 监听表单的输入事件,检查表单的必填项是否完成输入,如果未完成,则确认按钮不可用
form.addEventListener('input', function () { formBtnOk.disabled = !form.checkValidity() })
// 编辑弹窗的确定按钮监听点击事件
formBtnOk.addEventListener('click', function () { if (funcPopConfirm) { funcPopConfirm(id) } })
}
},
showElement: function (id, visible) {
var elemt = document.getElementById(id)
if (elemt) { elemt.style.display = visible ? 'block' : 'none' }
},
popSetParams: function (id, keys, rowdata, callback) {
keys.forEach(function (key, index) {
var val = ''
if (rowdata && rowdata.length > index) { val = rowdata[index] }
if (key == 'is_open') {
G.switchSetStatus(id + 'Form_on', id + 'Form_off', parseInt(val))
} else {
var myval = (callback) ? callback(id, key, val) : val
// 回调函数返回 undefined 时, 不需要设置参数值
if (myval != undefined) {
val = myval
var element = $('#' + id + 'Form_' + key)
if (element) {
if (element.prop("tagName") == "SELECT" && val == '') {
element.get(0).selectedIndex = 0;
} else {
element.val(val)
}
}
}
}
})
},
popGetParams: function (id, keys, rowdata, callback) {
var params = {}
keys.forEach(function (key, index) {
var val
if (key == 'is_open') {
val = G.switchGetStatus(id + 'Form_on') ? '1' : '0'
} else {
var myval = callback ? callback(id, key) : undefined
val = myval != undefined ? myval : $('#' + id + 'Form_' + key).val()
}
if (rowdata) {
if (rowdata.length > index && val != rowdata[index]) { params[key] = val }
} else {
if (val != '') { params[key] = val }
}
})
G.cppNative.log('POP get params id=' + id + ', params=' + JSON.stringify(params))
return params
},
popSetParamReadonly: function (id, key, isReadonly) {
$('#' + id + 'Form_' + key).attr('readonly', isReadonly)
},
tableGetOption: function () {
return {
data: [],
columns: [],
bSort: false,
aLengthMenu: [10, 20, 50, 100], //设置每页显示数据条数的下拉选项
displayLength: 10, //每页初始显示最大记录数量
// 设置表格t、分页数据条数l、搜索框f、表格信息i、分页p、加载信息r
dom: 'rt<"table-ext"<"item">p<"item"<"gotopage">><"item"i>>',
language: {
emptyTable: '无数据',
lengthMenu: '每页显示 _MENU_ 条记录',
zeroRecords: '对不起,查询不到任何相关数据',
info: '共 _TOTAL_ 条记录', // '当前显示 _START_ 到 _END_ 条,共 _TOTAL_ 条记录',
infoEmpty: '共 0 页',
infoFiltered: '数据表中共为 _MAX_ 条记录)',
processing: '正在加载中...',
search: '结果中搜索',
paginate: { previous: '<', next: '>' }, // first: '首页', last: '尾页'
},
columnDefs: [{ targets: '_all', className: 'dt-head-left' }, { targets: '_all', className: 'dt-body-left' }],
serverSide: true,
processing: false,
ajax: function (req, callback, settings) {
// 查询服务器获取数据, 同时获取总数据条数
callback({ draw: req.draw, recordsTotal: 0, recordsFiltered: 0, data: [] })
},
createdRow: function (row, data, dataIndex) {
if (dataIndex % 2 === 0) {
//$(row).css('background-color', '#ff000010')
} else {
//$(row).css('background-color', '#00ff0010')
}
$(row).on('mouseenter', function () {
//if (curEditRow && myTableApi.row(curEditRow).index() == myTableApi.row($(this)).index()) return
$(this).css('background-color', '#ff808050') // 高亮颜色
})
$(row).on('mouseleave', function () {
//if (curEditRow && myTableApi.row(curEditRow).index() == myTableApi.row($(this)).index()) return
$(this).css('background-color', '') // 恢复默认
})
},
}
},
clickSubpageBtn: function (id) {
if (G.curSubpageId == id) return
if (G.curSubpageId) {
var oldBtn = document.getElementById(G.curSubpageId + 'Btn')
if (oldBtn) { oldBtn.className = 'btn btn-primary' }
var oldSubpage = $('#' + G.curSubpageId)
if (oldSubpage) { oldSubpage.hide() }
}
if (id) {
var curBtn = document.getElementById(id + 'Btn')
if (curBtn) { curBtn.className = 'btn btn-success btn-lg' }
var curSubpage = $('#' + id)
if (curSubpage) { curSubpage.show() }
}
G.curSubpageId = id
}
}
</script>
</head>
<body>
<div style="height: calc(8vh); line-height: 100px; display: flex;">
<!-- <button style="height:50px; line-height: 50px;" onclick='window.location.reload()'>重新加载</button> -->
<div id="currentTime"
style="color:white; font-family: Cascadia Mono; font-size: 20px; font-weight: 1000; margin-left: 20px; float: left">
<div
style="width:100%; height: calc(8vh); display: flex; justify-content: space-between; padding-top: 1.4%; font-family: 优设标题黑;">
<div class="myrow" style="height: 30px; color:white; font-size: 20px; float: left">
<div id="currentTime" style="width:250px; margin-left: 20px; "></div>
<div id="currentWeekday"></div>
</div>
<div style=" width:500px; height: 30px; display: flex;justify-content: flex-end;">
<div style=" width: 28px; height: 28px; background-color: #01b7d1; border-radius: 14px;"></div>
<div id='username' style="line-height:28px;color: white; font-size: 20px; font-weight: 500; margin-left: 10px; ">
</div>
<button
style="width:30px; height: 30px; background-color: transparent; border: none; background-image: url('../ui/exit.png'); background-size: cover; background-repeat: no-repeat;margin-left: 10px; margin-right: 10px;"
onclick="loginOut()"></button>
</div>
</div>
<div id="mypage" style="height: calc(92vh - 60px); overflow: hidden;">
</div>
<div id="mypage" style="height: calc(92vh - 60px);display: flex;flex-direction: row;"> </div>
<div style="background-color: #00496e; display: flex; justify-content: center;">
<button class="btn btn-primary" style="margin: 10px" onclick="G.loadPage('系统总览')">系统总览</button>
<button class="btn btn-primary" style="margin: 10px" onclick="G.loadPage('运行监控')">运行监控</button>
<button class="btn btn-primary" style="margin: 10px" onclick="G.loadPage('预测管理')">预测管理</button>
<button class="btn btn-primary" style="margin: 10px" onclick="G.loadPage('统计分析')">统计分析</button>
<button class="btn btn-primary" style="margin: 10px" onclick="G.loadPage('系统管理')">系统管理</button>
<button class="btn btn-primary" style="margin: 10px" onclick="G.loadPage('安全管理')">安全管理</button>
<button id="homePageBtn" class="btn btn-success" style="margin: 10px"
onclick="onClickMenuBtn(this, '系统总览')">系统总览</button>
<button class="btn btn-primary" style="margin: 10px" onclick="onClickMenuBtn(this, '运行监控')">运行监控</button>
<button class="btn btn-primary" style="margin: 10px" onclick="onClickMenuBtn(this, '预测管理')">预测管理</button>
<button class="btn btn-primary" style="margin: 10px" onclick="onClickMenuBtn(this, '统计分析')">统计分析</button>
<button class="btn btn-primary" style="margin: 10px" onclick="onClickMenuBtn(this, '系统管理')">系统管理</button>
<button class="btn btn-primary" style="margin: 10px" onclick="onClickMenuBtn(this, '安全管理')">安全管理</button>
<button class="btn btn-primary" style="margin: 10px" onclick="onClickMenuBtn(this, 'test')">测试页面</button>
</div>
<script>
//第一个参数是QtWebEngine 挂载到前端全局环境中的 window.qt.webChannelTransport
new QWebChannel(qt.webChannelTransport, function (channel) {
// 在C++侧注册的对象名称为cppNative所以channel.objects后面的名字是cppNative
G.cppNative = channel.objects.cppNative
// 连接WebObject类的signalNativeTextChanged信号
G.cppNative.signalNativeTextChanged.connect(function (text) { alert('signal: ' + text) })
})
document.addEventListener("keydown", function (e) {
if (e.keyCode == 116) { window.location.reload() }
});
// 查询用户权限,确定页面显示内容
$(document).ready(function () {
setInterval(() => {
var now = new Date()
var year = now.getFullYear();
var month = ('0' + (now.getMonth() + 1)).slice(-2);
var day = ('0' + now.getDate()).slice(-2);
var hours = ('0' + now.getHours()).slice(-2);
var minutes = ('0' + now.getMinutes()).slice(-2);
var seconds = ('0' + now.getSeconds()).slice(-2);
var currentT = year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds;
document.getElementById('currentTime').innerHTML = currentT;
}, 1000);
//G.loadPage('系统总览')
})
</script>
<div id="loginPage" style="position: fixed; top:0px; left:0px; width: 100%; height: 100%; background-color: #07486f; background-image: url('../ui/bkgLogin.png'); background-size: 100% 100%;
background-attachment: fixed;">
<form id="loginForm" class="was-validated"
style="position: fixed; top:41.0%; left:43.6%; width:17.6%; height: 13%; ">
<input id="loginForm_name" type="text" class="form-control" required
style="height: 33%; background-color: #163b7d; color: white" />
<input id="loginForm_pwd" type="password" class="form-control" required
style="margin-top: 4.5%;height: 33%; background-color: #163b7d; color: white" />
</form>
<div id="loginMsg" style="position:fixed;top:52%;left:43.7%;width:17.5%;height:30px;color:crimson"></div>
<button id="loginFormOK"
style="position: fixed; top:54.7%; left:43.7%; width: 17.5%; height: 4%; background-color: #2a82e4; border-radius:5px; border: none; color: white; font-weight: 600;"
onclick="login()"> 登 录</button>
</div>
</body>
<script>
// 第一个参数是QtWebEngine 挂载到前端全局环境中的 window.qt.webChannelTransport
new QWebChannel(qt.webChannelTransport, function (channel) {
// 在C++侧注册的对象名称为cppNative所以channel.objects后面的名字是cppNative
G.cppNative = channel.objects.cppNative
// 连接QWeb的信号signalNativeTextChanged是qt侧定义的signal
G.cppNative.signalNativeTextChanged.connect(function (text) { alert('signal: ' + text) })
// 连接信号:登录完成
G.cppNative.signalLongin.connect(onSignalLogin)
})
document.addEventListener("keydown", function (e) {
if (e.keyCode == 116) { window.location.reload() }
});
var activeMenuBtn = document.getElementById('homePageBtn')
function onClickMenuBtn(btn, id) {
if (activeMenuBtn) activeMenuBtn.className = 'btn btn-primary'
activeMenuBtn = btn
activeMenuBtn.className = 'btn btn-success'
G.loadPage(id)
}
function login() {
var username = $("#loginForm_name").val()
var passwd = $("#loginForm_pwd").val()
if (!username) {
$('#loginMsg').text('请输入用户名!')
return
}
if (!passwd) {
$('#loginMsg').text('请输入密码!')
return
}
$('#loginMsg').text('')
// 调用CPP接口
G.cppNative.login(username, passwd);
}
function loginOut() {
$("#loginPage").show()
}
var form = document.getElementById('loginForm')
var formBtnOk = document.getElementById('loginFormOK')
if (form && formBtnOk) {
// 监听表单的输入事件,检查表单的必填项是否完成输入,如果未完成,则确认按钮不可用
form.addEventListener('input', function () {
formBtnOk.disabled = !form.checkValidity()
if (!$("#loginForm_name").val()) {
$('#loginMsg').text('请输入用户名!')
} else if (!$("#loginForm_pwd").val()) {
$('#loginMsg').text('请输入密码!')
} else {
$('#loginMsg').text('')
}
})
}
function onSignalLogin(username, ecode) {
if (ecode != 0) {
const ErrCode = {
101: '数据库连接错误',
102: '数据库查询SQL错误',
103: '用户不存在',
104: '密码不正确'
}
var errmsg = ErrCode[ecode]
if (!errmsg) { errmsg = '错误码:' + ecode }
$('#loginMsg').text('登入失败,' + errmsg)
// $("#loginForm_name").val('')
// $("#loginForm_pwd").val('')
} else {
G.user.username = username
$('#username').text(username)
$("#loginPage").hide()
onClickMenuBtn(document.getElementById('homePageBtn'), '系统总览')
}
}
// 查询用户权限,确定页面显示内容
$(document).ready(function () {
setInterval(() => {
var now = new Date()
var year = now.getFullYear();
var month = ('0' + (now.getMonth() + 1)).slice(-2);
var day = ('0' + now.getDate()).slice(-2);
var hours = ('0' + now.getHours()).slice(-2);
var minutes = ('0' + now.getMinutes()).slice(-2);
var seconds = ('0' + now.getSeconds()).slice(-2);
var weekday = now.toLocaleDateString('zh-CN', { weekday: "long" });
var time = year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds;
document.getElementById('currentTime').innerHTML = time;
document.getElementById('currentWeekday').innerHTML = weekday
}, 1000);
// 测试: 不显示登录页,正式版本需要删除
$("#loginPage").hide()
onClickMenuBtn(document.getElementById('homePageBtn'), '系统总览')
})
</script>
</html>

View File

@@ -1,34 +1,110 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<div style="width: 100%; height: 100%; ;">
<script src="../libs/jquery/jquery-3.7.1.min.js"></script>
<div id="workspace" class="myrow">
<div class="mycard" style="width:320px">
<div class="myrow" style="margin-bottom: 20px; border: solid 1px salmon;">
<div style="width: 65px;height: 65px; background-color: #2991b6;border-radius: 10px;"></div>
<div class="mycol" style="margin-left: 10px; font-size:15px;">
<div> 编号111 </div>
<div style="font-size:15px;"> 名称 </div>
<div style="color: #08afff; font-size:14px; font-weight: bold;"> 设备类型 </div>
</div>
</div>
<link rel="stylesheet" href="../libs/DataTables-2.1.8/css/dataTables.dataTables.css" />
<script src="../libs/DataTables-2.1.8/js/dataTables.js"></script>
<div class="mycard-param">
<div class="mycard-param-key">工作状态: </div>
<div id="id" class="mycard-param-text">运行/空闲</div>
</div>
</div>
<link rel="stylesheet" href="../libs/bootstrap-5.3.3-dist/css/bootstrap.min.css" />
<script src="../libs/bootstrap-5.3.3-dist/js/bootstrap.min.js"></script>
<script src="../libs/bootstrap-5.3.3-dist/js/bootstrap.bundle.min.js"></script>
<div class="mycard" style="width:320px">
<div class="myrow" style="margin-bottom: 20px; ">
<div style="width: 65px;height: 65px; background-color: #2991b6;border-radius: 10px;"></div>
<div class="mycol" style="margin-left: 10px; font-size:15px;">
<div> 编号222 </div>
<div style="font-size:15px;"> 名称 </div>
<div style="color: #08afff; font-size:14px; font-weight: bold;"> 设备类型 </div>
</div>
</div>
<div class="myrow">
<div style="width: calc(50% - 10px); border: solid gray; border-width: 0 1px 0 0;">
<div class="myrow" style="font-size:14px; margin-left: 10px;">
<div style="background-color:#00dbd7; width: 5px; height:18px; "></div>
<div style="margin-left: 10px;">枪: #1</div>
<div class="status-ok" style="margin: 3px 0 0 30px; ">
</div>
</div>
<script type="text/javascript" src="../js/qwebchannel.js"></script>
<div class=" mycard-param">
<div class="mycard-param-key">状态: </div>
<div id="id" class="mycard-param-text">运行</div>
</div>
<div class="mycard-param">
<div class="mycard-param-key">电压: </div>
<div id="id" class="mycard-param-text">220 V</div>
</div>
<div class="mycard-param">
<div class="mycard-param-key">电流: </div>
<div id="id" class="mycard-param-text">10 A</div>
</div>
<div class="mycard-param">
<div class="mycard-param-key">功率: </div>
<div id="id" class="mycard-param-text">2.2 kW</div>
</div>
<div class="mycard-param">
<div class="mycard-param-key">温度: </div>
<div id="id" class="mycard-param-text">2.2 kW</div>
</div>
<div class="mycard-param">
<div class="mycard-param-key">SOC: </div>
<div id="id" class="mycard-param-text">20.6%</div>
</div>
<div class="mycard-param">
<div class="mycard-param-key">SOH: </div>
<div id="id" class="mycard-param-text">89.7%</div>
</div>
</div>
<link rel="stylesheet" type="text/css" href="../css/mystyle.css" />
<div style="width: calc(50% - 10px); margin-left: 10px;">
<div class="myrow" style="font-size:14px; margin-left: 10px;">
<div style="background-color:#00dbd7; width: 5px; height:18px; "></div>
<div style="margin-left: 10px;">枪: #2</div>
<div class="status-err" style="margin: 3px 0 0 30px; "></div>
</div>
<style>
.tablebox {
width: 100%;
height: 600px;
background-color: #052f4d;
margin-top: 20px;
padding: 20px 20px 20px 20px;
}
</style>
</head>
<body>
<iframe src="./index.html"></iframe>
<script src="./index.js"></script>
<>
</body>
</html>
<div class="mycard-param">
<div class="mycard-param-key">状态: </div>
<div id="id" class="mycard-param-text">运行</div>
</div>
<div class="mycard-param">
<div class="mycard-param-key">电压: </div>
<div id="id" class="mycard-param-text">220 V</div>
</div>
<div class="mycard-param">
<div class="mycard-param-key">电流: </div>
<div id="id" class="mycard-param-text">10 A</div>
</div>
<div class="mycard-param">
<div class="mycard-param-key">功率: </div>
<div id="id" class="mycard-param-text">2.2 kW</div>
</div>
<div class="mycard-param">
<div class="mycard-param-key">温度: </div>
<div id="id" class="mycard-param-text">2.2 kW</div>
</div>
<div class="mycard-param">
<div class="mycard-param-key">SOC: </div>
<div id="id" class="mycard-param-text">57.3%</div>
</div>
<div class="mycard-param">
<div class="mycard-param-key">SOH: </div>
<div id="id" class="mycard-param-text">93.2%</div>
</div>
</div>
</div>
</div>
</div>
<table id="myTable"></table>
</div>

View File

@@ -0,0 +1,149 @@
function addCardPanel(code, name, type, subList) {
var root = document.getElementById('workspace')
var card = document.createElement('div')
card.className = 'mycard'
card.setAttribute('id', code);
card.innerHTML =
`<div class="myrow" style="margin-bottom: 20px">
<div style="width: 65px;height: 65px; background-color: #2991b6;border-radius: 10px;"></div>
<div class="mycol" style="margin-left: 10px; font-size:15px;">
<div> ${code} </div>
<div style="font-size:15px;"> ${name} </div>
<div style="color: #08afff; font-size:14px; font-weight: bold;"> ${type} </div>
</div>
</div>`
// '<div class="mycard-param">'
// '<div class="mycard-param-key">工作状态: </div>'
// '<div id="id" class="mycard-param-text">运行/空闲</div>'
// '</div>'
if (subList && subList.length > 1) {
card.innerHTML +=
`<div class="myrow">
<div id="${code}_${subList[0]}" style="width: calc(50% - 10px); border: solid gray; border-width: 0 1px 0 0;">
<div class="myrow" style="font-size:14px; margin-left: 10px;">
<div style="background-color:#00dbd7; width: 5px; height:18px; "></div>
<div style="margin-left: 10px;">#${subList[0]}</div>
<div class="status-ok" style="margin: 3px 0 0 30px; "></div>
</div>
</div>
<div id="${code}_${subList[1]}" style="width: calc(50% - 10px); margin-left: 10px;">
<div class="myrow" style="font-size:14px; margin-left: 10px;">
<div style="background-color:#00dbd7; width: 5px; height:18px; "></div>
<div style="margin-left: 10px;">#${subList[1]}</div>
<div class="status-err" style="margin: 3px 0 0 30px; "></div>
</div>
</div>
</div>`
}
root.appendChild(card)
return card
}
function addCardParam(cardid, subid, key, text) {
var paramid = cardid + (subid ? ("_" + subid) : "") + "_" + key
param = document.createElement('div')
param.className = 'mycard-param'
param.innerHTML = `<div class="mycard-param-key">${key}: </div>
<div id="${paramid}" class="mycard-param-text">${text}</div>`
if (subid) {
$('#' + cardid + '_' + subid).append(param)
} else {
$('#' + cardid).append(param)
}
}
function setCardParam(cardid, subid, key, text) {
var paramid = cardid + (subid ? ("_" + subid) : "") + "_" + key
$("#" + paramid).text(text);
}
addCardPanel('编号1', '名称', '设备类型')
addCardParam('编号1', null, "电压", "220 V");
setCardParam('编号1', null, "电压", "290 V");
addCardPanel('编号2', '名称', '设备类型', ['1', '2'])
addCardParam('编号2', '1', "电压", "200 V");
addCardParam('编号2', '1', "电流", "10 V");
addCardParam('编号2', '2', "电压", "220 V");
setCardParam('编号2', '1', "电压", "210 V");
// var dataTablesOption = {
// data: [],
// columns: [],
// scrollY: "800px",
// bSort: false,
// aLengthMenu: [10, 20, 50, 100], //设置每页显示数据条数的下拉选项
// displayLength: 20, //每页初始显示最大记录数量
// // 设置表格t、分页数据条数l、搜索框f、表格信息i、分页p、加载信息r
// //dom: '<"table-ext"<"item"f><"item"l><"item"i><"item"p>>rt',
// language: {
// lengthMenu: '每页显示 _MENU_ 条记录',
// sZeroRecords: '对不起,查询不到任何相关数据',
// sInfo: '当前显示 _START_ 到 _END_ 条,共 _TOTAL_ 条记录',
// sInfoEmtpy: '找不到相关数据',
// sInfoFiltered: '数据表中共为 _MAX_ 条记录)',
// processing: '正在加载中...',
// search: '结果中搜索: ',
// paginate: { sPrevious: ' 上一页 ', sNext: ' 下一页 ', },
// },
// }
// var htmlOptEdit = '<button class="btn btn-outline-primary btn-sm" style="width:80px; height: 28px;" id="btnRowEdit">编辑</button>'
// var htmlOptHref = '<a href="javascript:void(0);" class="table-btn-edit">编辑</a>' +
// // '<a href="javascript:void(0);" class="table-btn-del">删除</a>' +
// '<a href="javascript:void(0);" class="">采购</a>' +
// '<a href="javascript:void(0);" class="">入库</a>' +
// '<a href="javascript:void(0);" class="">销售</a>' +
// '<a href="javascript:void(0);" class="">出库</a>'
// dataTablesOption.columns = [
// { title: '编号', width: '50px' },
// { title: '产品名称', width: '150px' },
// { title: '规格型号', width: '150px' },
// { title: '类别', width: '150px' },
// { title: '库存量', width: '80px' },
// { title: '采购总量', width: '80px' },
// { title: '入库总量', width: '80px' },
// { title: '销售总量', width: '80px' },
// { title: '出库总量', width: '80px' },
// { title: '异常总量', width: '80px' },
// { title: '异常说明' },
// {
// title: '操作',
// width: '300px',
// render: function (data, type, row) { return htmlOptEdit },
// },
// ]
// var table = $('#myTable').DataTable(dataTablesOption)
// var rowid = 0;
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.row.add([++rowid, '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
// table.draw()

View File

@@ -1,4 +1,4 @@
<div class="mycolumn" style="padding: 10px">
<div class="mycol" style="width:100%;padding: 10px">
<div class="myrow" style="height: 40px">
<button id="secpolicyBtn" class="btn btn-success btn-lg" style="width: 120px"
onclick="initSubpage('secpolicy')">安全策略</button>

View File

@@ -1,177 +1,174 @@
<div class="myrow" style="width:100%; height:100%; padding: 10px; ">
<div class="myrow" style="height:100%; padding: 10px; ">
<div style="width: 25%; height: 100%; overflow: hidden">
<div class="mypanel" style="height: calc(30% - 10px)">
<div class="mypanel-icon"></div>
<div class="mypanel-title">运行状况</div>
<div class="mypanel-line"></div>
<div class="mypanel " style="height: calc(30% - 10px)">
<myrow style="width: 100%; height: calc(100% - 40px); margin-top: 10px">
<div class="mypanel-title myline-lb">运行状况</div>
<div class="myrow" style="width: 100%; height: calc(100% - 40px); margin-top: 10px">
<div class="label-bkg" style="width: 30%">
<div class="label-val-lg">123</div>
<div class="label-val-lg">0</div>
<div class="label-tail"></div>
<div class="label-key">安全运行</div>
</div>
<mycolumn style="width: 70%; margin-left: 5px">
<myrow style="width: 100%; height: 33%">
<div class="mycol" style="width: 70%; margin-left: 5px">
<div class="myrow" style="width: 100%; height: 33%">
<div class="label-bkg" style="width: 50%; height: 100%">
<div class="label-key">风机设备</div>
<div class="label-val">100</div>
<div id="windTurbineNum" class="label-val">0</div>
<div class="label-tail"></div>
</div>
<div class="label-bkg" style="width: 50%; height: 100%; margin-left: 5px">
<div class="label-key">光伏设备</div>
<div class="label-val">100</div>
<div id="solarNum" class="label-val">0</div>
<div class="label-tail"></div>
</div>
</myrow>
<myrow style="width: 100%; height: 33%; margin-top: 5px">
</div>
<div class="myrow" style="width: 100%; height: 33%; margin-top: 5px">
<div class="label-bkg" style="width: 50%; height: 100%">
<div class="label-key">累计发电电量</div>
<div class="label-val">100</div>
<div id="electricTotal" class="label-val">0</div>
<div class="label-tail">kWh</div>
</div>
<div class="label-bkg" style="width: 50%; height: 100%; margin-left: 5px">
<div class="label-key">累计入网电量</div>
<div class="label-val">100</div>
<div id="electricInTotal" class="label-val">0</div>
<div class="label-tail">kWh</div>
</div>
</myrow>
<myrow style="width: 100%; height: 33%; margin-top: 5px">
</div>
<div class="myrow" style="width: 100%; height: 33%; margin-top: 5px">
<div class="label-bkg" style="width: 50%; height: 100%">
<div class="label-key">累计收益</div>
<div class="label-val">100</div>
<div id="incomeTotal" class="label-val">0</div>
<div class="label-tail"></div>
</div>
<div class="label-bkg" style="width: 50%; height: 100%; margin-left: 5px">
<div class="label-key">碳减排量</div>
<div class="label-val">100</div>
<div id="carbonReduction" class="label-val">0</div>
<div class="label-tail"></div>
</div>
</myrow>
</mycolumn>
</myrow>
</div>
</div>
</div>
</div>
<div class="mypanel" style="height: calc(35% - 10px)">
<div class="mypanel-icon"></div>
<div class="mypanel-title">光伏设备</div>
<div class="mypanel-line"></div>
<myrow style="margin-top: 10px">
<div class="mypanel-title myline-lb">光伏设备</div>
<div class="myrow" style="margin-top: 10px">
<div class="label-bkg" style="width: 33%; height: 100%; margin-left: 0px">
<div class="label-key">日发电电量</div>
<div class="label-val">100</div>
<div class="label-val">0</div>
<div class="label-tail">kWh</div>
</div>
<div class="label-bkg" style="width: 33%; height: 100%; margin-left: 5px">
<div class="label-key">日入网电量</div>
<div class="label-val">100</div>
<div class="label-val">0</div>
<div class="label-tail">kWh</div>
</div>
<div class="label-bkg" style="width: 33%; height: 100%; margin-left: 5px">
<div class="label-key">日收益金额</div>
<div class="label-val">100</div>
<div class="label-val">0</div>
<div class="label-tail"></div>
</div>
</myrow>
</div>
<div id="mychartSolar" style="width: 100%; height: calc(100% - 90px)"></div>
</div>
<div class="mypanel" style="height: calc(35% - 10px)">
<div class="mypanel-icon"></div>
<div class="mypanel-title">储能设备</div>
<div class="mypanel-line"></div>
<myrow style="margin-top: 10px">
<div class="mypanel-title myline-lb">储能设备</div>
<div class="myrow" style="margin-top: 10px">
<div class="label-bkg" style="width: 50%; height: 100%; margin-left: 0px">
<div class="label-key">日充电电量</div>
<div class="label-val">100</div>
<div class="label-val">0</div>
<div class="label-tail">kWh</div>
</div>
<div class="label-bkg" style="width: 50%; height: 100%; margin-left: 5px">
<div class="label-key">日放电电量</div>
<div class="label-val">100</div>
<div class="label-val">0</div>
<div class="label-tail">kWh</div>
</div>
</myrow>
</div>
<div id="mychartStorage" style="width: 100%; height: calc(100% - 90px)"></div>
</div>
</div>
<div style="margin-left: 10px; width: 50%; height: 100%; overflow: hidden">
<div class="mypanel" style="height: calc(70% - 10px); ">
<myrow style="justify-content: center ; ">
<div style="margin-left: 10px; width: 50%; height: 100%; overflow: hidden; font-size: 14px;">
<div class="mypanel" style="height: calc(70% - 10px); background-color: #012036;">
<div class="myrow" style="justify-content: center ; ">
<div style="display: flex; width: 20%;">
<div style="width:5px; height: 50px; background-color: #f69b52;"></div>
<div style="width:50px; height: 50px; background-color: #f69b5250;"></div>
<mycolumn style="margin-left: 10px;">
<img src="./res/icon-brightness.png"
style="width:50px; height: 50px; object-fit: fill; background-color: #f69b5250;">
<!-- <div style="width:50px; height: 50px; background-color: #f69b5250;"></div> -->
<div class="mycol" style="margin-left: 10px; margin-top: 5px;">
<div>光照</div>
<div id="envIllumination">--</div>
</mycolumn>
</div>
</div>
<div style="display: flex;width: 20%;">
<div style="float: left;width:5px; height: 50px; background-color: #9bd801;"></div>
<div style="width:50px; height: 50px; background-color: #9bd80150;"></div>
<mycolumn style="margin-left: 10px;">
<img src="./res/icon-windspeed.png"
style="width:50px; height: 50px; object-fit: fill; background-color: #9bd80150;">
<!-- <div style="width:50px; height: 50px; background-color: #9bd80150;"></div> -->
<div class="mycol" style="margin-left: 10px; margin-top: 5px;">
<div>风速</div>
<div id="envWindspeed">--</div>
</mycolumn>
</div>
</div>
<div style="display: flex;width: 20%;">
<div style="float: left;width:5px; height: 50px; background-color: #3dfefa;"></div>
<div style="width:50px; height: 50px; background-color: #3dfefa50;"></div>
<mycolumn style="margin-left: 10px;">
<img src="./res/icon-temperature.png"
style="width:50px; height: 50px; object-fit: fill; background-color: #3dfefa50;">
<!-- <div style="width:50px; height: 50px; background-color: #3dfefa50;"></div> -->
<div class="mycol" style="margin-left: 10px; margin-top: 5px;">
<div>环境温度</div>
<div id="envTemperture">--</div>
</mycolumn>
</div>
</div>
<div style="display: flex;width: 20%;">
<div style="float: left;width:5px; height: 50px; background-color: #d83d6c;"></div>
<div style="width:50px; height: 50px; background-color: #d83d6c50;"></div>
<mycolumn style="margin-left: 10px;">
<img src="./res/icon-humidity.png"
style="width:50px; height: 50px; object-fit: fill; background-color: #d83d6c50;">
<!-- <div style="width:50px; height: 50px; background-color: #d83d6c50;"></div> -->
<div class="mycol" style="margin-left: 10px; margin-top: 5px;">
<div>环境湿度</div>
<div id="envHumidity">--</div>
</mycolumn>
</div>
</div>
</myrow>
<img src="./res/overview.png" style="width: 100%; height: calc(100% - 50px); object-fit: fill;"> </img>
</div>
<img src="./res/overview.png" style="width: 100%; height: calc(100% - 60px); object-fit: fill; margin-top: 20px;">
</img>
</div>
<div class="mypanel" style="height: calc(30% - 10px)">
<div class="mypanel-icon"></div>
<div class="mypanel-title">发电功率和辐照度</div>
<div class="mypanel-line"></div>
<div class="mypanel-title myline-lb">发电功率和辐照度</div>
<div id="mychartRunning" style="width: 100%; height: 90%"></div>
</div>
</div>
<div style="margin-left: 10px; width: 25%; height: 100%; overflow: hidden">
<div class="mypanel" style="height: calc(30% - 10px)">
<div class="mypanel-icon"></div>
<div class="mypanel-title">负荷设备</div>
<div class="mypanel-line"></div>
<myrow style="margin-top: 10px">
<div class="mypanel-title myline-lb">负荷设备</div>
<div class="myrow" style="margin-top: 10px">
<div class="label-bkg" style="width: 50%; height: 100%; margin-left: 0px">
<div class="label-key">日用电电量</div>
<div class="label-val">100</div>
<div class="label-val">0</div>
<div class="label-tail">kWh</div>
</div>
<div class="label-bkg" style="width: 50%; height: 100%; margin-left: 5px">
<div class="label-key">日最大功率</div>
<div class="label-val">100</div>
<div class="label-val">0</div>
<div class="label-tail">kW</div>
</div>
</myrow>
</div>
<div id="mychartLoad" style="width: 100%; height: calc(100% - 90px)"></div>
</div>
<div class="mypanel" style="height: calc(35% - 10px)">
<div class="mypanel-icon"></div>
<div class="mypanel-title">充电设备</div>
<div class="mypanel-line"></div>
<myrow style="margin-top: 10px">
<div class="mypanel-title myline-lb">充电设备</div>
<div class="myrow" style="margin-top: 10px">
<div class="label-bkg" style="width: 33%; height: 100%; margin-left: 0px">
<div class="label-key">日充电电量</div>
<div class="label-val">100</div>
<div class="label-val">0</div>
<div class="label-tail">kWh</div>
</div>
<div class="label-bkg" style="width: 33%; height: 100%; margin-left: 5px">
@@ -181,18 +178,16 @@
</div>
<div class="label-bkg" style="width: 33%; height: 100%; margin-left: 5px">
<div class="label-key">日充电收益</div>
<div class="label-val">100</div>
<div class="label-val">0</div>
<div class="label-tail"></div>
</div>
</myrow>
</div>
<div id="mychartCharge" style="width: 100%; height: calc(100% - 90px)"></div>
</div>
<div class="mypanel" style="height: calc(35% - 10px)">
<div class="mypanel-icon"></div>
<div class="mypanel-title">告警信息</div>
<div class="mypanel-line"></div>
<myrow style="margin-top: 10px">
<div class="mypanel-title myline-lb">告警信息</div>
<div class="myrow" style="margin-top: 10px">
<div class="label-bkg" style="width: 33%; height: 100%; margin-left: 0px">
<div class="label-key">日光伏设备告警</div>
<div class="label-val">1</div>
@@ -208,7 +203,7 @@
<div class="label-val">3</div>
<div class="label-tail"></div>
</div>
</myrow>
</div>
<div id="mychartAlert" style="width: 100%; height: calc(100% - 90px)"></div>
</div>
</div>

View File

@@ -1,4 +1,4 @@
optionBar.xAxis.data = ['2025/3/1', '2025/3/2', '2025/3/3', '2025/3/4', '2025/3/5', '2025/3/6', '2025/3/7']
optionBar.xAxis.data = ['03/01', '03/02', '03/03', '03/04', '03/05', '03/06', '03/07']
optionBar.legend.data = ['发电电量', '入网电量']
optionBar.series = [
{ name: '发电电量', type: 'bar', data: [50, 28, 35, 18, 36, 27, 19] },
@@ -47,9 +47,12 @@ function getRandomCurveData(m, n) {
var t0 = Date.parse('2025-03-01 00:00:00')
var step = 600
var N = 86400 / step
var y = 500
for (var i = 0; i <= N; ++i) {
var t = t0 + i * step * 1000
data[i] = { name: t, value: [t, Math.sin(i * 0.1) * (n - m) + m] }
//var y = Math.sin(i * 0.1) * (n - m) + m
y = Math.floor((y + RAND(0, 50) - 25) * 100) / 100
data[i] = { name: t, value: [t, y] }
}
return data
}
@@ -78,6 +81,13 @@ function updatePageData() {
$('#envWindspeed').text('1.5 m/s')
$('#envTemperture').text('27.8 ℃')
$('#envHumidity').text('37.6 %')
// 查询获取统计信息
$('#windTurbineNum').text('8')
$('#solarNum').text('207')
$('#electricTotal').text('153.21')
$('#electricInTotal').text('120.35')
$('#carbonReduction').text('36.17')
}
var timerId = null

View File

@@ -1,4 +1,5 @@
<div class="mycolumn" style="padding: 10px">
<div class="mycol" style="width:100%;padding: 10px">
<div class="myrow" style="height: 40px">
<button id="userBtn" class="btn btn-success btn-lg" style="width: 120px" onclick="initSubpage('user')">人员管理</button>
<button id="roleBtn" class="btn btn-primary" style="width: 120px; margin-left: 10px"
@@ -16,6 +17,7 @@
<button id="syslogBtn" class="btn btn-primary" style="width: 120px; margin-left: 10px"
onclick="initSubpage('syslog')">系统日志</button>
</div>
<hr style="margin: 10px 0 10px 0;" />
<div id="user" style="display: block">
@@ -35,26 +37,31 @@
<div id="role" style="display: none">
<button class="btn btn-success" style="width: 90px" onclick="showPop('role')">新增</button>
<button class="btn btn-success" style="width: 90px; margin-left: 20px" onclick="">查询</button>
<table id="roleTable" class="stripe" style="width: 100%; margin-top: 10px"></table>
</div>
<div id="permission" style="display: none">
<button class="btn btn-success" style="width: 90px" onclick="showPop('permission')">新增</button>
<button class="btn btn-success" style="width: 90px; margin-left: 20px" onclick="">查询</button>
<table id="permissionTable" class="stripe" style="width: 100%; margin-top: 10px"></table>
</div>
<div id="device" style="display: none">
<button class="btn btn-success" style="width: 90px" onclick="showPop('device')">新增</button>
<button class="btn btn-success" style="width: 90px; margin-left: 20px" onclick="">查询</button>
<table id="deviceTable" class="stripe" style="width: 100%; margin-top: 10px"></table>
</div>
<div id="price" style="display: none">
<button class="btn btn-success" style="width: 90px" onclick="showPop('price')">新增</button>
<button class="btn btn-success" style="width: 90px; margin-left: 20px" onclick="">查询</button>
<table id="priceTable" class="stripe" style="width: 100%; margin-top: 10px"></table>
</div>
<div id="policy" style="display: none">
<button class="btn btn-success" style="width: 90px" onclick="showPop('policy')">新增</button>
<button class="btn btn-success" style="width: 90px; margin-left: 20px" onclick="">查询</button>
<table id="policyTable" class="stripe" style="width: 100%; margin-top: 10px"></table>
</div>
@@ -196,7 +203,18 @@
<form id="deviceForm" class="was-validated" style="margin: 0 80px 0 80px; padding-top: 30px">
<div class="input-group mb-3">
<span class="input-group-text" style="width: 90px; background-color: #a6c0da">类型*</span>
<input id="deviceForm_type" type="text" class="form-control" required />
<select id="deviceForm_type" class="form-select" required>
<option value="101">逆变器</option>
<option value="102">汇流箱</option>
<option value="103">光伏板</option>
<option value="104">风力发电机</option>
<option value="105">储能变流器</option>
<option value="106">储能电池</option>
<option value="107">BMS</option>
<option value="108">充电桩</option>
<option value="109">充电枪</option>
<option value="110">集中器</option>
</select>
</div>
<div class="input-group mb-3">
<span class="input-group-text" style="width: 90px; background-color: #a6c0da">名称*</span>
@@ -229,7 +247,23 @@
<div style="display: flex; justify-content: center; padding: 20px 20px 20px 20px">
<button id="deviceFormOk" class="btn btn-success" style="width: 90px; margin-right: 20px" disabled>确定</button>
<button class="btn btn-danger" style="width: 90px; margin-left: 20px"
onclick="G.showElement('device', false)">取消</button>
onclick="G.showElement('devicePop', false)">取消</button>
</div>
</div>
</div>
<div id="deviceAttrPop" class="mask">
<div class="pop" style="height: 500px">
<p id="devicePopTitle" class="pop_title">设备属性设置</p>
<form id="deviceAttrForm" class="was-validated" style="margin: 0 80px 0 80px; padding-top: 30px">
<div class="input-group mb-3"></div>
<div class="input-group mb-3"></div>
</form>
<div style="display: flex; justify-content: center; padding: 20px 20px 20px 20px">
<button id="deviceAttrFormOk" class="btn btn-success" style="width: 90px; margin-right: 20px"
disabled>确定</button>
<button class="btn btn-danger" style="width: 90px; margin-left: 20px"
onclick="G.showElement('deviceAttrPop', false)">取消</button>
</div>
</div>
</div>
@@ -313,6 +347,8 @@
</div>
</div>
<div id="promptPop" class="mask">
<div class="pop" style="height: 240px">
<p id="promptTitle" class="pop_title"></p>

View File

@@ -19,20 +19,29 @@ function renderPolicy(data, type, row) {
}
var deviceTypeDef = {
101: "光伏设备",
102: "充电设备",
103: "储能设备",
104: "汇流箱",
105: "逆变器",
106: "储能变流器",
1: "变压器",
2: "配电柜",
3: "电表",
4: "门禁",
5: "空调",
6: "照明",
7: "消防",
8: "光照监测设备",
9: "风速监测设备",
10: "温湿度监测设备",
11: "烟感监测设备",
12: "水浸传感器",
13: "视频监控",
101: "逆变器",
102: "汇流箱",
103: "光伏板",
104: "风力发电机",
105: "储能变流器",
106: "储能电池",
107: "BMS",
108: "配电柜",
109: "电表",
201: "光照监测设备",
202: "风速监测设备",
203: "温湿度监测设备",
204: "视频监控",
205: "照明设备"
108: "充电桩",
109: "充电枪",
110: "集中器",
}
function renderDeviceType(data, type, row) {
var text = deviceTypeDef[data]
@@ -146,14 +155,13 @@ var tableDef = {
{ title: '是否启用', width: '120px', render: renderIsOpen },
{ title: '创建时间', width: '180px' },
{ title: '更新时间', width: '180px' },
{ title: '更新人', width: '180px' },
{
title: '操作',
width: '200px',
render: function (data, type, row) { return htmlOptEdit + htmlOptDel },
render: function (data, type, row) { return htmlOptEdit + htmlOptAttrs },
},
],
header: ['device_id', 'type', 'name', 'code', 'model', 'factory', 'is_open', 'create_time', 'update_time', 'update_by'],
header: ['device_id', 'type', 'name', 'code', 'model', 'factory', 'is_open', 'create_time', 'update_time', 'attrs'],
query: G.cppNative.queryDeviceList,
update: G.cppNative.updateDevice,
insert: G.cppNative.insertDevice,
@@ -225,9 +233,9 @@ var tableDef = {
}
}
var htmlOptEdit = '<button class="btn btn-outline-primary btn-sm" style="width:80px" id="btnRowEdit">编辑</button>'
var htmlOptEdit = '<button class="btn btn-primary btn-sm" style="width:80px; height:28px;" id="btnRowEdit">编辑</button>'
var htmlOptDel = '' //'<button class="btn btn-outline-danger btn-sm" style="width:80px; margin-left:8px;" id="btnRowDel">删除</button>'
var htmlOptAttrs = '<button class="btn btn-outline-warning btn-sm" style="width:80px; margin-left:8px;" id="btnRowAttrs">属性设置</button>'
var htmlOptAttrs = '<button class="btn btn-primary btn-sm" style="width:80px; height:28px; margin-left:8px;" id="btnRowAttrs">属性设置</button>'
var popRowdata = null
@@ -280,6 +288,11 @@ async function initSubpage(id) {
var row = tableInfo.table.row($(this).closest('tr'))
showPop(id, row.data())
})
tableInfo.table.on('click', '#btnRowAttrs', function () {
var row = tableInfo.table.row($(this).closest('tr'))
showPopDeviceAttr(row.data())
})
}
@@ -302,6 +315,46 @@ function showPop(id, rowData) {
}
}
var deviceAttrKeyDef = {
commType: "通讯方式",
ip: "通讯地址",
port: "通讯端口",
isclient: "客户端",
}
// 显示设备的属性编辑弹窗属性字段格式为JSON: attrs="{}"
function showPopDeviceAttr(rowData) {
G.showElement('deviceAttrPop', true)
var device_id = rowData[0]
var deviceType = rowData[1]
var deviceTypeStr = deviceTypeDef[deviceType]
var attrsStr = rowData[9]
var attrs = { commType: "", ip: "", port: 0, isclient: 1 }
try {
attrs = JSON.parse(attrsStr);
} catch (error) {
}
var elemtForm = document.getElementById('deviceAttrForm')
elemtForm.innerHTML =
`<div class="input-group mb-3">
<span class="input-group-text" style="width: 90px; background-color: #a6c0da">编号</span>
<input type="text" class="form-control" value='${device_id}' disabled />
</div>
<div class="input-group mb-3">
<span class="input-group-text" style="width: 90px; background-color: #a6c0da">设备类型</span>
<input type="text" class="form-control" value='${deviceTypeStr}' disabled />
</div>`
for (k in attrs) {
var title = deviceAttrKeyDef[k]
elemtForm.innerHTML += `<div class="input-group mb-3">
<span class="input-group-text" style="width: 90px; background-color: #a6c0da">${title}</span>
<input type="text" class="form-control" value='${attrs[k]}' />
</div>`
}
}
function showPrompt(text, status) {
G.showElement('promptPop', true)
var promptText = $('#promptText')
@@ -358,6 +411,17 @@ function callbackPopGetParams(id, key) {
return val
}
function updateTableData(id) {
var info = tableDef[id]
var queryFunc = info.query
if (!queryFunc) return
queryFunc(1, 10).then((res) => {
})
}
// 用户弹窗确认
function popConfirm(id) {
// 获取数据表格操作对象
@@ -398,6 +462,15 @@ function popConfirm(id) {
}
}
// 设置设备类型下拉列表
var elementSelectDeviceType = document.getElementById('deviceForm_type')
elementSelectDeviceType.innerHTML = ''
for (k in deviceTypeDef) {
elementSelectDeviceType.options.add(new Option(deviceTypeDef[k], k))
}
$(document).ready(function () {
initSubpage('user')
//G.initTable('user', tableDef['user'])
})

View File

@@ -1,4 +1,4 @@
<div class="mycolumn" style="padding: 10px; overflow: hidden">
<div class="mycol" style="width:100%; height:100%; padding: 10px; overflow: hidden">
<div class="myrow" style="height: 40px">
<button id="solarBtn" class="btn btn-success btn-lg" style="width: 200px"
onclick="initSubPage('solar')">光伏设备运行分析</button>
@@ -22,97 +22,75 @@
</div> -->
<div id="solar" class="mypanelstat" style="height: 100%; display: block;">
<!-- <mycolumn style="width:100%; height: 100%;"> -->
<myrow style="height: 50%; ">
<!-- <div class="mycol" style="width:100%; height: 100%;"> -->
<div class="myrow" style="height: 50%; ">
<div class="mypanel" style="width: 50%; height: calc(100% - 20px); margin: 10px; ">
<div class="mypanel-icon"></div>
<div class="mypanel-title">电量与收益分析</div>
<!-- <div class="mypanel-line"></div> -->
<div class="mypanel-title myline-l">电量与收益分析</div>
<div id="solarEchart1" style="width: 100%; height:calc(100% - 30px)"></div>
</div>
<div class="mypanel" style="width: 50%; height: calc(100% - 20px); margin: 10px; ">
<div class="mypanel-icon"></div>
<div class="mypanel-title">运行状态分析</div>
<!-- <div class="mypanel-line"></div> -->
<div class="mypanel-title myline-l">运行状态分析</div>
<div id="solarEchart2" style="width: 100%; height:calc(100% - 30px)"></div>
</div>
</myrow>
<myrow style="height: 50%; ">
</div>
<div class="myrow" style="height: 50%; ">
<div class="mypanel" style="width: 50%; height: calc(100% - 20px); margin: 10px; ">
<div class="mypanel-icon"></div>
<div class="mypanel-title">日电压/电流分析</div>
<!-- <div class="mypanel-line"></div> -->
<div class="mypanel-title myline-l">日电压/电流分析</div>
<div id="solarEchart3" style="width: 100%; height:calc(100% - 30px)"></div>
</div>
<div class="mypanel" style="width: 50%; height: calc(100% - 20px); margin: 10px; ">
<div class="mypanel-icon"></div>
<div class="mypanel-title">日功率分析</div>
<!-- <div class="mypanel-line"></div> -->
<div class="mypanel-title myline-l">日功率分析</div>
<div id="solarEchart4" style="width: 100%; height:calc(100% - 30px)"></div>
</div>
</myrow>
</div>
</div>
<div id="storage" class="mypanelstat" style="height: 100%; display: none;">
<myrow style="height: 50%; ">
<div class="myrow" style="height: 50%; ">
<div class="mypanel" style="width: 50%; height: calc(100% - 20px); margin: 10px; ">
<div class="mypanel-icon"></div>
<div class="mypanel-title">储能放电分析</div>
<!-- <div class="mypanel-line"></div> -->
<div class="mypanel-title myline-l">储能放电分析</div>
<div id="storageEchart1" style="width: 100%; height:calc(100% - 30px)"></div>
</div>
<div class="mypanel" style="width: 50%; height: calc(100% - 20px); margin: 10px; ">
<div class="mypanel-icon"></div>
<div class="mypanel-title">运行状态分析</div>
<!-- <div class="mypanel-line"></div> -->
<div class="mypanel-title myline-l">运行状态分析</div>
<div id="storageEchart2" style="width: 100%; height:calc(100% - 30px)"></div>
</div>
</myrow>
<myrow style="height: 50%; ">
</div>
<div class="myrow" style="height: 50%; ">
<div class="mypanel" style="width: 50%; height: calc(100% - 20px); margin: 10px; ">
<div class="mypanel-icon"></div>
<div class="mypanel-title">日电压电流分析</div>
<!-- <div class="mypanel-line"></div> -->
<div class="mypanel-title myline-l">日电压电流分析</div>
<div id="storageEchart3" style="width: 100%; height:calc(100% - 30px)"></div>
</div>
<div class="mypanel" style="width: 50%; height: calc(100% - 20px); margin: 10px; ">
<div class="mypanel-icon"></div>
<div class="mypanel-title">日功率分析</div>
<!-- <div class="mypanel-line"></div> -->
<div class="mypanel-title myline-l">日功率分析</div>
<div id="storageEchart4" style="width: 100%; height:calc(100% - 30px)"></div>
</div>
</myrow>
</div>
</div>
<div id="charge" class="mypanelstat" style="height: 100%; display: none;">
<myrow style="height: 50%; ">
<div class="myrow" style="height: 50%; ">
<div class="mypanel" style="width: 50%; height: calc(100% - 20px); margin: 10px; ">
<div class="mypanel-icon"></div>
<div class="mypanel-title">充电与收益分析</div>
<!-- <div class="mypanel-line"></div> -->
<div class="mypanel-title myline-l">充电与收益分析</div>
<div id="chargeEchart1" style="width: 100%; height:calc(100% - 30px)"></div>
</div>
<div class="mypanel" style="width: 50%; height: calc(100% - 20px); margin: 10px; ">
<div class="mypanel-icon"></div>
<div class="mypanel-title">运行状态分析</div>
<!-- <div class="mypanel-line"></div> -->
<div class="mypanel-title myline-l">运行状态分析</div>
<div id="chargeEchart2" style="width: 100%; height:calc(100% - 30px)"></div>
</div>
</myrow>
<myrow style="height: 50%; ">
</div>
<div class="myrow" style="height: 50%; ">
<div class="mypanel" style="width: 50%; height: calc(100% - 20px); margin: 10px; ">
<div class="mypanel-icon"></div>
<div class="mypanel-title">日电压电流分析</div>
<!-- <div class="mypanel-line"></div> -->
<div class="mypanel-title myline-l">日电压电流分析</div>
<div id="chargeEchart3" style="width: 100%; height:calc(100% - 30px)"></div>
</div>
<div class="mypanel" style="width: 50%; height: calc(100% - 20px); margin: 10px; ">
<div class="mypanel-icon"></div>
<div class="mypanel-title">日功率分析</div>
<!-- <div class="mypanel-line"></div> -->
<div class="mypanel-title myline-l">日功率分析</div>
<div id="chargeEchart4" style="width: 100%; height:calc(100% - 30px)"></div>
</div>
</myrow>
</div>
</div>
</div>

View File

@@ -39,8 +39,11 @@ function getRandomCurveData(m, n) {
var t0 = Date.parse('2025-03-01 00:00:00')
var step = 600
var N = 86400 / step
var y = 500;
for (var i = 0; i < N; ++i) {
data[i] = { x: t0 + i * step * 1000, y: Math.sin(i * 0.1) * (n - m) }
// data[i] = { x: t0 + i * step * 1000, y: Math.sin(i * 0.1) * (n - m) }
y = Math.floor((y + RAND(0, 50) - 25) * 100) / 100
data[i] = { x: t0 + i * step * 1000, y: y }
}
return data
}
@@ -56,7 +59,7 @@ function getCurveData(a, b, n) {
}
function RAND(a, b) {
return (Math.random() * (b - a) + a).toFixed(2)
return a + Math.random() * (b - a)
}
// 点击子页面菜单按钮,切换子页面
@@ -89,7 +92,7 @@ function initSubPage(id) {
} else if (item.type == 'line') {
item.echart = initEchartCurve(item.id, item.series)
for (var i = 0; i < item.series.length; ++i) {
updateEchartCurve(item.echart, i, getRandomCurveData(100 * (i + 1), 200 * (i + 1)))
updateEchartCurve(item.echart, i, G.getRandDataDay(100 * (i + 1), 200 * (i + 1)))
}
}

View File

@@ -1,65 +1,157 @@
<div class="mypanelstat" style="height: calc(100% - 20px); margin: 10px">
<myrow style="height: 100%">
<div class="mycolumn" style="width: 18%; height: 100%; padding-top: 10px; ">
<div id="solarCardBtn" class="mycardbtn" style="height: 15%;" onclick="clickCardBtn(this, 'solar')">
<div class="mypanelstat" style="width:100%; height: calc(100% - 20px); margin: 10px">
<div class="myrow" style="height: 100%">
<div class="mycol" style="width: 300px; height: 100%; padding-top: 10px; ">
<div id="solarCardBtn" class="mycardbtn" style="height: 15%;" onclick="onClickCardBtn(this, 'solar')">
<div class="mypanel-title">光伏系统</div>
<mycolumn style="margin-top: 20px; height:60%">
<div>光伏板数量: 100 个</div>
<myrow style="font-size: 14px; margin-top: 10px;">
<div>空闲: 0 个</div>
<div style="margin-left: 30px;">离线: 0 个</div>
<div style="margin-left: 30px;">故障: 0 个</div>
</myrow>
</mycolumn>
<div class="mycol" style="margin-top: 20px; height:60%">
<div id="solarDeviceNum">光伏板数量: 100 个</div>
<div class="myrow" style="font-size: 14px; margin-top: 10px;">
<div id="solarIdleNum">空闲: 0 个</div>
<div id="solarOfflineNum" style="margin-left: 30px;">离线: 0 个</div>
<div id="solarFaultNum" style="margin-left: 30px;">故障: 0 个</div>
</div>
</div>
</div>
<div class="mycardbtn" style="height: 15%;" onclick="clickCardBtn(this, 'storage')">
<div class="mycardbtn" style="height: 15%;" onclick="onClickCardBtn(this, 'storage')">
<div class="mypanel-title">储能系统</div>
<mycolumn style="margin-top: 20px; height:60%">
<div>储能电池数量: 10 个</div>
<myrow style="font-size: 14px; margin-top: 10px;">
<div>空闲: 0 个</div>
<div style="margin-left: 30px;">离线: 0 个</div>
<div style="margin-left: 30px;">故障: 0 个</div>
</myrow>
</mycolumn>
<div class="mycol" style="margin-top: 20px; height:60%">
<div id="storageDeviceNum">储能电池数量: 0 个</div>
<div class="myrow" style="font-size: 14px; margin-top: 10px;">
<div id="storageIdleNum">空闲: 0 个</div>
<div id="storageOfflineNum" style="margin-left: 30px;">离线: 0 个</div>
<div id="storageFaultNum" style="margin-left: 30px;">故障: 0 个</div>
</div>
</div>
</div>
<div class="mycardbtn" style="height: 15%;" onclick="clickCardBtn(this, 'charge')">
<div class="mycardbtn" style="height: 15%;" onclick="onClickCardBtn(this, 'charge')">
<div class="mypanel-title">充电系统</div>
<mycolumn style="margin-top: 20px; height:60%">
<div>充电桩数量: 50 个</div>
<myrow style="font-size: 14px; margin-top: 10px;">
<div>空闲: 0 个</div>
<div style="margin-left: 30px;">离线: 0 个</div>
<div style="margin-left: 30px;">故障: 0 个</div>
</myrow>
</mycolumn>
<div class="mycol" style="margin-top: 20px; height:60%">
<div id="chargeDeviceNum">充电桩数量: 0 个</div>
<div class="myrow" style="font-size: 14px; margin-top: 10px;">
<div id="chargeIdleNum">空闲: 0 个</div>
<div id="chargeOfflineNum" style="margin-left: 30px;">离线: 0 个</div>
<div id="chargeFaultNum" style="margin-left: 30px;">故障: 0 个</div>
</div>
</div>
</div>
<div class="mycardbtn" style="height: 15%;" onclick="clickCardBtn(this, 'load')">
<div class="mycardbtn" style="height: 15%;" onclick="onClickCardBtn(this, 'load')">
<div class="mypanel-title">负荷系统</div>
<mycolumn style="margin-top: 20px; height:60%">
<div>照明设备数量: 100 个</div>
<myrow style="font-size: 14px; margin-top: 10px;">
<div>空闲: 0 个</div>
<div style="margin-left: 30px;">离线: 0 个</div>
<div style="margin-left: 30px;">故障: 0 个</div>
</myrow>
</mycolumn>
<div class="mycol" style="margin-top: 20px; height:60%">
<div id="loadDeviceNum">照明设备数量: 0 个</div>
<div class="myrow" style="font-size: 14px; margin-top: 10px;">
<div id="loadIdleNum">空闲: 0 个</div>
<div id="loadOfflineNum" style="margin-left: 30px;">离线: 0 个</div>
<div id="loadFaultNum" style="margin-left: 30px;">故障: 0 个</div>
</div>
</div>
</div>
<div class="mycardbtn" style="height: 15%;" onclick="clickCardBtn(this, 'security')">
<div class="mycardbtn" style="height: 15%;" onclick="onClickCardBtn(this, 'security')">
<div class="mypanel-title">安防系统</div>
<mycolumn style="margin-top: 20px; height:60%">
<div>摄像头数量: 50 个</div>
<myrow style="font-size: 14px; margin-top: 10px;">
<div class="mycol" style="margin-top: 20px; height:60%">
<div id="securityDeviceNum">摄像头数量: 0 个</div>
<div class="myrow" style="font-size: 14px; margin-top: 10px;">
<div>空闲: 0 个</div>
<div style="margin-left: 30px;">离线: 0 个</div>
<div style="margin-left: 30px;">故障: 0 个</div>
</myrow>
</mycolumn>
</div>
</div>
</div>
</div>
<div style="width: 82%; height: 100%; overflow: auto">
<div id="deviceList" class="myrow" style="width: 100%; height: 100%; flex-wrap: wrap;"> </div>
<div class="myrow" style="width: calc(100% - 300px); height: 100%; ">
<div id="deviceList" class="myrow" style="width: 100%; height: 100%; flex-wrap: wrap; overflow-y: auto;">
<!-- <div class="mycard">
<div class='btn-group' style="width: 80px; position: absolute; left: 100px; top: 30px;">
<input id="_off" type="checkbox" class="btn-check" //
onclick="G.switchSetStatus('_on', '_off', !this.checked)" checked />
<label class="btn btn-outline-danger" for="_off" style="padding: 0;">关</label>
<input id="_on" type="checkbox" class="btn-check" //
onclick="G.switchSetStatus('_on', '_off', this.checked)" />
<label class="btn btn-outline-success" for="_on" style="padding: 0;">开</label>
</div>
</div> -->
</div>
<div id="envpanel" style="width: 300px; height: 100%; display: block">
<div class="mycol" style="width: 250px; height: 100%; padding: 12px;">
<div style="font-size: 16px; font-weight: 600;">环境温湿度信息</div>
<div class="mypanel-line"></div>
<div style="margin-top: 12px;">
<div class="myrow"
style="font-size: 14px; font-weight: 600; justify-content: space-between; border: solid #00fffb; border-radius: 8px 8px 0 0; border-width: 1px 1px 0 1px; background-color: #115d73; height: 40px;line-height: 40px;">
<div style="width: 33%; text-align: center;">点位</div>
<div style="width: 33%; text-align: center;">温度</div>
<div style="width: 33%; text-align: center;">湿度</div>
</div>
<div class="myrow"
style="font-size: 14px; font-weight: 600; justify-content: space-between; border: solid #00fffb; border-radius: 0 0 8px 8px; border-width: 0 1px 1px 1px; height: 40px; line-height: 40px;">
<div style="width: 33%; text-align: center;">#1</div>
<div style="width: 33%; text-align: center;">20℃</div>
<div style="width: 33%; text-align: center;">20%</div>
</div>
</div>
<div style="font-size: 16px; font-weight: 600; margin-top: 30px;">消防信息</div>
<div class="mypanel-line"></div>
<div style="margin-top: 12px; border: 1px solid #00fffb; border-radius: 8px; ">
<div class="myrow"
style="font-size: 14px; font-weight: 600; justify-content: space-between; border-radius: 8px 8px 0 0; background-color: #115d73; height: 40px;line-height: 40px;">
<div style="width: 50%; text-align: center;">点位</div>
<div style="width: 50%; text-align: center;">烟感状态</div>
</div>
<div class="myrow"
style="font-size: 14px; font-weight: 600; justify-content: space-between; height: 40px; line-height: 40px;">
<div style="width: 50%; text-align: center;">#1</div>
<div style="width: 50%; text-align: center;">正常</div>
</div>
<div class="myrow"
style="font-size: 14px; font-weight: 600; justify-content: space-between; height: 40px; line-height: 40px;">
<div style="width: 50%; text-align: center;">#1</div>
<div style="width: 50%; text-align: center;">正常</div>
</div>
<div class="myrow"
style="font-size: 14px; font-weight: 600; justify-content: space-between; height: 40px; line-height: 40px;">
<div style="width: 50%; text-align: center;">#1</div>
<div style="width: 50%; text-align: center;">正常</div>
</div>
<div class="myrow"
style="font-size: 14px; font-weight: 600; justify-content: space-between; height: 40px; line-height: 40px;">
<div style="width: 50%; text-align: center;">#1</div>
<div style="width: 50%; text-align: center;">正常</div>
</div>
<div class="myrow"
style="font-size: 14px; font-weight: 600; justify-content: space-between; height: 40px; line-height: 40px;">
<div style="width: 50%; text-align: center;">#1</div>
<div style="width: 50%; text-align: center;">正常</div>
</div>
<div class="myrow"
style="font-size: 14px; font-weight: 600; justify-content: space-between; height: 40px; line-height: 40px;">
<div style="width: 50%; text-align: center;">#1</div>
<div style="width: 50%; text-align: center;">正常</div>
</div>
<div class="myrow"
style="font-size: 14px; font-weight: 600; justify-content: space-between; height: 40px; line-height: 40px;">
<div style="width: 50%; text-align: center;">#1</div>
<div style="width: 50%; text-align: center;">正常</div>
</div>
</div>
</div>
</div>
</div>
</myrow>
<div id="deviceSettingPop" class="mask" style="display: none;">
<div
style="margin: 200px auto;width:800px; padding: 20px; height: 500px; background-color: #012036f0; border:4px solid #14dcfb; ">
<div class="myline-b" style="color:white;">控制功能</div>
<div style="display: flex; justify-content: center; width: 100%; margin-top: 100px;">
<button class="btn btn-success" style="width:80px; color: white;"
onclick="G.showElement('deviceSettingPop', false)">确定</button>
<button class="btn btn-default" style="width:80px; color: white; margin-left: 50px;"
onclick="G.showElement('deviceSettingPop', false)">取消</button>
</div>
</div>
</div>
</div>
</div>

View File

@@ -1,64 +1,244 @@
var mapDeviceTypeDef = new Map([
['1', '变压器'],
['2', '配电柜'],
['3', '电表'],
['4', '门禁'],
['5', '空调'],
['6', '照明'],
['7', '消防'],
['8', '光照监测设备'],
['9', '风速监测设备'],
['10', '温湿度监测设备'],
['11', '烟感监测设备'],
['12', '水浸传感器'],
['13', '视频监控'],
['101', '逆变器'],
['102', '汇流箱'],
['103', '光伏板'],
['104', '风力发电机'],
['105', '储能变流器'],
['106', '储能电池'],
['107', 'BMS'],
['108', '充电桩'],
['109', '充电枪'],
['110', '集中器'],
])
function getDeviceTypeId(name) {
var res = ''
mapDeviceTypeDef.forEach((v, k) => { if (v == name) { res = k } })
return res;
}
function getDeviceTypeName(id) {
var res = ''
mapDeviceTypeDef.forEach((v, k) => { if (k == id) { res = v } })
return res;
}
function addCard(deviceId, type, name, code) {
var a = '<div class="myrow">' +
'< div style = "width: 100px;height: 70px; background-color: #2991b6;border-radius: 10px;" > </div>' +
'< div class="mycolumn" style = "margin-left: 10px;" > ' +
'<div>3201001234567890</div>' +
'<div>逆变器1 </div>' +
'<div style="color: #08afff; font-size:14px; font-weight: bold;">逆变器 </div>' +
'</div >' +
'</div >'
var elementDeviceList = document.getElementById('deviceList')
// <div class="mycard" ></div>
function addDeviceCardPanel(root, deviceid, name, type, subList) {
var card = document.createElement('div')
card.className = 'mycard'
card.innerHTML = '<div class="myrow" style="margin-bottom: 20px">' +
'<div style="width: 100px;height: 70px; background-color: #2991b6;border-radius: 10px;"></div>' +
'<div class="mycolumn" style="margin-left: 10px;">' +
'<div>' + code + '</div><div>' + name + '</div>' +
'<div style="color: #08afff; font-size:14px; font-weight: bold;">' + type + '</div>' +
'</div></div>'
card.setAttribute('id', deviceid) // 设置id
if (type == "充电桩") { card.style.width = '320px' }
card.innerHTML =
`<div class="myrow" style="margin-bottom: 20px">
<div style="width:64px; height:64px; background-color: #2991b6;border-radius: 10px;"></div>
<div class="mycol" style="margin-left: 10px; font-size:15px;">
<div> ${deviceid} </div>
<div style="font-size:15px;"> ${name} </div>
<div style="color: #08afff; font-size:14px; font-weight: bold;"> ${type} </div>
</div>
</div>`
var params = {
工作状态: '运行',
在线状态: '运行',
故障状态: '运行',
额定功率: '20 kW',
电压: '220 V',
电流: '30 A',
功率: '11 kW',
// 充电桩区分1号枪和2号枪
if (subList && subList.length > 1) {
card.innerHTML +=
`<div class="myrow">
<div id="${deviceid}_${subList[0]}" style="width: calc(50% - 10px); border: solid gray; border-width: 0 1px 0 0;">
<div class="myrow" style="font-size:14px; margin-left: 10px;">
<div style="background-color:#00dbd7; width: 5px; height:18px; "></div>
<div style="margin-left: 10px;">#${subList[0]}</div>
</div>
</div>
<div id="${deviceid}_${subList[1]}" style="width: calc(50% - 10px); margin-left: 10px;">
<div class="myrow" style="font-size:14px; margin-left: 10px;">
<div style="background-color:#00dbd7; width: 5px; height:18px; "></div>
<div style="margin-left: 10px;">#${subList[1]}</div>
</div>
</div>
</div>`
}
Object.keys(params).forEach((k) => {
var id = deviceId + '_' + k
card.innerHTML += ('<div class="mycard-param">' +
'<div class="mycard-param-title">' + k + '</div>' + '<div id="' + id + '" class="mycard-param-text">' + params[k] + '</div>' +
'</div>')
});
elementDeviceList.appendChild(card)
root.appendChild(card)
return card
}
function updateParam(deviceId, k, v) {
var id = deviceId + '_' + k
document.getElementById(id).innerHTML = v
/// ===========================================================
// 创建设备卡片的参数信息
// @param deviceid: 设备 ID
// @param subid: 参数子分类 ID如充电桩的充电枪的编号1号枪2号枪
// @param key: 参数名称
// @param key: 参数值
// 说明: 每个参数值的 element 的 id 设置为:{deviceid}_{subid}_{key}
function addDeviceCardParam(deviceid, subid, key, text) {
var elemtid = deviceid + (subid ? ("_" + subid) : "") + "_" + key
param = document.createElement('div')
param.className = 'mycard-param'
param.innerHTML = `<div class="mycard-param-key">${key}: </div>
<div id="${elemtid}" class="mycard-param-text">${text}</div>`
if (subid) {
$('#' + deviceid + '_' + subid).append(param)
} else {
$('#' + deviceid).append(param)
}
if (text == '离线' | text == '故障') {
$("#" + elemtid).css("color", "red")
}
}
/// ===========================================================
// 设置设备卡片的参数值
// @param deviceid: 设备ID
// @param subid: 参数子分类ID如充电桩的充电枪的编号1号枪2号枪
// @param key: 参数名称
// @param key: 参数值
// 说明: 每个参数值的 element 的 id 设置为:{deviceid}_{subid}_{key}
function setDeviceCardParam(deviceid, subid, key, text) {
var elemtid = deviceid + (subid ? ("_" + subid) : "") + "_" + key
$("#" + elemtid).text(text);
// 特殊状态设置颜色区分显示
if (text == '离线' | text == '故障') {
$("#" + elemtid).css("color", "red")
}
}
var activeCardBtn = null
function clickCardBtn(btn, id) {
function onClickCardBtn(btn, id) {
if (activeCardBtn) activeCardBtn.className = 'mycardbtn'
activeCardBtn = btn
activeCardBtn.className = 'mycardbtn-active'
var deviceType = id
initDeviceList(deviceType)
}
function initDeviceList() {
function creatElementSwitch(id, x, y) {
var eswitch = document.createElement('div')
eswitch.className = 'btn-group'
eswitch.setAttribute('style', `margin-left: 5px; width: 60px; height: 26px; position:absolute; left: ${x}px; top: ${y}px`);
eswitch.innerHTML = `
<input id="${id}_off" type="checkbox" class="btn-check"
onclick="G.switchSetStatus('${id}_on', '${id}_off', !this.checked)" checked />
<label class="btn btn-outline-danger" for="${id}_off" style="padding: 0;">关</label>
<input id="${id}_on" type="checkbox" class="btn-check"
onclick="G.switchSetStatus('${id}_on', '${id}_off', this.checked)" />
<label class="btn btn-outline-success" for="${id}_on" style="padding: 0;">开</label>`
return eswitch;
}
function creatElementCard() {
var card = document.createElement('div')
card.className = 'mycard'
return card;
}
function createCardVideo(name) {
var elemt = document.createElement('div')
elemt.className = 'mycard'
elemt.style.width = '320px'
elemt.innerHTML = `
<div>${name}</div>
<div style='width=90%; height:84%; margin-top:10px; border: 5px solid black;'>
<div style='width:100%; height:100%; line-height:200px; text-align: center; background-color: gray'> 无信号</div>
</div>`
return elemt;
}
function initDeviceList(deviceType) {
var elemtDeviceList = document.getElementById('deviceList')
elemtDeviceList.innerHTML = ''
var subList = [null]
if (deviceType === 'security') {
document.getElementById('envpanel').style.display = 'block'
elemtDeviceList.appendChild(createCardVideo('监控点1'))
elemtDeviceList.appendChild(createCardVideo('监控点2'))
elemtDeviceList.appendChild(createCardVideo('监控点3'))
elemtDeviceList.appendChild(createCardVideo('监控点4'))
elemtDeviceList.appendChild(createCardVideo('监控点5'))
elemtDeviceList.appendChild(createCardVideo('监控点6'))
elemtDeviceList.appendChild(createCardVideo('监控点7'))
elemtDeviceList.appendChild(createCardVideo('监控点8'))
elemtDeviceList.appendChild(createCardVideo('监控点9'))
elemtDeviceList.appendChild(createCardVideo('监控点1'))
elemtDeviceList.appendChild(createCardVideo('监控点2'))
elemtDeviceList.appendChild(createCardVideo('监控点3'))
elemtDeviceList.appendChild(createCardVideo('监控点4'))
elemtDeviceList.appendChild(createCardVideo('监控点5'))
elemtDeviceList.appendChild(createCardVideo('监控点6'))
elemtDeviceList.appendChild(createCardVideo('监控点7'))
elemtDeviceList.appendChild(createCardVideo('监控点8'))
elemtDeviceList.appendChild(createCardVideo('监控点9'))
return
}
var reqDeviceType = ['101', '102', '103']
if (deviceType === 'storage') {
reqDeviceType = ['101', '102', '106']
}
else if (deviceType === 'charge') {
subList = ['1', '2']
reqDeviceType = ['108']
}
else {
document.getElementById('envpanel').style.display = 'none'
}
// 查询数据库,获取设备信息
//G.cppNative.queryDevice({ type: reqDeviceType }).then((res) => {
G.cppNative.getDeviceInfo(reqDeviceType).then((res) => {
res.forEach(function (item, index) {
var deviceType = getDeviceTypeName(item.type)
addDeviceCardPanel(elemtDeviceList, item.device_id, item.name, deviceType, subList)
var params = {
在线状态: (item.online == 0) ? '离线' : '在线',
工作状态: (item.status == 0) ? '空闲' : '运行',
故障状态: (item.err == 0) ? '正常' : '故障',
额定功率: '-- kW',
电压: '-- V',
电流: '-- A',
功率: '-- kW',
}
if (subList) {
subList.forEach((subid) => {
Object.keys(params).forEach((k) => {
addDeviceCardParam(item.device_id, subid, k, params[k]);
});
})
}
var elemtPanel = document.getElementById(item.device_id)
elemtPanel.innerHTML += `<button
class="btn btn-outline-primary btn-sm"
style="height:30px; margin: 5px 0 0 10px"
onclick="onDeviceSetting(${item.device_id})">
参数设置
</button>`
})
})
}
function onDeviceSetting(deviceid) {
G.showElement('deviceSettingPop', true)
}
// ====================================================================================================
// 【注意】 DOM 元素的移除不会自动清理 JavaScript 运行时创建的资源(如定时器、事件监听器等),这些都需要手动管理
// 开启定时器更新页面数据
var timerId = null
@@ -69,27 +249,43 @@ document.currentScript.addEventListener('DOMNodeRemoved', () => {
clearInterval(timerId);
});
$(document).ready(function () {
addCard('1', '逆变器', '逆变器1', '1111')
addCard('2', '汇流箱', '汇流箱', '2222')
addCard('3', '光伏板', '光伏板1', '3333')
addCard('4', '光伏板', '光伏板2', '4444')
addCard('5', '光伏板', '光伏板3', '5555')
addCard('5', '光伏板', '光伏板3', '5555')
addCard('5', '光伏板', '光伏板3', '5555')
addCard('5', '光伏板', '光伏板3', '5555')
addCard('5', '光伏板', '光伏板3', '5555')
addCard('5', '光伏板', '光伏板3', '5555')
addCard('5', '光伏板', '光伏板3', '5555')
addCard('5', '光伏板', '光伏板3', '5555')
addCard('5', '光伏板', '光伏板3', '5555')
addCard('5', '光伏板', '光伏板3', '5555')
addCard('5', '光伏板', '光伏板3', '5555')
addCard('5', '光伏板', '光伏板3', '5555')
onClickCardBtn(document.getElementById('solarCardBtn'), 'solar')
// timerId = setInterval(() => {
// updateParam('1', '电压', Math.floor(Math.random() * 220) + ' V')
// }, 2000);
clickCardBtn(document.getElementById('solarCardBtn'), 'solar')
G.cppNative.getDeviceInfo([0]).then((res) => {
var nums = {
'103': { num: 0, numIdle: 0, numOffline: 0, numFault: 0 },
'106': { num: 0, numIdle: 0, numOffline: 0, numFault: 0 },
'108': { num: 0, numIdle: 0, numOffline: 0, numFault: 0 },
}
res.forEach(function (item, index) {
var deviceType = item.type + ''
if (nums[deviceType]) {
nums[deviceType].num += 1
if (item.status == 0) nums[deviceType].numIdle += 1
if (item.online == 0) nums[deviceType].numOffline += 1
if (item.err != 0) nums[deviceType].numFault += 1
}
})
$('#solarDeviceNum').text('光伏板数量: ' + nums['103'].num + ' 个')
$('#solarIdleNum').text('空闲: ' + nums['103'].numIdle + ' 个')
$('#solarOfflineNum').text('离线: ' + nums['103'].numOffline + ' 个')
$('#solarFaultNum').text('故障: ' + nums['103'].numFault + ' 个')
$('#storageDeviceNum').text('储能电池数量: ' + nums['106'].num + ' 个')
$('#storageIdleNum').text('空闲: ' + nums['106'].numIdle + ' 个')
$('#storageOfflineNum').text('离线: ' + nums['106'].numOffline + ' 个')
$('#storageFaultNum').text('故障: ' + nums['106'].numFault + ' 个')
$('#chargeDeviceNum').text('充电桩数量: ' + nums['108'].num + ' 个')
$('#chargeIdleNum').text('空闲: ' + nums['108'].numIdle + ' 个')
$('#chargeOfflineNum').text('离线: ' + nums['108'].numOffline + ' 个')
$('#chargeFaultNum').text('故障: ' + nums['108'].numFault + ' 个')
})
timerId = setInterval(() => {
updateParam('1', '电压', Math.floor(Math.random() * 220) + ' V')
}, 2000);
})

View File

@@ -0,0 +1,30 @@
<div class="mycol" style="width:100%; height:100%; padding: 10px; overflow: hidden">
<div class="myrow" style="height: 50%; ">
<div class="mypanel" style="width: 100%; height: calc(100% - 20px); margin: 10px; position:relative">
<div class="myrow">
<div class="mypanel-title myline-l">光伏发电预测</div>
<div style="margin: 0px 0 0 50px; font-size: 12px; font-weight:bold; color:#a6a6a6; ">
当天累计发电量 <span style="font-size: 16px; font-weight:bold; color:white"> 1520 kW/h</span>
</div>
</div>
<div id="solarEchart" style="width: 100%; height:calc(100% - 30px); "></div>
</div>
</div>
<div class="myrow" style="height: 50%; ">
<div class="mypanel" style="width: 50%; height: calc(100% - 20px); margin: 10px; ">
<div class="mypanel-title myline-l">充电负荷预测</div>
<!-- <div class="mypanel-line"></div> -->
<div id="chargeEchart" style="width: 100%; height:calc(100% - 30px)"></div>
</div>
<div class="mypanel" style="width: 50%; height: calc(100% - 20px); margin: 10px; ">
<div class="mypanel-title myline-l">用电负荷预测</div>
<!-- <div class="mypanel-line"></div> -->
<div id="loadEchart" style="width: 100%; height:calc(100% - 30px)"></div>
</div>
</div>
<table id="myTable" class="stripe" style="width: 100%; margin-top: 10px"></table>
</div>

View File

@@ -0,0 +1,45 @@
var chartDef = [
{ id: 'solarEchart', echart: null, type: 'bar', series: ['预测功率', '实时功率', '预测发电量', '实时发电量'] },
{ id: 'chargeEchart', echart: null, type: 'bar', series: ['预测功率', '实时功率'] },
{ id: 'loadEchart', echart: null, type: 'line', series: ['预测功率', '实时功率'] },
]
function RAND(a, b) {
return (a + Math.random() * (b - a))
}
function getRandomCurveData(m, n) {
var data = []
var t0 = Date.parse('2025-03-01 00:00:00')
var step = 600
var N = 86400 / step
for (var i = 0; i < N; ++i) {
//data[i] = { x: t0 + i * step * 1000, y: Math.sin(i * 0.1) * (n - m) }
data[i] = { x: t0 + i * step * 1000, y: RAND(m, n) }
}
return data
}
function getRandomData1(m, n) {
var data = []
var t0 = Date.parse('2025-03-01 00:00:00')
var step = 600
var N = 86400 / step
var y = 500;
for (var i = 0; i < N; ++i) {
//data[i] = { x: t0 + i * step * 1000, y: Math.sin(i * 0.1) * (n - m) }
y = Math.floor((y + RAND(0, 50) - 25) * 100) / 100
data[i] = { x: t0 + i * step * 1000, y: y }
}
return data
}
chartDef.forEach((item) => {
item.echart = initEchartCurve(item.id, item.series)
updateEchartCurve(item.echart, 1, getRandomData1(100, 200))
for (var i = 0; i < item.series.length; ++i) {
updateEchartCurve(item.echart, i, getRandomData1(300 * (i + 1), 400 * (i + 1)))
}
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 879 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 726 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 749 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 679 B

View File

@@ -0,0 +1,128 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>光储充站控系统</title>
<script src="./libs/jquery/jquery-3.7.1.min.js"></script>
<link rel="stylesheet" href="./libs/DataTables-2.1.8/css/dataTables.dataTables.css" />
<script src="./libs/DataTables-2.1.8/js/dataTables.js"></script>
<style>
body {
/* background-color: #012036; */
/* background-image: url('../ui/bkg01.png'); */
background-size: 100% 100%;
background-attachment: fixed;
}
button {
color: #f0f0f0;
background-color: #44aaec;
border: 1px solid #0a87da;
border-radius: 5px;
margin: 5px;
height: 40px;
font-size: 16px;
}
</style>
</head>
<body>
<table id="myTable" class="cell-border compact hover order-column stripe">
<thead>
<tr></tr>
</thead>
<tbody></tbody>
</table>
</body>
<script>
const dataTablesOption = {
data: [],
columns: [],
bSort: false,
aLengthMenu: [10, 20, 50, 100], //设置每页显示数据条数的下拉选项
displayLength: 20, //每页初始显示最大记录数量
// 设置表格t、分页数据条数l、搜索框f、表格信息i、分页p、加载信息r
//dom: '<"table-ext"<"item"f><"item"l><"item"i><"item"p>>rt',
language: {
sLengthMenu: '每页显示 _MENU_ 条记录',
sZeroRecords: '对不起,查询不到任何相关数据',
sInfo: '当前显示 _START_ 到 _END_ 条,共 _TOTAL_ 条记录',
sInfoEmtpy: '找不到相关数据',
sInfoFiltered: '数据表中共为 _MAX_ 条记录)',
sProcessing: '正在加载中...',
sSearch: '结果中搜索',
paginate: { sPrevious: ' 上一页 ', sNext: ' 下一页 ', },
},
}
$(document).ready(function () {
dataTablesOption.columns = [
{ title: '编号1', width: '50px' },
{ title: '产品名称', width: '150px' },
{ title: '规格型号', width: '150px' },
{ title: '类别', width: '150px' },
{ title: '库存量', width: '80px' },
{ title: '采购总量', width: '80px' },
{ title: '入库总量', width: '80px' },
{ title: '销售总量', width: '80px' },
{ title: '出库总量', width: '80px' },
{ title: '异常总量', width: '80px' },
{ title: '异常说明' },
{
title: '操作',
width: '160px',
render: function (data, type, row) {
return (
'<a href="javascript:void(0);" class="table-btn-edit">编辑</a>' +
// '<a href="javascript:void(0);" class="table-btn-del">删除</a>' +
'<a href="javascript:void(0);" class="">采购</a>' +
'<a href="javascript:void(0);" class="">入库</a>' +
'<a href="javascript:void(0);" class="">销售</a>' +
'<a href="javascript:void(0);" class="">出库</a>'
)
},
},
]
var table = $('#myTable').DataTable(dataTablesOption)
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.row.add(['1', '产品名称', '产品型号', '五金类库/五金制品', '', '', '', '', '', '', ''])
table.draw()
})
</script>
</html>