Files
ljwx-health/ljwx-bigscreen/bigscreen/bigScreen/templates/personal_old.html
T
bruno ce2937c9d1 feat: 添加 ljwx-bigscreen/bigscreen/bigScreen 目录所有重要代码文件
- 🐍 添加所有 Python 源码文件(*.py)
- 📄 添加所有 HTML 模板文件(templates/)
- 🗂️ 添加控制器、模型、测试等目录结构
- 📋 添加文档文件(*.md)和配置文件
- ⚙️ 更新 .gitignore 配置,只忽略日志和 SQL 文件
- 🚀 确保所有重要代码都被 Git 跟踪和版本控制

根据要求:ljwx-bigscreen/bigscreen/bigScreen 里面除了 log 和 sql 都需要提交
2025-08-14 21:09:12 +08:00

1527 lines
64 KiB
HTML

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="utf-8">
<title>智能穿戴管理演示大屏</title>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/personal-index.css') }}">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.socket.io/4.0.0/socket.io.min.js"></script>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/profile-button.css') }}">
<style type="text/css">
.profile-button a {
color: #28a745; /* 链接文字为绿色 */
text-decoration: none;
font-size: 12px;
}
.profile-button a:hover {
color: #1e7e34; /* 鼠标悬停时,文字变深绿 */
}
/*resize*/
.breathe-zct{ position:relative; width:20px; height:20px; top:2px;float:left; border:1px solid #008000; border-radius:20px; color:#fff; font-size:10px; cursor:pointer; box-shadow:0 1px 2px rgba(0,0,0,.3); overflow:hidden;
background-image: -webkit-gradient(linear, left top, left bottom, from(#00FF00), to(#00FF00));
background-image: -moz-linear-gradient(#00FF00,#00FF00);
}
.breathe-yct{ position:relative; width:20px; height:20px; top:2px;float:left; border:1px solid #008000; border-radius:20px; color:#fff; font-size:20px; cursor:pointer; box-shadow:0 1px 2px rgba(0,0,0,.3); overflow:hidden;
background-image: -webkit-gradient(linear, left top, left bottom, from(#FF0000), to(#FF0000));
background-image: -moz-linear-gradient(#FF0000,#FF0000);
}
.breathe-zc{ position:relative; width:20px; height:20px; margin:10px auto; line-height:40px; border:1px solid #008000; border-radius:10px; color:#fff; font-size:20px; text-align:center; cursor:pointer; box-shadow:0 1px 2px rgba(0,0,0,.3); overflow:hidden;
background-image: -webkit-gradient(linear, left top, left bottom, from(#00FF00), to(#00FF00));
background-image: -moz-linear-gradient(#00FF00,#00FF00);
-webkit-animation-timing-function: ease-in-out;
-webkit-animation-name: breathe;
-webkit-animation-duration: 500ms;
-webkit-animation-iteration-count: infinite;
-webkit-animation-direction: alternate;
animation:ease-in-out breathe 500ms infinite alternate;
}
@keyframes breathe{
0% { opacity: .2; box-shadow:0 1px 2px rgba(255,255,255,0.1);}
100% { opacity: 1; border:1px solid rgba(59,235,235,1); box-shadow:0 1px 30px rgba(59,255,255,1);}
}
@-webkit-keyframes breathe {
0% { opacity: .2; box-shadow:0 1px 2px rgba(255,255,255,0.1);}
100% { opacity: 1; border:1px solid rgba(59,235,235,1); box-shadow:0 1px 30px rgba(59,255,255,1);}
}
.breathe-yc{ position:relative; width:20px; height:20px; margin:10px auto; line-height:40px; border:1px solid #008000; border-radius:10px; color:#fff; font-size:20px; text-align:center; cursor:pointer; box-shadow:0 1px 2px rgba(0,0,0,.3); overflow:hidden;
background-image: -webkit-gradient(linear, left top, left bottom, from(#FF0000), to(#FF0000));
background-image: -moz-linear-gradient(#FF0000,#FF0000);
-webkit-animation-timing-function: ease-in-out;
-webkit-animation-name: breathe;
-webkit-animation-duration: 1000ms;
-webkit-animation-iteration-count: infinite;
-webkit-animation-direction: alternate;
animation:ease-in-out breathe 500ms infinite alternate;
}
@keyframes breathe{
0% { opacity: .2; box-shadow:0 1px 2px rgba(255,255,255,0.1);}
100% { opacity: 1; border:1px solid rgba(59,235,235,1); box-shadow:0 1px 30px rgba(59,255,255,1);}
}
@-webkit-keyframes breathe {
0% { opacity: .2; box-shadow:0 1px 2px rgba(255,255,255,0.1);}
100% { opacity: 1; border:1px solid rgba(59,235,235,1); box-shadow:0 1px 30px rgba(59,255,255,1);}
}
</style>
</head>
<body>
<div class="content">
<div class="left">
<!--气压-->
<div class="air">
<div class="air-title title numfont">指标指数</div>
<div class="air-relative">
<div class="air-val">
<span class="air-icon"></span>
<div class="numfont">
<p class="hpa-rel"></p>
<p class="hpa-nam">健康指数</p>
</div>
</div>
<div class="gray">
</div>
<div class="light">
</div>
</div>
<div class="air-absolutely">
<div class="air-val">
<span class="air-icon"></span>
<div class="numfont">
<p class="hpa-abs"></p>
<p class="hpa-nam">告警指数</p>
</div>
</div>
<div class="gray">
</div>
<div class="light">
</div>
</div>
</div>
<!--气压 end-->
<!--温度和湿度-->
<div class="tem-hum">
<div class="air-title title numfont">实时体征数据</div>
<div class="temperature">
<div class="tem-hum-title numfont">实时心率</div>
<div class="tem-hum-chart" id="heartRateChart">
</div>
<div class="heartRate-val">
<button class="profile-button">87</button>
</div>
</div>
<div class="humidity">
<div class="tem-hum-title numfont">实时血氧</div>
<div class="tem-hum-chart" id="bloodOxygenChart">
</div>
<div class="bloodOxygen-val">
<button class="profile-button">87</button>
</div>
</div>
</div>
<div class="tem-hum">
<div class="temperature">
<div class="tem-hum-title numfont">实时血压</div>
<div class="tem-hum-chart" id="pressureChart">
</div>
<div class="pressure-val">
<button class="profile-button">101/101</button>
</div>
</div>
<div class="humidity">
<div class="tem-hum-title numfont">实时体温</div>
<div class="tem-hum-chart" id="temperatureChart">
</div>
<div class="temperature-val">
<button class="profile-button">33</button>
</div>
</div>
</div>
<!--温度和湿度 end-->
<!--温度一周k线图-->
</div>
<div class="middle">
<div class="headTitle">灵境万象智能穿戴个人大屏</div>
<!--地图-->
<div class="chinaMap" style="color: white;">
<div class="circle0"></div>
<div id="btn" style="display: none;">
<div style="position: relative;">
<div class="btn0"></div>
<div class="btn1"></div>
<div class="btn2"></div>
</div>
</div>
<div class="mapBox">
<div id="map">
</div>
</div>
</div>
<!--地图 end-->
<!--动画-->
<div class="lineRun">
</div>
<!--动画 end-->
</div>
<div class="right">
<div class="rainfall">
<div class="air-title title numfont">设备状态</div>
<div class="hp_con_right_u">
<table class="table3" style="border:0px; width:96%">
<tbody style="border:0px;">
<!--<tr><td colspan="4"><p style="width:9.6rem;">暂无数据</p></td></tr>-->
<tr style="border:0px;">
<td style="border:0px;"><div id="wearStatus" class="breathe-zc"></div></td>
<td style="border:0px;"><div id="chargeStatus" class="breathe-zc"></div></td>
<td style="border:0px;"><div id="onlineStatus" class="breathe-zc"></div></td>
<td style="border:0px;"><div id="alertStatus" class="breathe-zc"></div></td>
</tr>
<tr style="border:0px;">
<td style="border:0px;">佩戴状态</td>
<td style="border:0px;">充电状态</td>
<td style="border:0px;">在线状态</td>
<td style="border:0px;">告警状态</td>
</tr>
</tbody>
</table>
<div class="message-table">
<table>
<thead>
<tr>
<th>消息内容</th>
<th>消息类型</th>
<th>操作</th>
</tr>
</thead>
<tbody id="message-table-body">
</tbody>
</table>
</div>
</div>
</div>
<!--风-->
<div class="wind">
<div class="air-title title numfont">健康画像</div>
<div id="windChart">
</div>
<div class="windData">
<div class="windSpeed">
<div class="windTitle numfont">健康指数</div>
<div class="windBox">
<div style="width: 20%;margin-left: 4%;">
<p><span class="currentSpeed" id="nowWind">64</span></p>
</div>
<div style="width: 30%;margin-left: 4%;">
<p><span>心率:2.8</span></p>
<p><span>血氧:5.3</span></p>
<p><span>体温:7.1</span></p>
</div>
<div style="width: 30%;margin-left: 4%;">
<p><span>压力:5.4</span></p>
<p><span>睡眠:10.6</span></p>
<p><span>步数:8.5</span></p>
</div>
</div>
</div>
<div class="gust">
<div class="windTitle numfont">健康基线</div>
<div class="windBox">
<div style="width: 30%;margin-left: 4%;">
<p><span class="healthIndex">心率</span></p>
<p><span id="heartRate">86-118</span></p>
</div>
<div style="width: 30%;margin-left: 4%;">
<p><span class="healthIndex">血氧</span></p>
<p><span id="bloodOxygen">90-100</span></p>
</div>
<div style="width: 30%;">
<p><span class="healthIndex">血压</span></p>
<p><span id="bloodPressure">120-130</span></p>
</div>
<div style="width: 30%;margin-left: 4%;">
<p><span class="healthIndex">心率</span></p>
<p><span id="heartRate">86-118</span></p>
</div>
<div style="width: 30%;margin-left: 4%;">
<p><span class="healthIndex">血氧</span></p>
<p><span id="bloodOxygen">90-100</span></p>
</div>
<div style="width: 30%;">
<p><span class="healthIndex">血压</span></p>
<p><span id="bloodPressure">120-130</span></p>
</div>
</div>
</div>
</div>
</div>
<!--风 end-->
<!--降雨量-->
<div class="rainfall">
<div class="alert-table">
<table>
<thead>
<tr>
<th>告警类型</th>
<th>告警级别</th>
<th>告警时间</th>
<th>操作</th>
</tr>
</thead>
<tbody id="alert-table-body">
<!-- Existing static rows can be removed if you want to fully rely on dynamic data -->
</tbody>
</table>
</div>
</div>
<!--降雨量 end-->
</div>
</div>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='personal-js/jquery-3.2.1.min.js') }}">
<script src="{{ url_for('static', filename='personal-js/echarts.js') }}"></script>
<script src="{{ url_for('static', filename='personal-js/china.js') }}"></script>
<script src="{{ url_for('static', filename='personal-js/render.js') }}"></script>
<script>
function initialize() {
for (var i = 0; i < 50; i++) {
$('.air-relative').find('.gray').append('<span></span>');
$('.air-absolutely').find('.gray').append('<span></span>')
}
var pressureValRel = 0; //初始气压(相对)
var pressureValNowRel = 43; //当前气压(相对)
function airPreRel(now, old, par) {
if (now > old) {
par.find('.light').append('<span></span>');
pressureValRel++;
} else if (now < old) {
par.find('.light').children('span:last-child').remove();
pressureValRel--;
} else {
clearInterval(pressureRunRel);
return
}
$('.hpa-rel').text(pressureValRel * 2);
}
var pressureRunRel = setInterval(function() {
airPreRel(pressureValNowRel, pressureValRel, $('.air-relative'));
}, 50);
var pressureValAbs = 0; //初始气压(绝对)
var pressureValNowAbs = 33; //当前气压(绝对)
function airPreAbs(now, old, par) {
if (now > old) {
par.find('.light').append('<span></span>');
pressureValAbs++;
} else if (now < old) {
par.find('.light').children('span:last-child').remove();
pressureValAbs--;
} else {
clearInterval(pressureRunAbs);
return
}
$('.hpa-abs').text(pressureValAbs * 2);
}
var pressureRunAbs = setInterval(function() {
airPreAbs(pressureValNowAbs, pressureValAbs, $('.air-absolutely'));
}, 50);
//温度和湿度
var heartRateChart = echarts.init(document.getElementById('heartRateChart'));
var bloodOxygenChart = echarts.init(document.getElementById('bloodOxygenChart'));
var pressureChart = echarts.init(document.getElementById('pressureChart'));
var temperatureChart = echarts.init(document.getElementById('temperatureChart'));
var heartRateOption = {
tooltip: {
formatter: '{a}<br/>当前:{c}次/分'
},
series: [
//内圈
{
type: 'gauge',
center: ['50%', '60%'], // 默认全局居中
radius: '30%',
min: 0,
max: 10,
startAngle: 270,
endAngle: -89.99999,
splitNumber: 10,
axisLine: { // 仪表盘轴线
lineStyle: { // 属性lineStyle控制线条样式
color: [
[1, '#ff4500']
],
width: 0,
shadowColor: '#fff', //默认透明
shadowBlur: 10
}
},
axisLabel: { // 刻度标签
show: false
},
axisTick: { // 刻度
length: 4, // 属性length控制线长
lineStyle: { // 属性lineStyle控制线条样式
color: 'rgba(176,204,53,.5)'
}
},
splitLine: { // 分隔线
show: false
},
pointer: {
width: 0,
shadowColor: '#fff', //默认透明
shadowBlur: 5
},
detail: {
show: false
}
},
//中圈
{
name: '转速',
type: 'gauge',
center: ['50%', '60%'], // 默认全局居中
radius: '60%',
min: 0,
max: 10,
splitNumber: 10,
axisLine: { // 坐标轴线
lineStyle: { // 属性lineStyle控制线条样式
color: [
[1, '#6E6560']
],
width: 8,
shadowBlur: 10
}
},
axisLabel: { // 刻度
textStyle: { // 属性lineStyle控制线条样式
fontWeight: '',
color: 'rgba(30,144,255,0)',
shadowColor: '#fff', //默认透明
shadowBlur: 10
}
},
axisTick: { // 坐标轴小标记
length: 2, // 属性length控制线长
lineStyle: { // 属性lineStyle控制线条样式
color: 'auto'
/*shadowColor : '#fff', //默认透明
shadowBlur: 10*/
}
},
splitLine: { // 分隔线
length: 0, // 属性length控制线长
lineStyle: { // 属性lineStyle(详见lineStyle)控制线条样式
width: 0,
color: '#fff',
shadowColor: '#fff', //默认透明
shadowBlur: 10
}
},
pointer: {
width: 0,
shadowColor: '#fff', //默认透明
shadowBlur: 5
},
detail: {
show: false
}
},
//外圈室内
{
type: 'gauge',
center: ['50%', '60%'], // 默认全局居中
radius: '100%',
min: 60, // Updated minimum value
max: 150, // Updated maximum value
name: '心率',
axisLine: { // 坐标轴线
lineStyle: {
color: [
[0.33, '#FF0000'], // Red for 60-100
[0.67, '#00FF00'], // Green for 100-130
[1, '#FF0000'] // Red for 130-150
], // Adjusted color segments
width: 1
}
},
itemStyle: {
normal: {
color: '#FF0000'
}
},
axisTick: {
length: 3
},
axisLabel: { // 坐标轴小标记
textStyle: { // 属性lineStyle控制线条样式
fontWeight: 'bolder',
fontSize: 10,
fontFamily: 'numfont'
}
},
splitLine: { // 分隔线
length: 5, // 属性length控制线长
lineStyle: { // 属性lineStyle(详见lineStyle)控制线条样式
width: 1
}
},
pointer: {
width: 3,
length: '90%'
},
detail: {
show: false
},
data: [{
value: 87
}]
}
]
};
var bloodOxygenOption = {
tooltip: {
formatter: '{a}<br/>当前:{c}'
},
series: [
//内圈
{
type: 'gauge',
center: ['50%', '60%'], // 默认全局居中
radius: '30%',
min: 0,
max: 10,
startAngle: 270,
endAngle: -89.99999,
splitNumber: 10,
axisLine: { // 仪表盘轴线
lineStyle: { // 属性lineStyle控制线条样式
color: [
[1, '#ff4500']
],
width: 0,
shadowColor: '#fff', //默认透明
shadowBlur: 10
}
},
axisLabel: { // 刻度标签
show: false
},
axisTick: { // 刻度
length: 4, // 属性length控制线长
lineStyle: { // 属性lineStyle控制线条样式
color: 'rgba(176,204,53,.5)'
}
},
splitLine: { // 分隔线
show: false
},
pointer: {
width: 0,
shadowColor: '#fff', //默认透明
shadowBlur: 5
},
detail: {
show: false
}
},
//中圈
{
name: '转速',
type: 'gauge',
center: ['50%', '60%'], // 默认全局居中
radius: '60%',
min: 0,
max: 10,
splitNumber: 10,
axisLine: { // 坐标轴线
lineStyle: { // 属性lineStyle控制线条样式
color: [
[1, '#6E6560']
],
width: 8,
shadowBlur: 10
}
},
axisLabel: { // 刻度
textStyle: { // 属性lineStyle控制线条样式
fontWeight: '',
color: 'rgba(30,144,255,0)',
shadowColor: '#fff', //默认透明
shadowBlur: 10
}
},
axisTick: { // 坐标轴小标记
length: 2, // 属性length控制线长
lineStyle: { // 属性lineStyle控制线条样式
color: 'auto'
/*shadowColor : '#fff', //默认透明
shadowBlur: 10*/
}
},
splitLine: { // 分隔线
length: 0, // 属性length控制线长
lineStyle: { // 属性lineStyle(详见lineStyle)控制线条样式
width: 0,
color: '#fff',
shadowColor: '#fff', //默认透明
shadowBlur: 10
}
},
pointer: {
width: 0,
shadowColor: '#fff', //默认透明
shadowBlur: 5
},
detail: {
show: false
}
},
//外圈室内
{
type: 'gauge',
center: ['50%', '60%'], // 默认全局居中
radius: '100%',
min: 80, // Updated minimum value
max: 100, // Updated maximum value
name: '血氧',
axisLine: { // 坐标轴线
lineStyle: {
color: [
[0.5, '#FF0000'], // Red for 80-90
[1, '#00FF00'] // Green for 90-100
], // 属性lineStyle控制线条样式
width: 1
}
},
itemStyle: {
normal: {
color: '#FF0000'
}
},
axisTick: {
length: 3
},
axisLabel: { // 坐标轴标记
textStyle: { // 属性lineStyle控制线条样式
fontWeight: 'bolder',
fontSize: 10,
fontFamily: 'numfont'
}
},
splitLine: { // 分隔线
length: 5, // 属性length控制线长
lineStyle: { // 属性lineStyle(详见lineStyle)控制线条样式
width: 1
}
},
pointer: {
width: 3,
length: '90%'
},
detail: {
show: false
},
data: [{
value: 87
}]
},
//外圈室外
]
};
var pressureOption = {
tooltip: {
formatter: '{a}<br/>当前:{c}mmHg'
},
series: [
//内圈
{
type: 'gauge',
center: ['50%', '60%'], // 默认全局居中
radius: '30%',
min: 0,
max: 10,
startAngle: 270,
endAngle: -89.99999,
splitNumber: 10,
axisLine: { // 仪表盘轴线
lineStyle: { // 属性lineStyle控制线条样式
color: [
[1, '#ff4500']
],
width: 0,
shadowColor: '#fff', //默认透明
shadowBlur: 10
}
},
axisLabel: { // 刻度标签
show: false
},
axisTick: { // 度
length: 4, // 属性length控制线长
lineStyle: { // 属性lineStyle控制线条样式
color: 'rgba(176,204,53,.5)'
}
},
splitLine: { // 分隔线
show: false
},
pointer: {
width: 0,
shadowColor: '#fff', //默认透明
shadowBlur: 5
},
detail: {
show: false
}
},
//中圈
{
name: '转速',
type: 'gauge',
center: ['50%', '60%'], // 默认全局居中
radius: '60%',
min: 0,
max: 10,
splitNumber: 10,
axisLine: { // 坐标轴线
lineStyle: { // 属性lineStyle控制线条样式
color: [
[1, '#6E6560']
],
width: 8,
shadowBlur: 10
}
},
axisLabel: { // 刻度
textStyle: { // 属性lineStyle控制线条样式
fontWeight: '',
color: 'rgba(30,144,255,0)',
shadowColor: '#fff', //默认透明
shadowBlur: 10
}
},
axisTick: { // 坐标轴小标记
length: 2, // 属性length控制线长
lineStyle: { // 属性lineStyle控制线条样式
color: 'auto'
/*shadowColor : '#fff', //默认透明
shadowBlur: 10*/
}
},
splitLine: { // 分隔线
length: 0, // 属性length控制线长
lineStyle: { // 属性lineStyle(详见lineStyle)控制线条样式
width: 0,
color: '#fff',
shadowColor: '#fff', //默认透明
shadowBlur: 10
}
},
pointer: {
width: 0,
shadowColor: '#fff', //默认透明
shadowBlur: 5
},
detail: {
show: false
}
},
//外圈室内
{
type: 'gauge',
center: ['50%', '60%'], // 默认全局居中
radius: '100%',
min: 0,
max: 150,
name: '高压',
axisLine: { // 坐标轴线
lineStyle: {
color: [
[1, '#C7C5C3']
], // 属性lineStyle控制线条样式
width: 1
}
},
itemStyle: {
normal: {
color: '#FF0000'
}
},
axisTick: {
length: 3
},
axisLabel: { // 坐标轴小标记
textStyle: { // 属性lineStyle控制线条样式
fontWeight: 'bolder',
fontSize: 10,
fontFamily: 'numfont'
}
},
splitLine: { // 分隔线
length: 5, // 属性length控制线长
lineStyle: { // 属性lineStyle(详见lineStyle)控制线条样式
width: 1
}
},
pointer: {
width: 3,
length: '90%'
},
detail: {
show: false
},
data: [{
value: 101
}]
},
//外圈室外
{
type: 'gauge',
center: ['50%', '60%'], // 默认全局居中
radius: '100%',
min: 0,
max: 150,
name: '低压',
axisTick: {
length: 3
},
axisLine: { // 坐标轴线
lineStyle: {
color: [
[1, '#C7C5C3']
], // 属性lineStyle控制线条样式
width: 1
}
},
pointer: {
width: 3,
length: '90%'
},
itemStyle: {
normal: {
color: '#B0CC35'
}
},
axisLabel: {
textStyle: {
fontWeight: 'bolder',
fontSize: 16,
color: 'rgba(30,144,255,0)'
}
},
splitLine: { // 分隔线
length: 5, // 属性length控制线长
lineStyle: { // 属性lineStyle(详见lineStyle)控制线条样式
width: 1
}
},
detail: {
show: false
},
data: [{
value: 88
}],
title: {
show: false
}
}
]
};
var temperatureOption = {
tooltip: {
formatter: '{a}<br/>当前:{c}℃'
},
series: [
//内圈
{
type: 'gauge',
center: ['50%', '60%'], // 默认全局居中
radius: '30%',
min: 0,
max: 10,
startAngle: 270,
endAngle: -89.99999,
splitNumber: 10,
axisLine: { // 仪表盘轴线
lineStyle: { // 属性lineStyle控制线条样式
color: [
[1, '#ff4500']
],
width: 0,
shadowColor: '#fff', //默认透明
shadowBlur: 10
}
},
axisLabel: { // 刻度标签
show: false
},
axisTick: { // 刻度
length: 4, // 属性length控制线长
lineStyle: { // 属性lineStyle控制线条样式
color: 'rgba(176,204,53,.5)'
}
},
splitLine: { // 分隔线
show: false
},
pointer: {
width: 0,
shadowColor: '#fff', //默认透明
shadowBlur: 5
},
detail: {
show: false
}
},
//中圈
{
name: '转速',
type: 'gauge',
center: ['50%', '60%'], // 默认全局居中
radius: '60%',
min: 0,
max: 10,
splitNumber: 10,
axisLine: { // 坐标轴线
lineStyle: { // 属性lineStyle控制线条样式
color: [
[1, '#6E6560']
],
width: 8,
shadowBlur: 10
}
},
axisLabel: { // 刻度
textStyle: { // 属性lineStyle控制线条样式
fontWeight: '',
color: 'rgba(30,144,255,0)',
shadowColor: '#fff', //默认透明
shadowBlur: 10
}
},
axisTick: { // 坐标轴小标记
length: 2, // 属性length控制线长
lineStyle: { // 属性lineStyle控制线条样式
color: 'auto'
/*shadowColor : '#fff', //默认透明
shadowBlur: 10*/
}
},
splitLine: { // 分隔线
length: 0, // 属性length控制线长
lineStyle: { // 属性lineStyle(详见lineStyle)控制线条样式
width: 0,
color: '#fff',
shadowColor: '#fff', //默认透明
shadowBlur: 10
}
},
pointer: {
width: 0,
shadowColor: '#fff', //默认透明
shadowBlur: 5
},
detail: {
show: false
}
},
//外圈室内
{
type: 'gauge',
center: ['50%', '60%'], // 默认全局居中
radius: '100%',
min: 34, // Updated minimum value
max: 41, // Updated maximum value
name: '体温',
axisLine: { // 坐标轴线
lineStyle: {
color: [
[0.1429, '#FF0000'], // Red for 34-35
[0.5, '#00FF00'], // Green for 35-37.5
[1, '#FF0000'] // Red for 37.5-41
], // 属性lineStyle控制线条样式
width: 1
}
},
itemStyle: {
normal: {
color: '#FF0000'
}
},
axisTick: {
length: 3
},
axisLabel: { // 坐标轴小标记
textStyle: { // 属性lineStyle控制线条样式
fontWeight: 'bolder',
fontSize: 10,
fontFamily: 'numfont'
}
},
splitLine: { // 分隔线
length: 5, // 属性length控制线长
lineStyle: { // 属性lineStyle(详见lineStyle)控制线条样式
width: 1
}
},
pointer: {
width: 3,
length: '90%'
},
detail: {
show: false
},
data: [{
value: 36.5
}]
}
]
};
heartRateChart.setOption(heartRateOption);
bloodOxygenChart.setOption(bloodOxygenOption);
pressureChart.setOption(pressureOption);
temperatureChart.setOption(temperatureOption);
// Define the function globally
window.temHum = function(heartRateVal, bloodOxygenVal, pressureHighVal, pressureLowVal, temperatureVal) {
heartRateOption.series[2].data[0].value = heartRateVal;
heartRateChart.setOption(heartRateOption);
$('.heartRate-val').find('.profile-button').text(heartRateVal);
bloodOxygenOption.series[2].data[0].value = bloodOxygenVal;
bloodOxygenChart.setOption(bloodOxygenOption);
$('.bloodOxygen-val').find('.profile-button').text(bloodOxygenVal);
pressureOption.series[2].data[0].value = pressureHighVal;
pressureOption.series[3].data[0].value = pressureLowVal;
pressureChart.setOption(pressureOption);
console.log("temHum::pressureHighVal:", pressureHighVal);
$('.pressure-val').find('.profile-button').text(`${pressureHighVal}/${pressureLowVal}`);
temperatureOption.series[2].data[0].value = temperatureVal;
temperatureChart.setOption(temperatureOption);
$('.temperature-val').find('.profile-button').text(temperatureVal+ '℃');
};
//风向图
var windOption = {
tooltip: {},
radar: {
indicator: [{
name: '心率',
max: 12
},
{
name: '血氧',
max: 12
},
{
name: '体温',
max: 12
},
{
name: '压力',
max: 12
},
{
name: '睡眠',
max: 12
},
{
name: '步数',
max: 12
},
{
name: '血压',
max: 12
}
],
name: {
textStyle: {
color: 'rgba(176,204,53,1)'
}
},
axisLine: {
lineStyle: {
color: 'rgba(255, 255, 255, 0.4)'
}
},
splitLine: {
lineStyle: {
color: 'rgba(255, 255, 255, 0.4)'
}
},
splitArea: {
areaStyle: {
color: 'rgba(255,255,255,0)'
}
}
},
series: [{
type: 'radar',
data: [{
value: [2.8, 5.3, 7.1, 5.4, 10.6, 8.5, 10.0],
name: '2024'
}],
areaStyle: {
normal: {
color: 'rgba(176,204,53,.5)'
}
},
lineStyle: {
normal: {
color: 'rgba(176,204,53,.7)'
}
},
symbol: 'circle',
symbolSize: 6,
itemStyle: {
normal: {
color: '#A9C33B'
}
}
}]
};
var windChart = echarts.init(document.getElementById('windChart'));
windChart.setOption(windOption);
//风速与阵风数据
var speed = {
wind: [86, 42],
gust: [2.8, 4.3]
};
function getData() {
$('#nowWind').text(speed.wind[0]);
$('#highWind').text(speed.wind[1]);
var windSpeed = (50 - speed.wind[0]) * 10;
$('.windSpeed .windFan').css('animation-duration', windSpeed + 'ms');
$('#nowGust').text(speed.gust[0]);
$('#highGust').text(speed.gust[1]);
var gustSpeed = (50 - speed.gust[0]) * 10;
$('.gust .windFan').css('animation-duration', gustSpeed + 'ms');
}
getData();
};
initialize();
</script>
<style>
.device-status {
display: flex;
justify-content: space-around;
padding: 20px;
background-color: #333;
color: #fff;
}
.status-item {
text-align: center;
transition: transform 0.3s;
}
.status-item:hover {
transform: scale(1.1);
}
.status-title {
margin-bottom: 10px;
font-size: 16px;
}
.status-icon {
font-size: 24px;
transition: color 0.3s, transform 0.3s;
}
.icon {
transition: color 0.3s, transform 0.3s;
}
.icon.active {
color: green;
animation: pulse 1s infinite;
}
.icon.inactive {
color: red;
}
@keyframes pulse {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.2);
}
}
</style>
<script type="text/javascript">
//设置渠道状态
function qdzt(){
//breathe-zc 绿灯;breathe-yc 红灯
$("#dx").removeClass("breathe-yc");
$("#dx").addClass("breathe-zc");
$("#cz").removeClass("breathe-zc");
$("#cz").addClass("breathe-yc");
$("#gt").removeClass("breathe-yc");
$("#gt").addClass("breathe-zc");
$("#dlbxsp").removeClass("breathe-yc");
$("#dlbxsp").addClass("breathe-zc");
}
</script>
<script>
document.addEventListener('DOMContentLoaded', function() {
async function fetchData() {
try {
// Fetch data from the API
const response = await fetch(`./get_personal_info?deviceSn={{deviceSn}}`);
//console.log("get_personal_info response:", response);
// Check content type
const contentType = response.headers.get("content-type");
if (contentType && contentType.includes("application/json")) {
const personalData = await response.json();
console.log("get_personal_info response:", personalData);
// Ensure data structure is valid
if (personalData && personalData.success) {
const healthData = personalData.data.health_data.healthData[0];
console.log("DOMContentLoaded::healthData:", healthData);
if (healthData) {
const heartRate = healthData.heartRate;
const bloodOxygen = healthData.bloodOxygen;
const pressureHigh = healthData.pressureHigh;
const pressureLow = healthData.pressureLow;
const temperature = healthData.temperature;
// Initialize page components with the fetched data
temHum(heartRate, bloodOxygen, pressureHigh, pressureLow, temperature);
//console.log("DOMContentLoaded::data:", personalData.data);
} else {
console.error('Health data is undefined:', personalData.data);
}
const deviceInfo = personalData.data.device_info.devices[0];
console.log("DOMContentLoaded1::device_info:", deviceInfo);
// Device info handling
if (deviceInfo) {
const chargingStatus = deviceInfo.charging_status || 'UNKNOWN';
const wearableStatus = deviceInfo.wearable_status || 'UNKNOWN';
const onlineStatus = deviceInfo.status || 'UNKNOWN';
// Update charging status
if (chargingStatus === 'NOT_CHARGING') {
$("#chargeStatus").removeClass("breathe-zc").addClass("breathe-yc");
} else {
$("#chargeStatus").removeClass("breathe-yc").addClass("breathe-zc");
}
// Update wearable status
if (wearableStatus === 'NOT_WORN') {
$("#wearStatus").removeClass("breathe-zc").addClass("breathe-yc");
} else {
$("#wearStatus").removeClass("breathe-yc").addClass("breathe-zc");
}
// Update online status
if (onlineStatus === 'INACTIVE') {
$("#onlineStatus").removeClass("breathe-zc").addClass("breathe-yc");
} else {
$("#onlineStatus").removeClass("breathe-yc").addClass("breathe-zc");
}
}
const alerts = personalData.data.alert_info.alerts;
console.log("DOMContentLoaded::alertInfo:", alerts);
// Handle alert_info
if (alerts.length > 0) {
const alertTableBody = document.getElementById('alert-table-body');
alertTableBody.innerHTML = '';
//const alerts = alertInfo.alerts;
//console.log("DOMContentLoaded::alerts:", alerts);
alerts.slice(0, 3).forEach(alert => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${alert.alert_type || '未知'}</td>
<td>
<span class="level ${alert.severity_level || 'unknown'}">
${mapSeverityLevel(alert.severity_level) || '未知'}
</span>
</td>
<td>${alert.alert_timestamp || '未知时间'}</td>
<td>
<button class="profile-button"><a href="./dealAlert?alertId=${alert.id}">一键处理</a></button>
</td>
`;
alertTableBody.appendChild(row);
});
// Update alert status indicator
if (alerts.length > 0) {
$("#alertStatus").removeClass("breathe-zc").addClass("breathe-yc");
} else {
$("#alertStatus").removeClass("breathe-yc").addClass("breathe-zc");
}
}
const messageInfo = personalData.data.message_info;
const messages = messageInfo.messages;
// Handle message_info
console.log("DOMContentLoaded::messageInfo:", messages);
const messageTableBody = document.getElementById('message-table-body');
messageTableBody.innerHTML = '';
messages.slice(0, 3).forEach(message => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${message.message || '未知消息'}</td>
<td><span class="status ${message.message_type || 'unknown'}">${mapMessageType(message.message_type) || '未知类型'}</span></td>
<td class="${message.message_status === 'responded' ? 'responded' : 'pending'}">${mapMessageStatus(message.message_status) || '未处理'}</td>
`;
messageTableBody.appendChild(row);
});
} else {
console.error('Failed to fetch personal info:', data.error || 'Unknown error');
}
} else {
console.error('Response is not JSON:', await response.text());
}
} catch (error) {
console.error('Error fetching personal info:', error.message || error);
//alert('无法加载个人信息,请稍后重试。');
}
}
// Fetch data initially and then every 5 seconds
fetchData();
setInterval(fetchData, 5000);
});
</script>
<script>
const socket = io.connect(); // Adjust the URL as needed
console.log("socket", socket);
// Log when the connection is established
socket.on('connect', function() {
console.log('Connected to socket server');
});
// Log any connection errors
socket.on('connect_error', function(error) {
console.error('Connection error:', error);
});
// Listen for the personal_info_update event
socket.on('personal_info_update', function(data) {
console.log("personal_info_update:", data.data.health_data.heartRate);
temHum(data.data.health_data.heartRate, data.data.health_data.bloodOxygen, data.data.health_data.pressureHigh, data.data.health_data.pressureLow, data.data.health_data.temperature);
//console.log(data.data.device_info);
// Update charging status
if (data.data.device_info.charging_status === 'NOT_CHARGING') {
$("#chargeStatus").removeClass("breathe-zc").addClass("breathe-yc");
} else {
$("#chargeStatus").removeClass("breathe-yc").addClass("breathe-zc");
}
// Update wearable status
if (data.data.device_info.wearable_status === 'NOT_WORN') {
$("#wearStatus").removeClass("breathe-zc").addClass("breathe-yc");
} else {
$("#wearStatus").removeClass("breathe-yc").addClass("breathe-zc");
}
// Update online status
if (data.data.device_info.status === 'INACTIVE') {
$("#onlineStatus").removeClass("breathe-zc").addClass("breathe-yc");
} else {
$("#onlineStatus").removeClass("breathe-yc").addClass("breathe-zc");
}
// Update alert status
if (Object.keys(data.data.alert_info).length > 0) {
$("#alertStatus").removeClass("breathe-zc").addClass("breathe-yc");
} else {
$("#alertStatus").removeClass("breathe-yc").addClass("breathe-zc");
}
// Handle alert_info
if (data.data.alert_info && typeof data.data.alert_info === 'object') {
const alertTableBody = document.getElementById('alert-table-body');
alertTableBody.innerHTML = '';
// 将对象的值转换为数组并解析 JSON 字符串
const alerts = Object.values(data.data.alert_info).map(alertStr => JSON.parse(alertStr));
alerts.slice(0, 3).forEach(alert => {
//console.log("alert:", alert.severityLevel);
const row = document.createElement('tr');
row.innerHTML = `
<td>${alert.alertType || '未知'}</td>
<td>
<span class="level ${alert.severityLevel || 'unknown'}">
${mapSeverityLevel(alert.severityLevel) || '未知'}
</span>
</td>
<td>${alert.timestamp || '未知时间'}</td>
<td>
<button class="profile-button"><a href="./dealAlert?alertId=${alert.id}">一键处理</a></button>
</td>
`;
alertTableBody.appendChild(row);
});
// Update alert status indicator
if (alerts.length > 0) {
$("#alertStatus").removeClass("breathe-zc").addClass("breathe-yc");
} else {
$("#alertStatus").removeClass("breathe-yc").addClass("breathe-zc");
}
}
//console.log("data.message_info:", data.data.message_info);
if (data.data.message_info && typeof data.data.message_info === 'object') {
const messages = Object.values(data.data.message_info).map(messageStr => JSON.parse(messageStr));
// Handle message_info
const messageTableBody = document.getElementById('message-table-body');
messageTableBody.innerHTML = '';
// Iterate over each message in message_info
messages.slice(0, 3).forEach(message => {
console.log("message:", message.message_type);
const row = document.createElement('tr');
row.innerHTML = `
<td>${message.message || '未知消息'}</td>
<td><span class="status ${message.message_type || 'unknown'}">${mapMessageType(message.message_type) || '未知类型'}</span></td>
<td class="${message.message_status === '1' ? 'pending' : 'responded'}">${mapMessageStatus(message.message_status)}</td>
`;
messageTableBody.appendChild(row);
});
}
// Update the DOM with the new data
//const personalInfoDiv = document.getElementById('personal-info');
//personalInfoDiv.innerHTML = JSON.stringify(data.data, null, 2); // Example: display JSON data
});
</script>
<script>
function mapSeverityLevel(severityLevel) {
switch (severityLevel) {
case 'critical':
return '一级';
case 'high':
return '二级';
case 'medium':
return '三级';
default:
return '其他';
}
}
function mapMessageType(messageType) {
switch (messageType) {
case 'announcement':
return '公告';
case 'warning':
return '警告';
case 'notification':
return '通知';
case 'task':
return '任务管理';
case 'job':
return '作业指引';
default:
return '未知';
}
}
function mapMessageStatus(status) {
const statusMap = {
'1': '未响应',
'0': '已响应',
};
return statusMap[status] || '未响应';
}
</script>
</body>
</html>