MassageRobot_Dobot/UI_next/templates/control_panel_v2.html
2025-05-27 15:46:31 +08:00

3024 lines
103 KiB
HTML
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<title>Control Panel</title>
{% if mode == 'handheld' %}
<style>
/* 初始隐藏状态 */
.status-container .status-card:nth-child(1),
.status-container .status-card:nth-child(2),
#strength-card {
display: none;
}
</style>
{% endif %}
<script src="{{ url_for('static', filename='js/socketio/socket.io.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/license_module.js') }}"></script>
<link rel="stylesheet" href="/static/css/swiper-bundle.min.css" />
<script src="{{ url_for('static', filename='js/i18n/jquery-3.7.1.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/i18n/jquery.i18n.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/i18n/setting-lang.js') }}"></script>
<style>
/* 禁用用户选择 */
* {
-webkit-user-select: none;
/* Chrome, Opera, Safari */
-moz-user-select: none;
/* Firefox */
-ms-user-select: none;
/* Internet Explorer/Edge */
user-select: none;
/* Non-prefixed version, currently supported by Chrome, Opera and Firefox */
-webkit-tap-highlight-color: transparent;
/* 禁用触控点击的蓝色叠加层 */
}
body,
html {
height: 100%;
margin: 0;
font-family: Arial, sans-serif;
background-color: #ffffff00;
}
.controls-container {
height: 100%;
width: 100%;
/* add-code */
padding: 20px;
box-sizing: border-box;
position: relative;
}
.scroll-view {
position: fixed;
top: 50px;
width: calc(100% - 40px);
height: calc(100% - 70px);
overflow: auto;
}
/* 隐藏滚动条 */
.scroll-view::-webkit-scrollbar {
display: none;
}
.scroll-view {
-ms-overflow-style: none;
/* IE and Edge */
scrollbar-width: none;
/* Firefox */
}
.status-header-title {
height: 27px;
/* font-style: italic; */
font-size: 16px;
/* margin: 5px 0; */
margin: 25px 0 20px;
font-weight: 600;
color: #666;
}
.status-container {
box-sizing: border-box;
/* grid-auto-rows: auto; 原注释代码 */
/* justify-content: space-between; */
/* display: flex;
flex-wrap: wrap;
align-content: start; */
/* gap: 12px; */
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 10px 14px;
}
.status-card {
background-color: rgba(255, 255, 255, 0.507);
border-radius: 15px;
font-size: 16px;
text-align: center;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
overflow: hidden;
position: relative;
transition: all 0.15s ease-in-out;
/* add-code */
/* width: calc(25% - 12px); */
width: 100%;
/* height: 170px; */
height: 150px;
max-height: 230px;
display: flex;
flex-direction: column;
}
/*
.status-card:not(:nth-child(4n)) {
margin-right: 10px;
} */
.massage-head-card img {
/* max-width: 100%; */
position: absolute;
height: 60%;
width: 60%;
object-fit: cover; /* 使图片适应框架大小 */
z-index: 2;
transform: rotateZ(-35deg);
/* add-code */
margin: 16px 20% 0;
aspect-ratio: 1/1;
opacity: 0.7;
bottom: 20px;
}
.status-title {
padding: 6px 10px;
font-size: 16px;
font-weight: bold;
letter-spacing: 1px;
color: rgb(247, 0, 255); /* 默认颜色 */
color: rgba(252, 74, 252, 0.7); /* 使用 RGBA 透明色 */
text-shadow: 1px 3px 6px #fff, /* 模拟内阴影的颜色 */ 0 0 0 #000,
/* 透明阴影,用来确保支持老浏览器 */ 2px 3px 6px #fff; /* 模拟内阴影的颜色 */
z-index: 1;
opacity: 0.45;
text-align: left;
text-wrap: nowrap;
overflow: hidden;
/* overflow-x: auto; */
min-height: 25px;
line-height: 25px;
display: flex;
align-items: center;
}
.status-title::-webkit-scrollbar {
display: none;
}
.status-title-span {
max-width: 84px;
overflow-x: auto;
}
.common-range {
font-size: 12px;
}
.status-content {
width: 100%;
/* font-size: 16px; */
font-weight: 900;
letter-spacing: 5px;
color: rgb(247, 0, 255); /* 默认颜色 */
color: rgba(252, 74, 252, 0.7);
/* 使用 RGBA 透明色 */
text-shadow: 1px 3px 6px #fff, /* 模拟内阴影的颜色 */ 0 0 0 #000,
/* 透明阴影,用来确保支持老浏览器 */ 2px 3px 6px #fff; /* 模拟内阴影的颜色 */
z-index: 1;
opacity: 0.4;
text-align: center;
white-space: pre-wrap; /* 保持空白符和换行符 */
border-radius: 15px;
justify-content: center;
align-items: center;
display: flex;
/* add-code */
flex: 1;
height: calc(100% - 25px);
}
/* 隐藏滚动条 */
#status-program::-webkit-scrollbar {
display: none;
}
#status-program {
-ms-overflow-style: none;
/* IE and Edge */
scrollbar-width: none;
/* Firefox */
}
/* #massage-card:active {
background-color: rgba(255, 177, 238, 0.507);
} */
#massage-head {
box-sizing: border-box;
width: 80%;
height: calc(100% - 40px);
display: flex;
align-items: center;
justify-content: center;
position: absolute;
bottom: 42%;
left: 50%;
transform: translate(-50%, 50%);
letter-spacing: 0px;
font-size: 5.5vw;
line-height: 6vw;
opacity: 0.6;
overflow-y: auto;
align-self: center;
}
.massage-popup {
position: fixed;
background-color: rgba(255, 255, 255, 0.65);
backdrop-filter: blur(5px);
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
border-radius: 10px;
display: none;
flex-direction: column;
padding: 15px;
box-sizing: border-box;
gap: 10px; /* 按钮之间的间距 */
z-index: 9999; /* 确保在最前面 */
overflow-y: auto;
transition: all 0.15s ease-in-out;
}
/* 隐藏滚动条 */
.massage-popup::-webkit-scrollbar {
width: 0px;
height: 0px;
}
/* 隐藏IE和Edge的滚动条 */
.massage-popup {
-ms-overflow-style: none; /* IE和Edge */
scrollbar-width: none; /* Firefox */
}
.massage-head-button {
background-color: #bb29ff13;
border-radius: 10px; /* 圆角 */
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* 阴影 */
padding: 15px;
text-align: center;
font-size: 16px;
color: #333; /* 字体颜色 */
cursor: pointer;
transition: background-color 0.3s ease, box-shadow 0.3s ease;
}
.massage-head-button:hover {
background-color: rgba(255, 177, 238, 0.507);
box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15); /* 悬停时的阴影 */
}
#progress {
font-size: 55px;
margin: 2.5px;
margin-top: -10px;
background-color: rgb(247, 0, 255);
background-image: linear-gradient(
to top,
rgba(4, 0, 255, 0.7) 60%,
/* 深紫色填充到60% */ rgba(247, 0, 255, 0) 60% /* 剩余40%的颜色 */
);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: none;
opacity: 0.4;
/* opacity: 0.25; */
}
#progress::before {
content: attr(data-text);
position: absolute;
z-index: -1;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 1px 3px 6px rgba(255, 255, 255, 0.7),
/* 模拟内阴影的颜色 */ 0 0 0 #000,
/* 透明阴影,用来确保支持老浏览器 */ 2px 3px 6px
rgba(255, 255, 255, 0.7); /* 模拟内阴影的颜色 */
opacity: 0.35;
}
#force {
bottom: 0;
letter-spacing: normal;
display: flex;
align-items: baseline; /* 让数字和字母的底部对齐 */
margin-top: -18px;
}
.function-container {
/* add-code */
/* height: 170px; */
width: calc(100% - 40px);
/* width: 30px; */
position: fixed;
bottom: 20px;
/* bottom: 10px; */
transition: all 0.1s;
display: flex;
left: 20px;
border-radius: 15px;
overflow: hidden;
}
.common-button {
bottom: 0;
/* width: 90%; */
/* add-code */
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
position: absolute;
z-index: 9999;
box-sizing: border-box;
padding: 10px;
}
.common-button button {
flex: 1;
height: 46px;
background-color: #bb29ff13;
color: rgba(255, 255, 255, 0.65);
border: none;
border-radius: 10px; /* 圆角矩形 */
display: flex;
align-items: center;
justify-content: center;
font-size: 32px;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1);
}
.common-button button:first-child {
margin-right: 10px;
}
.common-button button:active {
background-color: rgba(255, 177, 238, 0.507);
}
.common-add,
.common-down {
width: 25px;
height: 25px;
background: linear-gradient(
to right bottom,
rgb(212, 96, 241),
rgba(145, 66, 197, 0.5)
);
mask-size: cover;
background-size: cover;
-webkit-mask-size: cover;
}
.common-add {
mask-image: url("static/images/massage_control/加号.svg");
-webkit-mask-image: url("static/images/massage_control/加号.svg");
}
.common-down {
mask-image: url("static/images/massage_control/减号.svg");
-webkit-mask-image: url("static/images/massage_control/减号.svg");
}
#temperature {
bottom: 0;
display: flex;
align-items: baseline; /* Align the bottom of numbers and unit */
margin-top: -20px;
}
.temperature-value {
letter-spacing: normal;
}
.temperature-unit {
letter-spacing: -4px;
}
.common-value,
.common-unit {
letter-spacing: normal;
text-align: center;
}
.common-value {
font-size: 6.5vw;
}
.common-unit {
font-size: 5vw;
}
.common-no-unit {
bottom: 0;
letter-spacing: normal;
display: flex;
align-items: baseline;
margin-top: -18px;
}
.common-no-unit-value {
font-size: 6.5vw; /* Adjust the size here */
letter-spacing: normal;
}
#direction {
opacity: 0.9;
margin-top: -16px;
}
.direction-container {
display: flex;
flex-direction: column;
gap: 14px;
align-items: center;
justify-content: center;
}
.direction-value {
opacity: 0.4;
letter-spacing: normal;
font-size: 12px;
}
.common-switch {
position: relative;
height: 40px;
width: 80px;
background-color: #f5f5f5;
border-radius: 20px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.25);
z-index: 3;
display: flex;
align-items: center;
justify-content: center;
}
.common-slide-toggle {
position: absolute;
height: 41px;
width: 41px;
background: linear-gradient(
to right bottom,
rgb(212, 96, 241, 1),
rgba(145, 66, 197, 1)
);
border-radius: 50%;
transition: left 0.2s ease-in-out;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.25);
box-shadow: -4px 2px 8px rgba(0, 0, 0, 0.25);
-webkit-transition: left 0.2s ease-in-out;
-moz-transition: left 0.2s ease-in-out;
-ms-transition: left 0.2s ease-in-out;
-o-transition: left 0.2s ease-in-out;
}
.joystick {
width: 150px;
height: 150px;
flex-direction: column;
align-items: center;
justify-content: center;
}
.joystick-text {
font-weight: bold;
opacity: 0.35;
font-size: 15px;
}
#joystick-frame {
width: 165px;
height: 175px; /* 调整iframe高度为页面底部的50% */
background-color: transparent; /* 设置背景透明 */
border: none; /* 去除边框 */
overflow: hidden;
/* background-color: #4CAF50; */
}
.flag-button {
width: 40px;
min-width: 40px;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
background-color: #bb29ff13;
z-index: 99;
}
.flag-button #flag-img {
width: 20px;
height: 20px;
}
.button-container {
display: flex;
width: 100%;
box-sizing: border-box;
overflow: hidden;
border-radius: 15px;
}
.control-button {
/* flex: 8; */
display: flex;
/* flex-direction: column; */
align-items: center;
justify-content: center;
box-sizing: border-box;
flex: 1;
width: 100%;
/* width: calc(100% - 40px); */
overflow: hidden !important;
border-radius: 15px;
gap: 20px;
}
.control-button .pause-btn-box {
position: relative;
overflow: hidden !important;
flex: 3.5;
border-radius: 10px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
-ms-border-radius: 10px;
-o-border-radius: 10px;
}
.pause {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
}
.pause-icon {
width: 30px;
height: 30px;
}
.re-start-icon {
width: 30px;
height: 30px;
display: none;
}
.control-button button {
height: 60px;
/* height: 55px; */
background-color: rgba(255, 255, 255, 0.507);
color: rgba(255, 255, 255, 0.65);
border: none;
border-radius: 10px; /* 圆角矩形 */
flex: 1;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1);
position: relative;
overflow: hidden !important;
}
/* .control-button button:not(:first-child) {
margin-left: 10px;
} */
/* .control-button button:last-child::after {
content: "";
position: absolute;
left: 0;
right: 0;
width: 100%;
height: 100%;
background: linear-gradient(
to right,
rgb(9, 198, 245),
rgb(44, 243, 120)
);
} */
.progress-bar {
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 0;
/* background: linear-gradient(
to right,
rgb(9, 198, 245),
rgb(44, 243, 120)
); */
animation: rise 12s linear forwards;
background: linear-gradient(
90deg,
rgba(214, 111, 240, 0.8),
rgba(145, 66, 197, 0.8)
);
overflow: hidden;
/* animation: rise 12s linear forwards; */
}
/* @keyframes rise {
0% {
width: 50px;
}
100% {
height: 100%;
filter: hue-rotate(360deg);
}
} */
.progress-bar::after {
content: "";
position: absolute;
top: 50%;
margin-top: -40px;
right: -74px;
width: 80px;
height: 80px;
border-radius: 45%;
background-color: rgba(255, 255, 255, 0.507);
animation: move 8s linear infinite;
}
@keyframes move {
100% {
transform: rotate(360deg);
}
}
.progress-bar::before {
content: "";
position: absolute;
top: 50%;
margin-top: -35px;
right: -62px;
width: 70px;
height: 70px;
border-radius: 38%;
background-color: rgba(255, 255, 255, 0.507);
animation: move2 5s linear infinite;
}
@keyframes move2 {
100% {
transform: rotate(360deg);
}
}
.control-button button:active {
background-color: rgba(255, 177, 238, 0.507);
}
.start div {
background: linear-gradient(45deg, #ff7e5f, #ffa764);
/* background: linear-gradient(45deg, #ff7e5f, #ffa764); */
}
.stop {
flex: 1;
align-items: center;
justify-content: center;
}
.stop div {
background: linear-gradient(45deg, #ff9fc4, #f83b64);
position: relative;
z-index: 1;
text-align: right;
}
.progress-num {
background: linear-gradient(45deg, #ff9fc4, #f83b64);
margin-left: 10px;
font-size: 15px !important;
text-align: left;
font-weight: bolder;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
/* position: relative;
z-index: 1; */
color: transparent; /* 设置文字颜色为透明,让背景色能透过文字 */
}
.start div,
.stop div {
font-size: 18px;
/* max-height: 55px; */
max-height: 60px;
font-weight: bolder;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
/* word-break: break-word; */
text-wrap: nowrap;
text-align: center;
overflow: hidden;
overflow-x: auto;
}
.popup {
display: block;
position: fixed;
top: -50px;
left: 50%;
transform: translateX(-50%);
background-color: #ffcccc;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1);
padding: 10px 14px;
color: #ff0000ab;
border-radius: 17.5px;
z-index: 1000;
font-size: 14px;
align-items: center;
justify-content: center;
text-align: center;
opacity: 0;
transition: all 0.15s ease-in-out; /* 添加滑动动画 */
}
.popup.show {
display: flex;
opacity: 0.8;
top: calc(2.5% + 40px); /* 显示时滑动到顶部的正常位置 */
}
.popup.hide {
opacity: 0;
top: -50px; /* 隐藏时滑回到视图上方 */
}
.program-swiper,
.body-part-swiper {
display: flex;
align-items: center;
justify-content: center;
height: calc(100% - 25px);
margin-top: -10px;
width: 100%;
position: absolute;
}
.swiper-container {
width: 100%;
height: 100%;
}
.swiper-slide {
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
position: relative;
/* transform: 0.5s; */
}
.swiper-slide div {
border-radius: 10px;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
letter-spacing: 0px;
box-shadow: 2px 4px 6px rgba(0, 0, 0, 0.4);
font-size: 12px;
}
.swiper-slide-active {
z-index: 6;
}
.swiper-slide-active div {
position: absolute;
width: 76%;
transform: width 0.5s;
font-size: 16px;
padding: 14px 8px;
opacity: 0.9;
background: linear-gradient(
to right bottom,
rgb(212, 96, 241, 0.8),
rgba(145, 66, 197, 0.8)
);
text-shadow: none;
color: white;
min-height: 60px;
font-size: 12px;
}
.body-swiper {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.body-swiper-icon {
margin-bottom: 6px;
width: 24px;
height: 24px;
}
.swiper-slide-next div,
.swiper-slide-prev div {
min-width: 40px;
position: absolute;
transform: width 0.5s;
font-size: 10px;
opacity: 0.9;
background-color: rgba(255, 255, 255, 0.3);
background-color: rgb(220, 246, 251, 0.5);
padding: 8px 6px;
color: #333;
background-color: rgba(249, 244, 252, 0.5);
}
.swiper-slide-next div {
left: -20%;
}
.swiper-slide-prev div {
right: -20%;
}
.swiper-slide-active {
z-index: 6;
}
.swiper-slide-next,
.swiper-slide-prev {
z-index: 5;
}
.swiper-button-next,
.swiper-button-prev {
display: none;
}
.swiper-button-next svg,
.swiper-button-prev svg {
display: none;
}
.swiper-button-next:after,
.swiper-button-prev:after {
display: none;
}
/* 弹窗的背景遮罩 */
.popup-modal {
display: none; /* 默认隐藏 */
position: fixed;
z-index: 1000; /* 确保弹窗在最顶层 */
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5); /* 背景透明 */
justify-content: center;
align-items: center;
}
/* 弹窗的内容 */
.popup-content {
background-color: rgba(255, 255, 255, 0.7); /* 背景透明度 */
backdrop-filter: blur(5px); /* 背景模糊效果 */
padding: 20px;
border-radius: 15px;
text-align: center;
width: 300px;
box-shadow: 0px 0px 24px rgba(255, 255, 255, 0.65); /* 与其他元素一致的阴影效果 */
}
/* 按钮样式 */
#popup-buttons button {
margin: 5px;
padding: 10px 25px;
border: none;
border-radius: 10px;
background: linear-gradient(
to right bottom,
rgb(212, 96, 241),
rgba(145, 66, 197, 0.5)
); /* 紫色渐变 */
color: white;
font-size: 16px;
cursor: pointer;
transition: background 0.3s ease;
}
#popup-buttons button:active {
background: linear-gradient(
to right bottom,
rgba(145, 66, 197, 1),
rgb(212, 96, 241)
); /* 悬停时加深渐变 */
}
</style>
</head>
<body>
<div class="controls-container">
<div class="scroll-view">
<div
class="status-header-title"
i18n="control.massage.header_title"
resize-font="true"
changeLineHeight="true"
smallSize="40"
checkHeight="true"
></div>
<div class="status-container">
<div class="status-card" {% if mode == 'handheld' %}style="display: none"{% endif %}>
<div class="status-title" i18n="control.massage.title"></div>
<div id="status-program">
<div id="program" class="program-swiper">
<div class="swiper-wrapper">
<div class="selectable swiper-slide">
<div i18n="control.massage.program"></div>
<!--基础放松-->
</div>
<div class="selectable swiper-slide">
<div i18n="control.massage.program2"></div>
<!--深入舒缓-->
</div>
<div class="selectable swiper-slide">
<div i18n="control.massage.program3"></div>
<!--深层修复-->
</div>
<div class="selectable swiper-slide">
<div i18n="control.massage.program4"></div>
</div>
<div class="selectable swiper-slide">
<div i18n="control.massage.program5"></div>
</div>
<div class="selectable swiper-slide">
<div i18n="control.massage.program6"></div>
</div>
</div>
<div class="program-prev"></div>
<div class="program-next"></div>
</div>
</div>
<!-- <img src="{{ url_for('static', filename='images/0.png') }}" alt=""> -->
</div>
<div class="status-card" {% if mode == 'handheld' %}style="display: none"{% endif %}>
<div
class="status-title"
i18n="control.massage.title2"
resize-font="true"
changeLineHeight="true"
smallSize="40"
checkHeight="true"
></div>
<div id="status-body-part">
<div id="body-part" class="body-part-swiper">
<div class="swiper-wrapper" id="body-part-wrapper"></div>
<div class="body-part-prev"></div>
<div class="body-part-next"></div>
</div>
</div>
</div>
<div class="status-card massage-head-card" id="massage-card">
<div
class="status-title"
i18n="control.massage.title3"
resize-font="true"
changeLineHeight="true"
smallSize="40"
checkHeight="true"
></div>
<div
class="status-content"
id="massage-head"
changeLineHeight="true"
smallSize="40"
checkHeight="true"
></div>
<img
src="{{ url_for('static', filename='images/massage_control/loading.gif') }}"
alt=""
/>
</div>
</div>
<div
class="status-header-title"
i18n="control.massage.header_title"
resize-font="true"
changeLineHeight="true"
smallSize="40"
checkHeight="true"
></div>
<!-- 力度 -->
<div class="status-container">
<div class="status-card" id="strength-card" {% if mode == 'handheld' %}style="display: none"{% endif %}>
<div class="status-title">
<span
i18n="control.massage.title4"
resize-font="true"
changeLineHeight="true"
smallSize="30"
checkHeight="true"
class="status-title-span"
></span>
<span class="common-range" id="force-range"></span>
</div>
<div class="status-content" id="force">
<span class="force-value common-value">20</span>
<span class="force-unit common-unit">N</span>
</div>
<div class="force-button common-button">
<button class="force-down-btn">
<div class="force-down common-down"></div>
</button>
<button class="force-add-btn">
<div class="force-add common-add"></div>
</button>
</div>
</div>
<!-- 温度 -->
<div class="status-card" id="temperature-card">
<div class="status-title">
<span
i18n="control.massage.title5"
resize-font="true"
changeLineHeight="true"
smallSize="30"
checkHeight="true"
class="status-title-span"
></span>
<span class="common-range" id="temperature-range">[0~5]</span>
</div>
<div class="status-content" id="temperature">
<span class="temperature-value common-value">1</span>
<!-- <span class="temperature-unit common-unit">°C</span> -->
</div>
<div class="temperature-button common-button">
<button class="temperature-down-btn">
<div class="temperature-down common-down"></div>
</button>
<button class="temperature-add-btn">
<div class="temperature-add common-add"></div>
</button>
</div>
</div>
<!-- 电流档位 -->
<div class="status-card" id="current-card">
<div class="status-title">
<span
i18n="control.massage.title6"
resize-font="true"
changeLineHeight="true"
smallSize="30"
checkHeight="true"
class="status-title-span"
></span>
<span class="common-range" id="gear-range">[0~5]</span>
</div>
<div class="status-content common-no-unit" id="gear">
<span class="gear-value common-no-unit-value">1</span>
</div>
<div class="gear-button common-button">
<button class="gear-down-btn">
<div class="gear-down common-down"></div>
</button>
<button class="gear-add-btn">
<div class="gear-add common-add"></div>
</button>
</div>
</div>
<!-- 频率 -->
<div class="status-card" id="shake-card">
<div class="status-title">
<span
i18n="control.massage.title7"
resize-font="true"
changeLineHeight="true"
smallSize="30"
checkHeight="true"
class="status-title-span"
></span>
<span class="common-range" id="shake-range">[0~5]</span>
</div>
<div class="status-content common-no-unit" id="shake">
<span class="shake-value common-no-unit-value">1</span>
</div>
<div class="shake-button common-button">
<button class="shake-down-btn">
<div class="shake-down common-down"></div>
</button>
<button class="shake-add-btn">
<div class="shake-add common-add"></div>
</button>
</div>
</div>
<!-- 频率 -->
<div class="status-card" id="frequency-card" style="display: none">
<div class="status-title">
<span
i18n="control.massage.title7"
resize-font="true"
changeLineHeight="true"
smallSize="30"
checkHeight="true"
class="status-title-span"
></span>
<span class="common-range" id="frequency-range">[1~16]</span>
</div>
<div class="status-content common-no-unit" id="frequency">
<span class="frequency-value common-no-unit-value">1</span>
</div>
<div class="frequency-button common-button">
<button class="frequency-down-btn">
<div class="frequency-down common-down"></div>
</button>
<button class="frequency-add-btn">
<div class="frequency-add common-add"></div>
</button>
</div>
</div>
<!-- 冲击力 -->
<div class="status-card" id="press-card" style="display: none">
<div class="status-title">
<span
i18n="control.massage.title8"
resize-font="true"
changeLineHeight="true"
smallSize="30"
checkHeight="true"
class="status-title-span"
></span>
<span id="press-range" class="common-range">[1~27]</span>
</div>
<div class="status-content common-no-unit" id="press">
<span class="press-value common-no-unit-value">1</span>
</div>
<div class="press-button common-button">
<button class="press-down-btn">
<div class="press-down common-down"></div>
</button>
<button class="press-add-btn">
<div class="press-add common-add"></div>
</button>
</div>
</div>
<!-- 速度 -->
<div class="status-card" id="speed-card" style="display: none">
<div class="status-title">
<span
i18n="control.massage.title9"
resize-font="true"
changeLineHeight="true"
smallSize="30"
checkHeight="true"
class="status-title-span"
></span>
<span class="common-range" id="speed-range">[0~3]</span>
</div>
<div class="status-content common-no-unit" id="speed">
<span class="speed-value common-no-unit-value">1</span>
</div>
<div class="speed-button common-button">
<button class="speed-down-btn">
<div class="speed-down common-down"></div>
</button>
<button class="speed-add-btn">
<div class="speed-add common-add"></div>
</button>
</div>
</div>
<!-- 方向 -->
<div class="status-card" id="direction-card" style="display: none">
<div class="status-title">
<span
i18n="control.massage.title10"
resize-font="true"
changeLineHeight="true"
smallSize="30"
checkHeight="true"
class="status-title-span"
></span>
</div>
<div class="status-content" id="direction">
<div class="direction-container">
<div class="common-switch">
<div class="common-slide-toggle" style="left: 40px"></div>
<!-- <div class="common-option"></div>
<div class="common-option active"></div> -->
</div>
<span
class="direction-value"
i18n="control.massage.title10_txt"
resize-font="true"
changeLineHeight="true"
smallSize="40"
checkHeight="true"
></span>
</div>
</div>
</div>
<!-- 高度 -->
<div class="status-card" id="high-card" style="display: none;">
<div class="status-title">
<span
i18n="control.massage.title11"
resize-font="true"
changeLineHeight="true"
smallSize="30"
checkHeight="true"
class="status-title-span"
></span>
<span class="common-range" id="high-range">[4~15]CM</span>
</div>
<div class="status-content common-no-unit" id="high">
<span class="high-value common-no-unit-value">6</span>
</div>
<div class="high-button common-button">
<button class="high-down-btn">
<div class="high-down common-down"></div>
</button>
<button class="high-add-btn">
<div class="high-add common-add"></div>
</button>
</div>
</div>
</div>
</div>
<div class="function-container" id="func-box">
<!-- <div class="flag-button" id="flag-btn">
<img id="flag-img" src="../static/images/narrow.png" alt="">
</div> -->
<div class="button-container">
<div class="control-button">
<button class="start" style="display: block">
<div i18n="control.massage.start_btn"></div>
</button>
<!-- <button class="stop" style="display: none">
<div i18n="control.massage.stop_btn">停止按摩</div>
<div class="progress-num"></div>
</button>
<div class="progress-bar"></div> -->
<div id="pause-btn-box" class="pause-btn-box" style="display: none">
<button class="pause" id="pause">
<img
class="pause-icon"
id="pause-icon"
src="/static/images/select_program/pause.png"
alt=""
/>
<div class="progress-num"></div>
</button>
<div class="progress-bar"></div>
</div>
<button class="stop" style="display: none">
<div i18n="control.massage.stop_btn"></div>
</button>
</div>
</div>
</div>
<div id="popup" class="popup"></div>
<!-- Popup Modal -->
<div id="popup-modal" class="popup-modal">
<div class="popup-content">
<p id="popup-message">这里是消息内容</p>
<div id="popup-buttons">
<button
id="confirm-btn"
onclick="confirmAction()"
i18n="popup.confirm_btn"
>
确认
</button>
<button
id="cancel-btn"
onclick="cancelAction()"
i18n="popup.cancel_btn"
>
取消
</button>
</div>
</div>
</div>
</div>
<script src="../static/js/swiper/swiper-bundle.min.js"></script>
<script src="../static/js/base.js"></script>
<script>
function showPopup2(message, buttons = { confirm: true, cancel: true }) {
// 设置弹窗的消息内容,使用 innerHTML 以支持换行
document.getElementById("popup-message").innerHTML = message;
// 控制按钮显示
document.getElementById("confirm-btn").style.display = buttons.confirm
? "inline-block"
: "none";
document.getElementById("cancel-btn").style.display = buttons.cancel
? "inline-block"
: "none";
// 显示弹窗
document.getElementById("popup-modal").style.display = "flex";
// 返回Promise等待用户选择
return new Promise((resolve) => {
popupResolve = resolve; // 保存 resolve 函数
});
}
function confirmAction() {
// 用户点击确认按钮关闭弹窗并返回true
document.getElementById("popup-modal").style.display = "none";
popupResolve(true);
}
function cancelAction() {
// 用户点击取消按钮关闭弹窗并返回false
document.getElementById("popup-modal").style.display = "none";
popupResolve(false);
}
const socket = io();
socket.on("update_massage_status", function (data) {
updateStatusDisplay(data);
});
document.addEventListener("DOMContentLoaded", function () {
const contentElement = document.getElementById("massage-head");
const text = contentElement.textContent;
const formattedText = text.replace(/(.{2})/g, "$1\n");
contentElement.textContent = formattedText;
const scrollView = document.querySelector(".scroll-view");
// 定义每个档位的高度,假设每个档位占窗口的高度
const slotHeight = window.innerHeight / 3; // 每次滚动到三分之一的窗口高度
scrollView.addEventListener("scroll", () => {
// 使用 setTimeout 来处理节流,避免频繁触发滚动事件
clearTimeout(scrollView.scrollTimeout);
scrollView.scrollTimeout = setTimeout(() => {
const scrollTop = scrollView.scrollTop;
const nearestSlot = Math.round(scrollTop / slotHeight) * slotHeight;
scrollView.scrollTo({
top: nearestSlot,
behavior: "smooth",
});
}, 100); // 延迟 100ms 检测滚动完成后吸附
});
});
let massageCard = document.getElementById("massage-card");
let massageContent = document.getElementById("massage-head");
let massageImage = massageCard.querySelector("img");
const strengthCard = document.querySelector("#strength-card");
const temperatureCard = document.querySelector("#temperature-card");
const shakeCard = document.querySelector("#shake-card");
const currentCard = document.querySelector("#current-card");
const frequencyCard = document.querySelector("#frequency-card");
const pressCard = document.querySelector("#press-card");
const speedCard = document.querySelector("#speed-card");
const directionCard = document.querySelector("#direction-card");
const highCard = document.querySelector("#high-card");
const commonSwitch = document.querySelector(".common-switch");
const commonSlideToggle = commonSwitch.querySelector(
".common-slide-toggle"
);
function getHeadSelectIndex() {
// let headerLength = parseInt(localStorage.getItem("headerLength"));
let headSelectIndex =
parseInt(localStorage.getItem("headSelectIndex")) || 0;
// if (headSelectIndex >= headerLength) {
// headSelectIndex = 0;
// localStorage.setItem("headSelectIndex", headSelectIndex);
// }
return headSelectIndex;
}
// 疗程滑块
var programSwiper = new Swiper(".program-swiper", {
// direction: "vertical", // 垂直切换选项
loop: false, // 循环模式选项
centeredSlides: true, // 居中切换选项
observer: true, // 监听选项
observeParents: true, // 监听父元素选项
centerInsufficientSlides: true, // 居中不足的slides选项
navigation: {
nextEl: ".program-next",
prevEl: ".program-prev",
},
});
// 右侧点击按摩头更换逻辑部分代码
let massageHeaderData = [
{
newText: "深部热疗",
i18n: "control.massage.data_text",
newImageSrc:
"{{ url_for('static', filename='images/massage_control/head/深部热疗.png') }}",
},
{
newText: "点阵按摩",
i18n: "control.massage.data_text2",
newImageSrc:
"{{ url_for('static', filename='images/massage_control/head/点阵按摩.png') }}",
},
{
newText: "全能滚珠",
i18n: "control.massage.data_text3",
newImageSrc:
"{{ url_for('static', filename='images/massage_control/head/全能滚珠.png') }}",
},
{
newText: "指疗通络",
i18n: "control.massage.data_text4",
newImageSrc:
"{{ url_for('static', filename='images/massage_control/head/指疗通络.png') }}",
},
{
newText: "滚滚刺疗",
i18n: "control.massage.data_text5",
newImageSrc:
"{{ url_for('static', filename='images/massage_control/head/滚滚刺疗.png') }}",
},
{
newText: "温砭舒揉",
i18n: "control.massage.data_text6",
newImageSrc:
"{{ url_for('static', filename='images/massage_control/head/温砭舒揉.png') }}",
},
{
newText: "离子光灸",
i18n: "control.massage.data_text7",
newImageSrc:
"{{ url_for('static', filename='images/massage_control/head/离子光灸.png') }}",
},
{
newText: "能量热疗",
i18n: "control.massage.data_text8",
newImageSrc:
"{{ url_for('static', filename='images/massage_control/head/能量热疗.png') }}",
},
{
newText: "天球滚捏",
i18n: "control.massage.data_text9",
newImageSrc:
"{{ url_for('static', filename='images/massage_control/head/天球滚捏.png') }}",
}
];
var bodyPartSwiper = new Swiper(".body-part-swiper", {
loop: false, // 循环模式选项
centeredSlides: true, // 居中切换选项
observer: true, // 监听选项
observeParents: true, // 监听父元素选项
centerInsufficientSlides: true, // 居中不足的slides选项
navigation: {
nextEl: ".body-part-next",
prevEl: ".body-part-prev",
},
});
const bodyPartWrapper = document.getElementById("body-part-wrapper");
function setBodySwiper(val) {
// 替换status-content中的文本
// massageContent.textContent = massageHeaderData[val].newText;
massageContent.style.fontSize = "5.5vw";
massageContent.style.lineHeight = "6vw";
massageContent.style.opacity = "0";
massageContent.setAttribute("i18n", massageHeaderData[val].i18n);
massageContent.setAttribute("resize-font", true);
massageContent.setAttribute("changeLineHeight", true);
massageContent.setAttribute("smallSize", "60");
massageContent.setAttribute("checkHeight", true);
// 替换img的图片路径
massageImage.src = massageHeaderData[val].newImageSrc;
if (val == 0 || val == 6 || val == 7 ) {
bodyPartWrapper.innerHTML = `
<div class="selectable swiper-slide swiper-slide-active">
<div class="body-swiper">
<img class="body-swiper-icon" src="{{ url_for('static', filename='images/massage_control/bodypart/back-btn.png') }}" />
<span i18n="control.massage.body_part_back"></span>
<!--背部-->
</div>
</div>
<div class="selectable swiper-slide">
<div class="body-swiper">
<img class="body-swiper-icon" src="{{ url_for('static', filename='images/massage_control/bodypart/belly-btn.png') }}" />
<span i18n="control.massage.body_part_belly"></span>
<!--腹部-->
</div>
</div>`;
} else if (val == 5 ) {
bodyPartWrapper.innerHTML = `
<div class="selectable swiper-slide swiper-slide-active">
<div class="body-swiper">
<img class="body-swiper-icon" src="{{ url_for('static', filename='images/massage_control/bodypart/back-btn.png') }}" />
<span i18n="control.massage.body_part_back"></span>
<!--背部-->
</div>
</div>
<div class="selectable swiper-slide">
<div class="body-swiper">
<img class="body-swiper-icon" src="{{ url_for('static', filename='images/massage_control/bodypart/belly-btn.png') }}" />
<span i18n="control.massage.body_part_belly"></span>
<!--腹部-->
</div>
</div>
<div class="selectable swiper-slide">
<div class="body-swiper">
<img class="body-swiper-icon" src="{{ url_for('static', filename='images/massage_control/bodypart/leg-btn.png') }}" />
<span i18n="control.massage.body_part_leg"></span>
<!--腿部-->
</div>
</div>`;
} else if (val == 1 || val == 8) {
bodyPartWrapper.innerHTML = `
<div class="swiper-slide swiper-slide-active" body-part="back">
<div class="body-swiper">
<img class="body-swiper-icon" src="{{ url_for('static', filename='images/massage_control/bodypart/back-btn.png') }}" />
<span i18n="control.massage.body_part_back"></span>
<!--背部-->
</div>
</div>
<div class="swiper-slide" body-part="shoulder">
<div class="body-swiper">
<img class="body-swiper-icon" src="{{ url_for('static', filename='images/massage_control/bodypart/shoulder-btn.png') }}" />
<span i18n="control.massage.body_part_shoulder"></span>
<!--肩颈-->
</div>
</div>
<div class="swiper-slide" body-part="back_shoulder">
<div class="body-swiper">
<img class="body-swiper-icon" src="{{ url_for('static', filename='images/massage_control/bodypart/back_shoulder-btn.png') }}"/>
<span i18n="control.massage.body_part_back_shoulder"></span>
<!--背部+肩颈-->
</div>
</div>`;
} else if (val == 2 || val == 3 || val == 4) {
bodyPartWrapper.innerHTML = `
<div class="swiper-slide swiper-slide-active" body-part="back">
<div class="body-swiper">
<img class="body-swiper-icon" src="{{ url_for('static', filename='images/massage_control/bodypart/back-btn.png') }}" />
<span i18n="control.massage.body_part_back"></span>
<!--背部-->
</div>
</div>
<div class="swiper-slide" body-part="shoulder">
<div class="body-swiper">
<img class="body-swiper-icon" src="{{ url_for('static', filename='images/massage_control/bodypart/shoulder-btn.png') }}" />
<span i18n="control.massage.body_part_shoulder"></span>
<!--肩颈-->
</div>
</div>
<div class="swiper-slide" body-part="back_shoulder">
<div class="body-swiper">
<img class="body-swiper-icon" src="{{ url_for('static', filename='images/massage_control/bodypart/back_shoulder-btn.png') }}"/>
<span i18n="control.massage.body_part_back_shoulder"></span>
<!--背部+肩颈-->
</div>
</div>
<div class="selectable swiper-slide">
<div class="body-swiper">
<img class="body-swiper-icon" src="{{ url_for('static', filename='images/massage_control/bodypart/leg-btn.png') }}" />
<span i18n="control.massage.body_part_leg"></span>
<!--腿部-->
</div>
</div>`;
} else {
bodyPartWrapper.innerHTML = `
<div class="swiper-slide swiper-slide-active" body-part="back">
<div class="body-swiper">
<img class="body-swiper-icon" src="{{ url_for('static', filename='images/massage_control/bodypart/back-btn.png') }}" />
<span i18n="control.massage.body_part_back"></span>
<!--背部-->
</div>
</div>`;
}
bodyPartSwiper.slideTo(0);
bodyPartSwiper.update();
setTimeout(() => {
loadLanguageFun(lang);
massageContent.style.opacity = "0.6";
}, 500);
}
let headSelectIndex = getHeadSelectIndex();
setBodySwiper(headSelectIndex);
toggleSettingCard(headSelectIndex);
// 监听 slideChange 事件
bodyPartSwiper.on("slideChange", function () {
// 获取当前滑动的索引
let headSelectIndex = getHeadSelectIndex();
let bodyPartSelectIndex = bodyPartSwiper.activeIndex + 1;
if (headSelectIndex == 1 || headSelectIndex == 3) {
bodyPart =
bodyPartSelectIndex == 1
? "back"
: bodyPartSelectIndex == 2
? "shoulder"
: "back_shoulder";
localStorage.setItem("bodyPart", bodyPart);
} else if (
headSelectIndex == 2 ||
headSelectIndex == 0 ||
headSelectIndex == 5
) {
bodyPart = bodyPartSelectIndex == 1 ? "back" : "belly";
localStorage.setItem("bodyPart", bodyPart);
} else {
bodyPart = "back";
localStorage.setItem("bodyPart", bodyPart);
}
changeSetting();
});
// 监听 slideChange 事件
bodyPartSwiper.on("touchMove", async function () {
if (
bodyPartSwiper.slides.length > 1 &&
bodyPartSwiper.allowSlideNext === false
) {
let commandStartedText = await getPopupText("commandStartedText");
showPopup(commandStartedText);
}
});
// 添加滑动提示
programSwiper.on("touchMove", async function () {
if (programSwiper.allowSlideNext === false) {
let commandStartedText = await getPopupText("commandStartedText");
showPopup(commandStartedText);
}
});
function toggleAllowSlide(flag) {
programSwiper.allowSlideNext = flag;
programSwiper.allowSlidePrev = flag;
bodyPartSwiper.allowSlideNext = flag;
bodyPartSwiper.allowSlidePrev = flag;
}
const popupElement = document.getElementById("popup");
function toggleSettingCard(type) {
/**
* 0深部热疗
* 1点阵按摩
* 2全能滚珠
* 3指疗通络
* 4滚滚刺疗
* 5温砭舒揉 stone
* 6离子光灸
* 7能量热疗
`````` * 8: 天球滚捏
*/
const allCards = [
strengthCard, temperatureCard, currentCard, shakeCard,
frequencyCard, pressCard, speedCard, directionCard, highCard
];
allCards.forEach(card => card.style.display = "none");
switch (parseInt(type)) {
case 0:
strengthCard.style.display = "block";
temperatureCard.style.display = "block";
shakeCard.style.display = "block";
currentCard.style.display = "block";
break;
case 1:
strengthCard.style.display = "block";
frequencyCard.style.display = "block";
pressCard.style.display = "block";
break;
case 2:
case 3:
case 4:
case 8:
strengthCard.style.display = "block";
break;
case 5:
strengthCard.style.display = "block";
temperatureCard.style.display = "block";
speedCard.style.display = "block";
directionCard.style.display = "block";
break;
case 6:
temperatureCard.style.display = "block";
highCard.style.display = "block";
break;
case 7:
strengthCard.style.display = "block";
temperatureCard.style.display = "block";
break;
}
}
function handleClickOutside(event) {
const massagePopup = document.getElementById("massage-popup");
if (
massagePopup.style.display === "flex" &&
!massagePopup.contains(event.target) &&
!document.getElementById("massage-card").contains(event.target)
) {
massagePopup.style.display = "none";
document.removeEventListener("click", handleClickOutside); // 移除文档的点击事件监听
}
}
// 获取按钮元素
const startButton = document.querySelector(".start");
const pauseButton = document.querySelector(".pause-btn-box");
const pauseIcon = document.querySelector("#pause-icon");
const stopButton = document.querySelector(".stop");
const massageHeadElement = document.getElementById("massage-head");
const calculateModeReal = () => {
let modeReal = parseInt(localStorage.getItem("modeReal")) === 0 ? 0 : 1;
const powerControl = localStorage.getItem("powerControl");
let loadMode = parseInt(localStorage.getItem("loadMode")) === 1 ? 1 : 0;
// if (loadMode === 1) {
// return 3;
// }
// // 如果 loadMode 为 0根据 modeReal 判断返回值
// if (loadMode === 0) {
// if (modeReal === 0) {
// // 如果 modeReal 为 0根据 powerControl 判断返回值
// if (powerControl === "导纳" || !powerControl) {
// return 0; // 如果 powerControl 为 "导纳" 或为空,则返回 0
// } else {
// return 2; // 否则返回 2
// }
// }
// }
// // 默认返回 1
// return 1;
if (modeReal === 0) {
if (powerControl === "导纳" || !powerControl) {
modeReal = 0;
} else {
modeReal = 2;
}
} else {
if (loadMode === 1) {
modeReal = 3;
} else if (loadMode === 0) {
modeReal = 1;
}
}
return modeReal;
};
const headSelectionMap = [
{
head: "thermotherapy",
headTxt: "深部热疗",
message: "请确认按摩机器人已经安装“深部热疗”按摩头",
},
{
head: "shockwave",
headTxt: "点阵按摩",
message: "请确认按摩机器人已经安装“点阵按摩”按摩头",
},
{
head: "ball",
headTxt: "全能滚珠",
message: "请确认按摩机器人已经安装“全能滚珠”按摩头",
},
{
head: "finger",
headTxt: "指疗通络",
message: "请确认按摩机器人已经安装“指疗通络”按摩头",
},
{
head: "roller",
headTxt: "滚滚刺疗",
message: "请确认按摩机器人已经安装“滚滚刺疗”按摩头",
},
{
head: "stone",
headTxt: "温砭舒揉",
message: "请确认按摩机器人已经安装“温砭舒揉”按摩头",
},
{
head: "ion",
headTxt: "离子光灸",
message: "请确认按摩机器人已经安装“离子光灸”按摩头",
},
{
head: "heat",
headTxt: "能量热疗",
message: "请确认按摩机器人已经安装“能量热疗”按摩头",
},
{
head: "spheres",
headTxt: "天球滚捏",
message: "请确认按摩机器人已经安装“天球滚捏”按摩头",
},
];
// 开始按摩点击事件
startButton.addEventListener(
"click",
debounce(async () => {
checkLicense()
.then(async (data) => {
console.log("License Data:", data);
const topDocument = window.top;
if (data.can_use) {
try {
// 获取状态
const status = await getStatus();
if (!status) {
let infoFailedText = await getPopupText("infoFailedText");
showPopup(infoFailedText);
return;
}
if (!status.massage_service_started) {
let connectArmText = await getPopupText("connectArmText");
showPopup(connectArmText);
return;
}
if (status.is_massaging) {
let massageStartText = await getPopupText(
"massageStartText"
);
showPopup(massageStartText);
return;
}
let head, headTxt;
const headSelectIndex =
parseInt(localStorage.getItem("headSelectIndex")) || 0;
const selection = headSelectionMap[headSelectIndex];
if (selection) {
head = selection.head;
headTxt = selection.headTxt;
// topDocument.showPopup(selection.message).then((confirm) => {
// if (confirm) {
// doMassage();
// }
// });
function setHintMsg(selectedHeadText) {
let msg = {
zh: `
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span>本设备必须由</span>
<span class="hint-bold-text">经过培训的专业人员</span>
<span>操作使用,非专业人员请勿擅自操作。</span>
</div>
</div>
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span class="hint-bold-text">孕妇、心血管疾病患者、局部皮肤破损者</span>
<span>等禁止使用。</span>
</div>
</div>
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span class="hint-bold-text">体内有金属者、佩戴金属饰品、严重骨质疏松患者</span>
<span>及其他身体不适者在理疗前告知理疗师。</span>
</div>
</div>
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span class="hint-bold-text">生理期与哺乳期</span>
<span>不建议进行理疗,建议根据身体状况选择理疗时间。</span>
</div>
</div>
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span class="hint-bold-text">空腹、醉酒</span>
<span>等状态下不宜进行理疗。</span>
</div>
</div>
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span>冬季理疗时请避免</span>
<span class="hint-bold-text">穿过厚、过宽松的衣物</span>
<span>,以确保最佳效果。</span>
</div>
</div>
<div class="hint-item" style="margin-top: 20px; font-weight: 600;">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span>请确认安装的按摩头为</span>
<span class="hint-bold-text" style="color: #FF5722;">${selectedHeadText}</span>
<span>按摩头</span>
</div>
</div>
`,
en: `
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span>This device must be operated by </span>
<span class="hint-bold-text">certified professionals only</span>
<span>. Unauthorized use is prohibited.</span>
</div>
</div>
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span class="hint-bold-text">Pregnant women, cardiovascular patients, individuals with skin lesions</span>
<span> are strictly prohibited from use.</span>
</div>
</div>
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span class="hint-bold-text">Metal implants, jewelry wearers, osteoporosis patients</span>
<span> must inform therapist prior to treatment.</span>
</div>
</div>
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span class="hint-bold-text">Menstruation and lactation periods</span>
<span> require medical consultation before therapy.</span>
</div>
</div>
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span class="hint-bold-text">Fasting or intoxication</span>
<span> are contraindicated for therapy.</span>
</div>
</div>
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span>In winter, avoid </span>
<span class="hint-bold-text">bulky clothing</span>
<span> to ensure therapeutic efficacy.</span>
</div>
</div>
<div class="hint-item" style="margin-top: 20px; font-weight: 600;">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span>Confirm installed head: </span>
<span class="hint-bold-text" style="color: #FF5722;">${selectedHeadText}</span>
</div>
</div>`,
jp: `
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span>本機器は</span>
<span class="hint-bold-text">訓練を受けた専門家のみ</span>
<span>が操作可能です。</span>
</div>
</div>
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span class="hint-bold-text">妊婦・心臓病患者・皮膚損傷者</span>
<span>は使用禁止です。</span>
</div>
</div>
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span class="hint-bold-text">体内金属・装身具・骨粗鬆症患者</span>
<span>は施術前に申告してください。</span>
</div>
</div>
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span class="hint-bold-text">生理中・授乳中</span>
<span>の方は医師にご相談ください。</span>
</div>
</div>
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span class="hint-bold-text">空腹時・飲酒時</span>
<span>の施術は避けてください。</span>
</div>
</div>
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span>冬季は</span>
<span class="hint-bold-text">厚着を避け</span>
<span>効果を確保してください。</span>
</div>
</div>
<div class="hint-item" style="margin-top: 20px; font-weight: 600;">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span>装着ヘッド確認: </span>
<span class="hint-bold-text" style="color: #FF5722;">${selectedHeadText}</span>
</div>
</div>`,
ko: `
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span>본 장비는 </span>
<span class="hint-bold-text">훈련된 전문가만</span>
<span> 조작 가능합니다.</span>
</div>
</div>
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span class="hint-bold-text">임산부, 심혈관 질환자, 피부 손상자</span>
<span> 사용 금지.</span>
</div>
</div>
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span class="hint-bold-text">체내 금속, 장신구, 골다공증 환자</span>
<span>는 시술 전 알려주세요.</span>
</div>
</div>
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span class="hint-bold-text">생리 중, 수유 중</span>
<span>에는 의사 상담이 필요합니다.</span>
</div>
</div>
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span class="hint-bold-text">공복, 음주 상태</span>
<span>에서는 사용을 자제하세요.</span>
</div>
</div>
<div class="hint-item">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span>겨울철 </span>
<span class="hint-bold-text">두꺼운 옷 착용을 피하고</span>
<span> 효과를 극대화하세요.</span>
</div>
</div>
<div class="hint-item" style="margin-top: 20px; font-weight: 600;">
<img class="hint-icon" src="static/images/hint/hint.png" alt="">
<div>
<span>장착 헤드 확인: </span>
<span class="hint-bold-text" style="color: #FF5722;">${selectedHeadText}</span>
</div>
</div>`,
};
return msg[lang];
}
let msg = setHintMsg(headTxt);
topDocument.showHintModal(msg).then((confirm) => {
if (confirm) {
doMassage();
}
});
} else {
console.error("Invalid headSelectIndex:", headSelectIndex);
}
const doMassage = async () => {
const bodyPart = localStorage.getItem("bodyPart") || "back";
const modeReal = calculateModeReal();
const selectedItem = getSelectedItem();
if (!head) {
console.error("Unknown massage head type");
return;
}
const postData = new URLSearchParams({
progress: "0",
current_head: head,
current_task: "-1",
task_time: selectedItem,
body_part: bodyPart,
});
try {
const response = await fetch("/update_massage_status", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: postData.toString(),
});
const result = await response.json();
console.log("Massage status updated:", result);
socket.emit(
"send_command",
`begin:${head}:${selectedItem}:${bodyPart}:${modeReal}`
);
console.log(
"send_command",
`begin:${head}:${selectedItem}:${bodyPart}:${modeReal}`
);
localStorage.setItem("headChangeFlag", false);
startButton.style.display = "none";
pauseButton.style.display = "block";
stopButton.style.display = "flex";
} catch (error) {
console.error("Failed to update massage status:", error);
}
};
} catch (error) {
console.error("Error during massage initialization:", error);
}
} else {
let activatePleaseText = await getPopupText(
"activatePleaseText"
);
topDocument.showPopup(activatePleaseText, {
confirm: true,
cancel: false,
});
}
})
.catch((error) => {
console.error("Error checking license:", error);
});
}, 800)
);
pauseButton.addEventListener(
"click",
debounce(async () => {
let isPausedText = await getPopupText("isPausedText");
let topDocument = window.top;
topDocument.showPopup(isPausedText).then(async (confirm) => {
if (confirm) {
try {
// 获取状态
const status = await getStatus();
if (!status) {
let infoFailedText = await getPopupText("infoFailedText");
showPopup(infoFailedText);
return;
}
if (status.is_massaging === true) {
socket.emit("send_command", "pause");
// pauseIcon.src = "/static/images/select_program/re-start.png";
} else {
if (status.is_pause === true) {
const head = status.current_head.replace(/_head$/, "");
const selectedItem = status.task_time;
const bodyPart = status.body_part;
const modeReal = calculateModeReal();
socket.emit(
"send_command",
`begin:${head}:${selectedItem}:${bodyPart}:${modeReal}`
);
console.log(
"send_command",
`begin:${head}:${selectedItem}:${bodyPart}:${modeReal}`
);
// pauseIcon.src = "/static/images/select_program/pause.png";
}
}
} catch (error) {
console.error("Error during massage initialization:", error);
}
}
});
}, 500)
);
// 监听"停止按摩"按钮点击事件
stopButton.addEventListener(
"click",
debounce(() => {
let topDocument = window.top;
topDocument.showPopup("确认结束按摩").then(async (confirm) => {
if (confirm) {
const status = await getStatus();
if (status && status.is_massaging === false) {
// 使用返回的状态字典
let massageStoppedText = await getPopupText(
"massageStoppedText"
);
showPopup(massageStoppedText);
} else {
socket.emit("send_command", "stop");
}
}
});
}, 800)
);
// 显示弹出框message是要显示的内容
function showPopup(message) {
popupElement.textContent = message;
popupElement.classList.add("show");
popupElement.classList.remove("hide");
setTimeout(() => {
popupElement.classList.add("hide");
setTimeout(() => {
popupElement.classList.remove("show");
}, 300); // 与CSS中的动画时间匹配
}, 2000); // 2秒后开始隐藏弹出框
}
// 公用设置项
let settings = [
{
name: "force",
min: 5,
// max: 50,
max: getDefaultData("max-force"),
initialValue: getDefaultData("force"),
elementSelectors: {
value: ".force-value",
addButton: ".force-add-btn",
downButton: ".force-down-btn",
},
socketCommand: {
increase: "adjust:force:increase:low",
decrease: "adjust:force:decrease:low",
},
maxPopupText: "maxForceText",
minPopupText: "minForceText",
},
{
name: "temperature",
min: 0,
max: getDefaultData("max-temperature"),
initialValue: getDefaultData("temperature"),
elementSelectors: {
value: ".temperature-value",
addButton: ".temperature-add-btn",
downButton: ".temperature-down-btn",
},
socketCommand: {
increase: "adjust:temperature:increase:low",
decrease: "adjust:temperature:decrease:low",
},
maxPopupText: "maxTempText",
minPopupText: "minTempText",
},
{
name: "shake",
min: 0,
max: 5,
initialValue: 0,
elementSelectors: {
value: ".shake-value",
addButton: ".shake-add-btn",
downButton: ".shake-down-btn",
},
socketCommand: {
increase: "adjust:shake:increase:low",
decrease: "adjust:shake:decrease:low",
},
maxPopupText: "maxLevelText",
minPopupText: "minLevelText",
},
{
name: "gear",
min: 0,
max: 5,
initialValue: 0,
elementSelectors: {
value: ".gear-value",
addButton: ".gear-add-btn",
downButton: ".gear-down-btn",
},
socketCommand: {
increase: "adjust:gear:increase:low",
decrease: "adjust:gear:decrease:low",
},
maxPopupText: "maxLevelText",
minPopupText: "minLevelText",
},
{
name: "frequency",
min: 1,
max: 16,
initialValue: 6,
elementSelectors: {
value: ".frequency-value",
addButton: ".frequency-add-btn",
downButton: ".frequency-down-btn",
},
socketCommand: {
increase: "adjust:frequency:increase:low",
decrease: "adjust:frequency:decrease:low",
},
maxPopupText: "maxFrequencyText",
minPopupText: "minFrequencyText",
},
{
name: "press",
min: 1,
max: 27,
initialValue: 12,
elementSelectors: {
value: ".press-value",
addButton: ".press-add-btn",
downButton: ".press-down-btn",
},
socketCommand: {
increase: "adjust:press:increase:low",
decrease: "adjust:press:decrease:low",
},
maxPopupText: "maxPressText",
minPopupText: "minPressText",
},
{
name: "speed",
min: 0,
max: 3,
initialValue: 2,
elementSelectors: {
value: ".speed-value",
addButton: ".speed-add-btn",
downButton: ".speed-down-btn",
},
socketCommand: {
increase: "adjust:speed:increase:low",
decrease: "adjust:speed:decrease:low",
},
maxPopupText: "maxLevelText",
minPopupText: "minLevelText",
},
{
name: "direction",
min: 0,
max: 1,
initialValue: 1,
},
];
// 创建通用函数来处理增减逻辑
async function handleAdjustButtonClick(setting, isIncrease) {
const btnClick = function () {
return new Promise(async (resolve, reject) => {
if (isIncrease) {
// 判断增值操作
if (setting.initialValue == setting.max) {
let maxPopupText = await getPopupText(setting.maxPopupText);
showPopup(maxPopupText, { confirm: true, cancel: false }); // 超过最大值时弹出提示
reject(); // 直接返回,不执行后续逻辑
} else {
socket.emit(
"send_command",
setting.socketCommand.increase,
() => {
resolve(); // 确保命令执行后再继续
}
);
}
} else {
// 判断减值操作
if (setting.initialValue == setting.min) {
let minPopupText = await getPopupText(setting.minPopupText);
showPopup(minPopupText, { confirm: true, cancel: false }); // 超过最小值时弹出提示
reject(); // 直接返回,不执行后续逻辑
} else {
socket.emit(
"send_command",
setting.socketCommand.decrease,
() => {
resolve(); // 确保命令执行后再继续
}
);
}
}
});
};
const status = await getStatus(); // 获取当前状态
if (status.is_massaging === true) {
if (
status.massage_state === "CV_TASK" ||
status.massage_state === "IDLE"
) {
let notAdjustText = await getPopupText("notAdjustText");
showPopup(notAdjustText);
return;
}
try {
btnClick().then((res) => {
getStatus();
});
} catch (error) {
console.error("操作未执行", error);
}
} else {
// 如果是 shockwave 模式,需要特殊处理
let notAdjustText = await getPopupText("notAdjustText");
showPopup(notAdjustText);
}
}
// 方向按钮的点击事件:
commonSwitch.addEventListener(
"click",
throttle(async () => {
const status = await getStatus(); // 等待获取状态
if (
status &&
status.massage_state === "CV_TASK" &&
status.is_massaging === true
) {
let photoingText = await getPopupText("photoingText");
showPopup(photoingText);
} else if (status && status.is_massaging === true) {
if (settings[7].initialValue == 0) {
settings[7].initialValue = 1;
commonSlideToggle.style.left = "40px";
} else {
settings[7].initialValue = 0;
commonSlideToggle.style.left = 0;
}
socket.emit("send_command", "adjust:direction:null:null");
} else {
// 如果是 shockwave 模式,需要特殊处理
let notAdjustText = await getPopupText("notAdjustText");
showPopup(notAdjustText);
return;
}
}, 2000)
);
// 更新显示的通用函数
function updateDisplay(setting) {
const valueElement = document.querySelector(
setting.elementSelectors.value
);
valueElement.textContent = String(setting.initialValue).padStart(
2,
"0"
);
}
// 创建并绑定事件监听器
function initializeSettings() {
settings.forEach((setting, index) => {
if (index != 7) {
// 更新显示初始值
updateDisplay(setting);
// 获取按钮元素
const addButton = document.querySelector(
setting.elementSelectors.addButton
);
const downButton = document.querySelector(
setting.elementSelectors.downButton
);
// 增加按钮,减少按钮
// 绑定点击事件
addButton.addEventListener(
"click",
throttle(() => handleAdjustButtonClick(setting, true), 500)
); // 增加
downButton.addEventListener(
"click",
throttle(() => handleAdjustButtonClick(setting, false), 500)
); // 减少
}
});
}
function getDefaultData(type) {
let bodyPart = localStorage.getItem("bodyPart") || "back";
// let val;
let headSelectIndex =
parseInt(localStorage.getItem("headSelectIndex")) || 0;
let val;
switch (type) {
case "force":
val =
headSelectIndex == 1
? 5
: headSelectIndex == 2
? 15
: bodyPart == "belly"
? 10
: 20;
break;
case "max-force":
// val = headSelectIndex === 1 ? 12 : 50;
val = 70;
break;
case "temperature":
val = headSelectIndex == 0 ? 3 : 1;
break;
case "max-temperature":
// val = 5;
val = headSelectIndex == 7 ? 3 : 5;
break;
default:
break;
}
return val;
}
async function changeSetting() {
// 初始化设置的默认值
settings[0].initialValue = getDefaultData("force");
settings[0].max = getDefaultData("max-force"); // force
settings[1].initialValue = getDefaultData("temperature"); // temperature
settings[1].max = getDefaultData("max-temperature"); // temperature
settings[2].initialValue = 0; // shake
settings[3].initialValue = 0; // gear
settings[4].initialValue = 6; // frequency
settings[5].initialValue = 12; // press
settings[6].initialValue = 2; // speed
settings[7].initialValue = 1; // direction
commonSlideToggle.style.left = "40px";
const forceRange = document.querySelector("#force-range");
forceRange.innerText = `[${settings[0].min}~${settings[0].max}]`;
const temperatureRange = document.querySelector("#temperature-range");
temperatureRange.innerText = `[${settings[1].min}~${settings[1].max}]`;
// 更新显示
settings.forEach((setting, index) => {
if (index != 7) {
updateDisplay(setting);
}
});
}
async function initDisplay() {
const status = await getStatus();
updateStatusDisplay(status);
}
function changeData(name, val) {
let setting = settings.find((setting) => setting.name === name);
setting.initialValue = parseInt(val);
if (name !== "direction") {
updateDisplay(setting);
} else {
// commonSlideToggle.style.left = "40px";
if (val == 1) {
commonSlideToggle.style.left = "40px";
} else {
commonSlideToggle.style.left = 0;
}
}
}
let progressBar = document.querySelector(".progress-bar");
let progressData = document.querySelector(".progress-num");
async function updateStatusDisplay(data) {
console.log("adfdsf", JSON.stringify(data));
let topDocument = window.top;
let img2dImage = topDocument.document.getElementById("img2d-image");
if (data.hasOwnProperty("progress")) {
var newValueStr = data.progress; // 接收到的字符串类型的progress
var newValue = Math.round(parseFloat(newValueStr));
if (!isNaN(newValue)) {
// 确保转换成功
// 格式化 progress 值
var formattedValue;
if (
newValue === 0 ||
(newValue !== 0 && newValue < progressData.innerText)
) {
if (data.is_massaging) {
formattedValue = parseFloat(progressData.innerText) || 0;
} else {
formattedValue = newValue;
startButton.style.display = "block";
pauseButton.style.display = "none";
stopButton.style.display = "none";
// progressBar.style.transition = "none"; // 移除过渡效果
progressBar.style.width = "0%";
progressData.innerText = `0%`;
// setTimeout(() => {
// progressBar.style.transition = "width 0.5s ease-out";
// }, 50);
}
// formattedValue = '100'
} else if (newValue >= 100) {
if (data.is_massaging) {
formattedValue = 100;
} else {
formattedValue = 0;
}
} else if (newValue < 10) {
formattedValue = Math.round(newValue * 10) / 10; // 保留一位小数
} else {
formattedValue = Math.round(newValue * 10) / 10; // 保留一位小数
}
progressBar.style.width = `${formattedValue}%`;
progressData.innerText = `${formattedValue}%`;
} else {
console.error("Received an invalid progress value:", newValueStr);
}
}
if (data.hasOwnProperty("is_massaging")) {
if (data.is_massaging) {
// 按摩开始禁止切换
toggleAllowSlide(false);
localStorage.setItem("headChangeFlag", false);
startButton.style.display = "none";
// 显示暂停按钮和停止按钮
pauseButton.style.display = "block";
pauseIcon.src = "/static/images/select_program/pause.png";
stopButton.style.display = "flex";
// 替换穴位图片
if (data.hasOwnProperty("is_acupoint")) {
if (data.is_acupoint) {
img2dImage.src = "/static/images/back108points.png";
}
} else {
setImg2dImage(data.body_part, img2dImage);
}
} else {
setImg2dImage(data.body_part, img2dImage);
if (data.is_pause === true) {
// 按摩开始禁止切换
toggleAllowSlide(false);
localStorage.setItem("headChangeFlag", false);
startButton.style.display = "none";
// 显示暂停按钮和停止按钮
pauseButton.style.display = "block";
pauseIcon.src = "/static/images/select_program/re-start.png";
stopButton.style.display = "flex";
} else {
startButton.style.display = "block";
pauseButton.style.display = "none";
stopButton.style.display = "none";
// 按摩停止允许切换
toggleAllowSlide(true);
localStorage.setItem("headChangeFlag", true);
startButton.style.display = "block";
stopButton.style.display = "none";
// progressBar.style.transition = "none"; // 移除过渡效果
progressBar.style.width = "0%";
progressData.innerText = `0%`;
changeSetting();
}
}
}
if (data.is_massaging) {
if (
data.massage_state !== "CV_TASK" ||
data.massage_state !== "IDLE"
) {
if (data.hasOwnProperty("force")) {
if (data.force) {
changeData("force", data.force);
}
}
if (data.hasOwnProperty("temperature")) {
if (data.temperature) {
changeData("temperature", data.temperature);
}
}
if (data.hasOwnProperty("shake")) {
if (data.shake) {
changeData("shake", data.shake);
}
}
if (data.hasOwnProperty("gear")) {
if (data.gear) {
changeData("gear", data.gear);
}
}
if (data.hasOwnProperty("speed")) {
if (data.speed) {
changeData("speed", data.speed);
}
}
if (data.hasOwnProperty("direction")) {
if (data.direction) {
changeData("direction", data.direction);
}
}
if (data.hasOwnProperty("high")) {
if (data.high) {
changeData("high", data.high);
}
}
if (data.hasOwnProperty("current_head")) {
if (data.current_head) {
head = data.current_head;
let newText;
let headIndex;
let i18n;
if (data.is_massaging) {
if (head.includes("thermotherapy")) {
newText = "深部热疗";
headIndex = 0;
i18n = massageHeaderData[0].i18n;
} else if (head.includes("shockwave")) {
newText = "点阵按摩";
headIndex = 1;
i18n = massageHeaderData[1].i18n;
} else if (head.includes("ball")) {
newText = "全能滚珠";
headIndex = 2;
i18n = massageHeaderData[2].i18n;
} else if (head.includes("finger")) {
newText = "指疗通络";
headIndex = 3;
i18n = massageHeaderData[3].i18n;
} else if (head.includes("roller")) {
newText = "滚滚刺疗";
headIndex = 4;
i18n = massageHeaderData[4].i18n;
} else if (head.includes("stone")) {
newText = "温砭舒揉";
headIndex = 5;
i18n = massageHeaderData[5].i18n;
} else if (head.includes("ion")) {
newText = "离子光灸";
headIndex = 6;
i18n = massageHeaderData[6].i18n;
} else if (head.includes("heat")) {
newText = "能量热疗";
headIndex = 7;
i18n = massageHeaderData[7].i18n;
} else if (head.includes("spheres")) {
newText = "天球滚捏";
headIndex = 8;
i18n = massageHeaderData[8].i18n;
}
} else {
let headSelectIndex = getHeadSelectIndex();
headIndex = headSelectIndex;
if (headSelectIndex == 0) {
newText = "深部热疗";
} else if (headSelectIndex == 1) {
newText = "点阵按摩";
} else if (headSelectIndex == 2) {
newText = "全能滚珠";
} else if (headSelectIndex == 3) {
newText = "指疗通络";
} else if (headSelectIndex == 4) {
newText = "滚滚刺疗";
} else if (headSelectIndex == 5) {
newText = "温砭舒揉";
} else if (headSelectIndex == 6) {
newText = "离子光灸";
} else if (headSelectIndex == 7) {
newText = "能量热疗";
} else if (headSelectIndex == 8) {
newText = "天球滚捏";
}
i18n = massageHeaderData[headSelectIndex].i18n;
}
// 替换status-content中的文本
massageContent.setAttribute("i18n", i18n);
// 替换img的图片路径
massageImage.src = "static/images/" + newText + ".png";
localStorage.setItem("headSelectIndex", headIndex);
toggleSettingCard(headIndex);
await setBodySwiper(headIndex);
}
}
if (data.hasOwnProperty("task_time") && data.task_time) {
if (data.is_massaging) {
let taskTime = data.task_time;
let taskTimeIndex;
switch (taskTime) {
case 900:
taskTimeIndex = 0;
break;
case 1800:
taskTimeIndex = 1;
break;
case 2700:
taskTimeIndex = 2;
break;
case 3600:
taskTimeIndex = 3;
break;
case 5400:
taskTimeIndex = 4;
break;
case 7200:
taskTimeIndex = 5;
break;
default:
break;
}
programSwiper.slideTo(taskTimeIndex);
}
}
if (data.hasOwnProperty("body_part")) {
if (data.is_massaging) {
let bodyPart = data.body_part;
let bodyPartSelectIndex;
let headSelectIndex = getHeadSelectIndex();
switch (bodyPart) {
case "back":
bodyPartSelectIndex = 0;
break;
case "shoulder":
bodyPartSelectIndex = 1;
break;
case "back_shoulder":
bodyPartSelectIndex = 2;
break;
case "belly":
bodyPartSelectIndex = 1;
break;
default:
bodyPartSelectIndex = 0;
break;
}
bodyPartSwiper.slideTo(bodyPartSelectIndex);
toggleAllowSlide(false);
}
}
if (data.hasOwnProperty("press")) {
if (data.press) {
changeData("press", data.press);
}
}
if (data.hasOwnProperty("frequency")) {
if (data.frequency) {
changeData("frequency", data.frequency);
}
}
}
}
}
function setImg2dImage(body_part, img2dImage) {
switch (body_part) {
case "belly":
img2dImage.src = "/static/images/smart_mode/穴位2.png";
break;
default:
img2dImage.src = "/static/images/smart_mode/穴位.png";
break;
}
}
async function getStatus() {
try {
const response = await fetch("/get_status");
if (!response.ok) {
throw new Error("Network response was not ok");
}
const data = await response.json();
console.log("Status data:", data);
return data; // 直接返回字典数据
} catch (error) {
console.error("There was a problem with the fetch operation:", error);
return null;
}
}
function getSelectedItem() {
let activeSlide = programSwiper.activeIndex;
let timeVal;
switch (activeSlide) {
case 0:
timeVal = 900;
break;
case 1:
timeVal = 1800;
break;
case 2:
timeVal = 2700;
break;
case 3:
timeVal = 3600;
break;
case 4:
timeVal = 5400;
break;
case 5:
timeVal = 7200;
break;
default:
break;
}
return timeVal;
}
function setStorageBodyPart() {
let headSelectIndex = getHeadSelectIndex();
let bodyPart = localStorage.getItem("bodyPart") || "back";
let slideIndex;
if (
headSelectIndex == 2 ||
headSelectIndex == 0 ||
headSelectIndex == 5
) {
slideIndex = bodyPart === "back" ? 0 : 1;
} else {
slideIndex =
bodyPart === "back" ? 0 : bodyPart === "shoulder" ? 1 : 2;
}
bodyPartSwiper.slideTo(slideIndex);
}
window.onload = function () {
const startElement = document.querySelector(".start");
const stopElement = document.querySelector(".stop");
initDisplay();
initializeSettings();
setStorageBodyPart();
changeSetting();
};
window.onresize = function () {
const startElement = document.querySelector(".start");
const stopElement = document.querySelector(".stop");
};
</script>
<script>
// 监听 storage 事件
window.addEventListener("storage", function (event) {
if (event.key === "headSelectIndex") {
if (event.oldValue === event.newValue) {
return;
} else {
// if
toggleSettingCard(event.newValue);
setBodySwiper(event.newValue);
changeSetting();
}
}
});
document.addEventListener("visibilitychange", async function () {
if (document.visibilityState === "visible") {
let welcomeBackText = await getPopupText("welcomeBackText");
showPopup(welcomeBackText);
if (!socket.connected) {
socket.on("connect", () => {
console.log("Reconnected to the server");
// 确保连接后你可以继续监听事件
socket.on("update_massage_status", function (data) {
updateStatusDisplay(data);
});
});
}
}
});
</script>
</body>
</html>