1310 lines
45 KiB
HTML
1310 lines
45 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||
<title>作者:平平,的墨水屏上位机</title>
|
||
<meta name="viewport" content="initial-scale=0.6, maximum-scale=0.6, user-scalable=no">
|
||
<script src="https://cdn.jsdelivr.net/npm/qrcodejs@1.0.0/qrcode.min.js"></script>
|
||
<style>
|
||
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
-webkit-tap-highlight-color: transparent;
|
||
}
|
||
|
||
body {
|
||
background: #f1f5f9;
|
||
font-family: 'Segoe UI', 'SF Pro Text', 'PingFang SC', 'Microsoft YaHei', system-ui, -apple-system, sans-serif;
|
||
padding: 20px 16px 48px;
|
||
color: #0f172a;
|
||
}
|
||
|
||
|
||
.app-container {
|
||
max-width: 640px;
|
||
margin: 0 auto;
|
||
position: relative;
|
||
}
|
||
|
||
|
||
.tabs-mobile {
|
||
background: rgba(255, 255, 255, 0.8);
|
||
backdrop-filter: blur(24px);
|
||
border-radius: 48px;
|
||
padding: 6px;
|
||
display: flex;
|
||
gap: 8px;
|
||
margin-bottom: 48px;
|
||
box-shadow: 0 6px 14px rgba(0, 0, 0, 0.05), 0 1px 2px rgba(0, 0, 0, 0.02);
|
||
border: 0.5px solid rgba(255, 255, 255, 0.7);
|
||
position: sticky;
|
||
top: 12px;
|
||
z-index: 30;
|
||
transition: all 0.2s ease;
|
||
}
|
||
|
||
.tab-btn {
|
||
flex: 1;
|
||
background: transparent;
|
||
border: none;
|
||
padding: 12px 0;
|
||
border-radius: 40px;
|
||
font-weight: 590;
|
||
font-size: 30px;
|
||
color: #475569;
|
||
transition: all 0.3s cubic-bezier(0.2, 0.9, 0.4, 1.1);
|
||
cursor: pointer;
|
||
letter-spacing: 0.3px;
|
||
backdrop-filter: blur(4px);
|
||
}
|
||
|
||
.tab-btn.active {
|
||
background: white;
|
||
color: #0f172a;
|
||
box-shadow: 0 6px 14px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.03);
|
||
font-weight: 600;
|
||
transform: scale(0.98);
|
||
}
|
||
|
||
|
||
.tab-pane {
|
||
display: none;
|
||
animation: floatUp 0.35s ease-out;
|
||
background: white;
|
||
border-radius: 36px;
|
||
padding: 24px 20px;
|
||
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.05), 0 1px 1px rgba(0, 0, 0, 0.02);
|
||
margin-bottom: 24px;
|
||
transition: all 0.2s;
|
||
}
|
||
|
||
.button-group {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
animation: floatUp 0.35s ease-out;
|
||
background: rgb(233, 231, 231);
|
||
border-radius: 36px;
|
||
padding: 24px 20px;
|
||
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.05), 0 1px 1px rgba(0, 0, 0, 0.02);
|
||
margin-bottom: 24px;
|
||
transition: all 0.2s;
|
||
}
|
||
.tab-pane.active {
|
||
display: block;
|
||
}
|
||
|
||
@keyframes floatUp {
|
||
0% {
|
||
opacity: 0;
|
||
transform: translateY(20px) scale(0.97);
|
||
}
|
||
100% {
|
||
opacity: 1;
|
||
transform: translateY(0) scale(1);
|
||
}
|
||
}
|
||
|
||
|
||
.button-group {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 12px;
|
||
margin: 18px 0;
|
||
align-items: center;
|
||
}
|
||
|
||
button, .btn-like {
|
||
background: #f8fafc;
|
||
border: 1px solid #e2e8f0;
|
||
padding: 10px 18px;
|
||
border-radius: 120px;
|
||
font-size: 30px;
|
||
font-weight: 500;
|
||
color: #1e293b;
|
||
cursor: pointer;
|
||
transition: all 0.2s ease;
|
||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.02);
|
||
}
|
||
|
||
button:active {
|
||
transform: scale(0.95);
|
||
background: #eef2ff;
|
||
}
|
||
|
||
.btn-primary {
|
||
background: #2d3e6e;
|
||
color: white;
|
||
border: none;
|
||
box-shadow: 0 4px 10px rgba(45, 62, 110, 0.2);
|
||
}
|
||
|
||
|
||
input, select, textarea {
|
||
background: #ffffff;
|
||
border: 1.5px solid #e9edf2;
|
||
border-radius: 32px;
|
||
padding: 12px 16px;
|
||
font-size: 14px;
|
||
transition: all 0.2s;
|
||
font-family: inherit;
|
||
outline: none;
|
||
}
|
||
|
||
input:focus, select:focus, textarea:focus {
|
||
border-color: #2d3e6e;
|
||
box-shadow: 0 0 0 3px rgba(45, 62, 110, 0.15);
|
||
transform: scale(1.01);
|
||
}
|
||
|
||
|
||
h2, h3 {
|
||
font-size: 1.35rem;
|
||
font-weight: 620;
|
||
margin-bottom: 16px;
|
||
letter-spacing: -0.3px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
.badge-icon {
|
||
background: #eef2ff;
|
||
padding: 6px 14px;
|
||
border-radius: 50px;
|
||
font-size: 13px;
|
||
font-weight: 500;
|
||
}
|
||
|
||
|
||
.slider-group {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
gap: 12px;
|
||
margin: 12px 0;
|
||
}
|
||
input[type="range"] {
|
||
flex: 1;
|
||
height: 5px;
|
||
|
||
background: #e2e8f0;
|
||
border-radius: 10px;
|
||
}
|
||
input[type="range"]:focus {
|
||
outline: none;
|
||
}
|
||
input[type="range"]::-webkit-slider-thumb {
|
||
-webkit-appearance: none;
|
||
width: 20px;
|
||
height: 20px;
|
||
background: #2d3e6e;
|
||
border-radius: 50%;
|
||
cursor: pointer;
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||
transition: 0.1s;
|
||
}
|
||
|
||
|
||
.color-palette {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 14px;
|
||
margin: 16px 0;
|
||
}
|
||
.color-option {
|
||
width: 42px;
|
||
height: 42px;
|
||
border-radius: 60px;
|
||
cursor: pointer;
|
||
transition: all 0.2s cubic-bezier(0.2, 0.9, 0.4, 1.2);
|
||
box-shadow: 0 3px 8px rgba(0,0,0,0.1);
|
||
}
|
||
.color-option:active {
|
||
transform: scale(0.88);
|
||
}
|
||
|
||
|
||
.switch-group {
|
||
background: #eef2ff;
|
||
border-radius: 60px;
|
||
padding: 4px;
|
||
display: flex;
|
||
position: relative;
|
||
margin: 16px 0;
|
||
cursor: pointer;
|
||
}
|
||
.switch-slider-ball {
|
||
position: absolute;
|
||
width: 50%;
|
||
height: calc(100% - 8px);
|
||
background: white;
|
||
border-radius: 50px;
|
||
transition: all 0.3s cubic-bezier(0.2, 0.9, 0.4, 1.2);
|
||
top: 4px;
|
||
left: 4px;
|
||
box-shadow: 0 3px 6px rgba(0,0,0,0.1);
|
||
}
|
||
.switch-opt {
|
||
flex: 1;
|
||
text-align: center;
|
||
padding: 8px 0;
|
||
z-index: 2;
|
||
font-weight: 500;
|
||
font-size: 14px;
|
||
}
|
||
|
||
canvas {
|
||
border-radius: 28px;
|
||
max-width: 100%;
|
||
height: auto;
|
||
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08);
|
||
background: #fff;
|
||
}
|
||
|
||
.preview-container, #canvas-box {
|
||
text-align: center;
|
||
margin: 18px 0;
|
||
}
|
||
|
||
|
||
#log-box {
|
||
background: #f1f4f9;
|
||
border-radius: 32px;
|
||
padding: 16px;
|
||
font-size: 12px;
|
||
font-family: monospace;
|
||
border: 1px solid #e4e9f0;
|
||
margin-top: 24px;
|
||
}
|
||
|
||
|
||
.editor-section {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 24px;
|
||
}
|
||
.ctrl-row {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 12px;
|
||
align-items: center;
|
||
margin-bottom: 12px;
|
||
}
|
||
hr {
|
||
margin: 12px 0;
|
||
border: none;
|
||
height: 1px;
|
||
background: linear-gradient(to right, #e2e8f0, transparent);
|
||
}
|
||
@media (max-width: 500px) {
|
||
body { padding: 12px; }
|
||
button { padding: 8px 14px; }
|
||
}
|
||
|
||
.image-adjustments {
|
||
padding: 24px;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
|
||
.image-adjustments h3 {
|
||
color: #333;
|
||
font-size: 1.3rem;
|
||
font-weight: 600;
|
||
margin: 0 0 20px 0;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
.adjustment-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 15px;
|
||
padding: 12px 0;
|
||
border-bottom: 1px solid #e5e7eb;
|
||
}
|
||
|
||
|
||
.adjustment-row label {
|
||
color: #4b5563;
|
||
font-weight: 500;
|
||
font-size: 0.95rem;
|
||
min-width: 70px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
}
|
||
|
||
|
||
.adjustment-value {
|
||
background: #f3f4f6;
|
||
color: #374151;
|
||
padding: 4px 10px;
|
||
border-radius: 20px;
|
||
font-size: 0.85rem;
|
||
font-weight: 600;
|
||
min-width: 45px;
|
||
text-align: center;
|
||
font-family: monospace;
|
||
}
|
||
|
||
|
||
.adjustment-row input[type="range"] {
|
||
flex: 1;
|
||
height: 4px;
|
||
|
||
background: #e5e7eb;
|
||
border-radius: 10px;
|
||
outline: none;
|
||
cursor: pointer;
|
||
}
|
||
|
||
|
||
.adjustment-row input[type="range"]::-webkit-slider-runnable-track {
|
||
height: 4px;
|
||
background: #e5e7eb;
|
||
border-radius: 10px;
|
||
}
|
||
|
||
|
||
.adjustment-row input[type="range"]::-webkit-slider-thumb {
|
||
-webkit-appearance: none;
|
||
width: 16px;
|
||
height: 16px;
|
||
background: #3b82f6;
|
||
border-radius: 50%;
|
||
margin-top: -6px;
|
||
cursor: pointer;
|
||
transition: all 0.2s ease;
|
||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.adjustment-row input[type="range"]::-webkit-slider-thumb:hover {
|
||
transform: scale(1.2);
|
||
background: #2563eb;
|
||
}
|
||
|
||
|
||
.adjustment-row input[type="range"]::-moz-range-track {
|
||
height: 4px;
|
||
background: #e5e7eb;
|
||
border-radius: 10px;
|
||
}
|
||
|
||
.adjustment-row input[type="range"]::-moz-range-thumb {
|
||
width: 16px;
|
||
height: 16px;
|
||
background: #3b82f6;
|
||
border-radius: 50%;
|
||
cursor: pointer;
|
||
border: none;
|
||
transition: all 0.2s ease;
|
||
}
|
||
|
||
.adjustment-row input[type="range"]::-moz-range-thumb:hover {
|
||
transform: scale(1.2);
|
||
background: #2563eb;
|
||
}
|
||
|
||
|
||
@media (max-width: 768px) {
|
||
.adjustment-row {
|
||
flex-wrap: wrap;
|
||
gap: 10px;
|
||
}
|
||
|
||
.adjustment-row input[type="range"] {
|
||
min-width: 400px;
|
||
max-width: 80%;
|
||
order: 1;
|
||
}
|
||
|
||
.adjustment-value {
|
||
order: 2;
|
||
}
|
||
}
|
||
|
||
#log-box {
|
||
background-color: #1e1e1e;
|
||
border-radius: 8px;
|
||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||
font-family: 'Courier New', 'Fira Code', 'Monaco', monospace;
|
||
font-size: 14px;
|
||
color: #d4d4d4;
|
||
margin: 30px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
|
||
#log-box > :first-child {
|
||
display: block;
|
||
background-color: #2d2d2d;
|
||
padding: 12px 16px;
|
||
margin: 0;
|
||
border-bottom: 1px solid #3c3c3c;
|
||
font-weight: 600;
|
||
color: #cccccc;
|
||
letter-spacing: 0.5px;
|
||
}
|
||
|
||
|
||
#log {
|
||
height: 300px;
|
||
overflow-y: auto;
|
||
padding: 12px 16px;
|
||
background-color: #1e1e1e;
|
||
line-height: 1.5;
|
||
white-space: pre-wrap;
|
||
word-break: break-word;
|
||
}
|
||
|
||
|
||
#log::-webkit-scrollbar {
|
||
width: 8px;
|
||
}
|
||
|
||
#log::-webkit-scrollbar-track {
|
||
background: #2d2d2d;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
#log::-webkit-scrollbar-thumb {
|
||
background: #555;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
#log::-webkit-scrollbar-thumb:hover {
|
||
background: #777;
|
||
}
|
||
|
||
|
||
#log > * {
|
||
margin: 4px 0;
|
||
padding: 4px 0;
|
||
border-bottom: 1px solid #2a2a2a;
|
||
font-family: inherit;
|
||
}
|
||
|
||
|
||
#log > .error {
|
||
color: #f48771;
|
||
}
|
||
|
||
#log > .warning {
|
||
color: #dcdcaa;
|
||
}
|
||
|
||
#log > .info, #log > .success {
|
||
color: #9cdcfe;
|
||
}
|
||
|
||
|
||
.log-timestamp {
|
||
color: #6a9955;
|
||
margin-right: 12px;
|
||
user-select: none;
|
||
}
|
||
|
||
|
||
#log:empty::before {
|
||
content: "暂无日志消息";
|
||
display: block;
|
||
color: #6c6c6c;
|
||
font-style: italic;
|
||
text-align: center;
|
||
padding: 20px 0;
|
||
}
|
||
|
||
|
||
#log > *:hover {
|
||
background-color: #2a2a2a;
|
||
transition: background-color 0.2s ease;
|
||
}
|
||
</style>
|
||
<style>
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
|
||
.dashboard {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
justify-content: center;
|
||
align-items: flex-start;
|
||
gap: 28px;
|
||
max-width: 1480px;
|
||
width: 100%;
|
||
}
|
||
|
||
.canvas-area {
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.canvas-stage {
|
||
width: 600px;
|
||
height: auto;
|
||
max-width: 800px;
|
||
background: #ffffff;
|
||
border-radius: 16px;
|
||
box-shadow: 0 20px 35px -10px rgba(0,0,0,0.6);
|
||
overflow: hidden;
|
||
|
||
position: relative;
|
||
}
|
||
|
||
canvas {
|
||
display: block;
|
||
width: 100%;
|
||
height: 100%;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.editor-panel {
|
||
flex: 1;
|
||
min-width: 360px;
|
||
max-width: 600px;
|
||
background: #12121a;
|
||
border-radius: 28px;
|
||
padding: 20px 22px 24px;
|
||
border-left: 6px solid #FF0000;
|
||
box-shadow: 0 12px 28px rgba(0,0,0,0.5);
|
||
}
|
||
|
||
.panel-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
flex-wrap: wrap;
|
||
gap: 12px;
|
||
margin-bottom: 16px;
|
||
border-bottom: 1px solid #FF000044;
|
||
padding-bottom: 12px;
|
||
}
|
||
|
||
.panel-header h2 {
|
||
color: #FF0000;
|
||
font-size: 20px;
|
||
letter-spacing: 2px;
|
||
}
|
||
|
||
.template-buttons {
|
||
margin-bottom: 10px;
|
||
display: flex;
|
||
gap: 16px;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.temp-btn {
|
||
background: transparent;
|
||
border: 1.2px solid #FF0000;
|
||
color: #FF0000;
|
||
font-family: '微软雅黑', monospace;
|
||
font-size: 18px;
|
||
padding: 5px 12px;
|
||
border-radius: 40px;
|
||
cursor: pointer;
|
||
transition: 0.2s;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.temp-btn.active {
|
||
background: #FF0000;
|
||
color: #000000;
|
||
box-shadow: 0 0 8px #ff0000aa;
|
||
}
|
||
|
||
.title-section {
|
||
background: #1a1a24;
|
||
border-radius: 28px;
|
||
padding: 10px 16px;
|
||
margin-bottom: 18px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
flex-wrap: wrap;
|
||
border: 1px solid #FF000044;
|
||
}
|
||
.title-label {
|
||
color: #FF0000;
|
||
font-weight: bold;
|
||
font-size: 12px;
|
||
letter-spacing: 1px;
|
||
}
|
||
#globalTitleInput {
|
||
flex: 2;
|
||
background: #0b0b12;
|
||
border: 1px solid #FF0000;
|
||
border-radius: 40px;
|
||
padding: 8px 16px;
|
||
color: #fff;
|
||
font-family: '微软雅黑', monospace;
|
||
font-size: 13px;
|
||
outline: none;
|
||
}
|
||
|
||
/* 自定义文本 & 二维码专用区域 */
|
||
.custom-zone, .qrcode-zone {
|
||
background: #1c1c26;
|
||
border-radius: 24px;
|
||
padding: 16px;
|
||
margin: 12px 0 16px;
|
||
border: 1px solid #FF000044;
|
||
transition: 0.2s;
|
||
}
|
||
.zone-label {
|
||
color: #FF0000;
|
||
font-size: 12px;
|
||
font-weight: bold;
|
||
margin-bottom: 12px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
.custom-textarea {
|
||
width: 100%;
|
||
background: #0b0b12;
|
||
border: 1px solid #FF0000;
|
||
border-radius: 20px;
|
||
padding: 14px;
|
||
color: #f0f0f0;
|
||
font-family: '微软雅黑', monospace;
|
||
font-size: 13px;
|
||
resize: vertical;
|
||
line-height: 1.5;
|
||
outline: none;
|
||
min-height: 100px;
|
||
}
|
||
.qr-input-row {
|
||
display: flex;
|
||
gap: 10px;
|
||
margin-bottom: 12px;
|
||
flex-wrap: wrap;
|
||
}
|
||
.qr-input-row input {
|
||
flex: 2;
|
||
background: #0b0b12;
|
||
border: 1px solid #FF0000;
|
||
border-radius: 40px;
|
||
padding: 8px 16px;
|
||
color: #fff;
|
||
font-size: 12px;
|
||
outline: none;
|
||
}
|
||
.qr-input-row button {
|
||
background: #FF0000;
|
||
border: none;
|
||
color: #000;
|
||
font-weight: bold;
|
||
border-radius: 40px;
|
||
padding: 6px 16px;
|
||
cursor: pointer;
|
||
}
|
||
.style-row {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 17px;
|
||
margin: 24px 0 14px;
|
||
align-items: center;
|
||
}
|
||
.style-chip {
|
||
background: #0a0a10;
|
||
border-radius: 32px;
|
||
padding: 4px 12px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
.style-chip label {
|
||
font-size: 12px;
|
||
color: #ccc;
|
||
}
|
||
.style-chip select, .style-chip input {
|
||
background: #2a2a34;
|
||
border: 1px solid #FF0000;
|
||
color: #FF0000;
|
||
border-radius: 20px;
|
||
padding: 8px 12px;
|
||
font-size: 12px;
|
||
font-family: monospace;
|
||
}
|
||
.style-chip input {
|
||
width: 58px;
|
||
text-align: center;
|
||
}
|
||
.auto-hint {
|
||
font-size: 9px;
|
||
color: #FF0000;
|
||
text-align: right;
|
||
margin-top: 6px;
|
||
}
|
||
.preset-hint {
|
||
background: #1a1a24;
|
||
border-radius: 20px;
|
||
padding: 10px 14px;
|
||
margin: 12px 0 8px;
|
||
font-size: 10px;
|
||
color: #aaa;
|
||
text-align: center;
|
||
border: 1px dashed #FF000044;
|
||
}
|
||
.action-global {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
gap: 12px;
|
||
margin-top: 12px;
|
||
}
|
||
.global-btn {
|
||
background: #00000055;
|
||
border: 1px solid #FF0000;
|
||
color: #FF0000;
|
||
padding: 5px 14px;
|
||
border-radius: 40px;
|
||
font-family: '微软雅黑', monospace;
|
||
font-weight: bold;
|
||
font-size: 18px;
|
||
cursor: pointer;
|
||
transition: 0.2s;
|
||
}
|
||
.global-btn:hover {
|
||
background: #FF0000;
|
||
color: #000;
|
||
}
|
||
.tip-note {
|
||
font-size: 9px;
|
||
text-align: right;
|
||
color: #aaa;
|
||
margin-top: 16px;
|
||
border-top: 1px solid #2a2a32;
|
||
padding-top: 10px;
|
||
}
|
||
.tip-note span {
|
||
color: #FF0000;
|
||
}
|
||
@media (max-width: 860px) {
|
||
.dashboard { flex-direction: column; align-items: center; }
|
||
.editor-panel { max-width: 520px; width: 100%; }
|
||
}
|
||
|
||
/* 模态框增强 */
|
||
.modal-mask {
|
||
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
|
||
background: rgba(0,0,0,0.85); backdrop-filter: blur(4px);
|
||
display: flex; align-items: center; justify-content: center; z-index: 2000;
|
||
}
|
||
.modal-card {
|
||
background: #1a1a24; border-radius: 32px; width: 400px; max-width: 90vw;
|
||
padding: 24px; border-left: 6px solid #FF0000; box-shadow: 0 25px 45px rgba(0,0,0,0.6);
|
||
}
|
||
.modal-card h3 { color: #FF0000; margin-bottom: 18px; font-size: 20px; text-align: center; }
|
||
.modal-field { margin-bottom: 14px; }
|
||
.modal-field label { display: block; color: #ddd; font-size: 12px; margin-bottom: 6px; font-weight: bold; }
|
||
.modal-field input, .modal-field select {
|
||
width: 100%; background: #0b0b12; border: 1px solid #FF0000; border-radius: 40px;
|
||
padding: 10px 14px; color: white; font-family: monospace; font-size: 13px; outline: none;
|
||
}
|
||
.modal-buttons { display: flex; justify-content: flex-end; gap: 12px; margin-top: 22px; }
|
||
.modal-buttons button { background: #FF0000; color: #000; border: none; padding: 6px 18px; border-radius: 40px; font-weight: bold; cursor: pointer; }
|
||
.modal-buttons button.cancel { background: #333; color: #FF0000; }
|
||
.course-grid-btn { margin-top: 8px; background: #FF000022; border: 1px solid #FF0000; border-radius: 28px; padding: 6px; font-size: 14px; text-align: center; cursor: pointer; color: #FF0000; }
|
||
</style>
|
||
</head>
|
||
|
||
<body>
|
||
|
||
<div class="tabs-mobile" id="tabBar">
|
||
<button class="tab-btn active" data-tab="tab-settings">📡 设备</button>
|
||
<button class="tab-btn" data-tab="tab-countdown">⏳ 倒计时</button>
|
||
<button class="tab-btn" data-tab="tab-image">🖼️ 传图</button>
|
||
<button class="tab-btn" data-tab="tab-editor">🎨 模板</button>
|
||
</div>
|
||
|
||
|
||
<div id="tab-settings" class="tab-pane active">
|
||
<h2>📡 墨水屏·蓝牙智控</h2>
|
||
<div class="button-group">
|
||
<button id="connectbutton" onclick="preConnect();">🔍 搜索设备</button>
|
||
<button onclick="reConnect();">🔄 重新链接</button>
|
||
<button onclick="document.getElementById('log').innerHTML = '';">🗑️ 清空日志</button>
|
||
<a href="http://4638e813e4.qicp.vip:8889/GuJian/file_down.php" target="_blank"><button>📥 下载固件</button></a>
|
||
</div>
|
||
<div class="button-group">
|
||
<h1>🎭>切换为三色屏幕或者黑白屏幕</h1>
|
||
<button onclick="setri('2300')">🎳 三色屏幕</button>
|
||
<button onclick="setri('2301')">🎱 黑白屏幕</button>
|
||
</div>
|
||
<div class="button-group">
|
||
<button id="time-setter" onclick="setTime()">⏰ 设置时间</button>
|
||
<button onclick="setri('14')">🕛 12/24小时制</button>
|
||
</div>
|
||
|
||
<div class="button-group">
|
||
|
||
|
||
<div class="button-group" >
|
||
<h1>🕒 时钟模式:</h1>
|
||
<button onclick="setri('e10201')">⏰模式一</button>
|
||
<button onclick="setri('e10202')">⌚ 模式二</button>
|
||
<button onclick="setri('e10203')">🕒 模式三</button>
|
||
|
||
</div>
|
||
<div class="button-group" >
|
||
<h1>📆 日历模式:</h1>
|
||
<button onclick="setri('e10103')">📅 模式一</button>
|
||
<button onclick="setri('e10104')">📆 模式二</button>
|
||
<button onclick="setri('e10105')">⌛ 模式三</button>
|
||
|
||
</div>
|
||
|
||
<div class="button-group" >
|
||
<h1>🖼️ 图片模式:</h1>
|
||
<button onclick="setri('e10000')">🖼️直接显示已上传的图片</button>
|
||
|
||
<!-- <button onclick="setri('e10000')">🖼️图一</button>
|
||
<button onclick="setri('e10001')">🖼️ 图二</button>
|
||
<button onclick="setri('e10002')">🖼️ 图三</button>
|
||
<button onclick="triggerRxTxCmd('e10003')">🖼️ 图四</button> -->
|
||
</div>
|
||
</div>
|
||
|
||
<div class="button-group">
|
||
<button onclick="triggerRxTxCmd('e3')">⚫ 反色模式</button>
|
||
|
||
<button onclick="setri('e4')">🎨 时钟字体</button>
|
||
<button onclick="setri('15')">🌈时钟颜色</button>
|
||
<button onclick="triggerRxTxCmd('E2')">🌌 强制刷新</button>
|
||
</div>
|
||
<div class="button-group">
|
||
<button onclick="triggerEpdRed_lut(document.getElementById('cmdlut_red').value)">✍️ 校准参数</button>
|
||
<button onclick="setri('e5')">🔄 旋转180°</button>
|
||
<input type="text" id="cmdlut_red" placeholder="以16进制输入。设置红色01到0f,设置黑色10到f0。越大颜色越深" style="flex:2">
|
||
|
||
</div>
|
||
<div class="button-group">
|
||
|
||
<h1>💤 休眠时段</h1>
|
||
<input type="number" id="D_S_hour" placeholder="开始休眠小时" value="0" min="0" max="23" style="width:100px">
|
||
<h1>:时至</h1>
|
||
<input type="number" id="D_S_min" placeholder="结束休眠小时" value="0" min="0" max="23" style="width:100px">
|
||
<h1>:时</h1>
|
||
<button onclick="triggerRxTxCmd_XM('FB01')">🌙 打开休眠</button>
|
||
<button onclick="triggerRxTxCmd_XM('FB00')">☀️ 关闭休眠</button>
|
||
|
||
|
||
</div>
|
||
<!-- <div class="button-group">
|
||
<h1>🧮>设置图片轮播模式</h1>
|
||
<h1>🔗 设置轮播间隔从1到240:</h1>
|
||
<input type="number" id="L_B_NUM" value="1" min="1" max="240" style="width:170px">
|
||
<button onclick="triggerRxTxCmd_LB('01')">📟 启用分钟制</button>
|
||
<button onclick="triggerRxTxCmd_LB('00')">🎡 启用小时制</button>
|
||
</div> -->
|
||
<div class="button-group">
|
||
🚗 停车牌号码:<input type="text" id="CP" placeholder="输入号码" style="flex:1">
|
||
<button onclick="triggerEpdCHEPAI(document.getElementById('CP').value)">设置显示</button>
|
||
</div>
|
||
<div class="button-group">
|
||
🔑 激活码:<input type="text" id="cmdJH" placeholder="输入激活码" style="flex:1">
|
||
<button onclick="triggerEpdJH(document.getElementById('cmdJH').value)">激活</button>
|
||
<a href="https://qbsg.top/" target="_blank"><button>🔑自助获取激活码(或者添加固件作者:2549294317微信)</button></a>
|
||
</div>
|
||
<div class="button-group">
|
||
🛸高级命令输入:<input type="text" id="cmdcmd" placeholder="填写命令" style="flex:1">
|
||
<button onclick="triggerRxTxCmd(document.getElementById('cmdcmd').value)">发送</button>
|
||
|
||
</div>
|
||
<div class="button-group">
|
||
🛸WIFI名称和密码:<input type="text" id="wifissd" placeholder="WIFI名称" style="flex:1">
|
||
<input type="text" id="wifipass" placeholder="WIFI密码" style="flex:1">
|
||
<input type="text" id="wificity" placeholder="天气城市" style="flex:1">
|
||
<button onclick=" sendHexString(document.getElementById('wifissd').value,document.getElementById('wifipass').value,document.getElementById('wificity').value)">配置WIFI</button>
|
||
|
||
</div>
|
||
<div "style="display:none">
|
||
|
||
<input type="text" id="fixedId" placeholder="用户ID" style="display:none">
|
||
<button id="fullAutoActivateBtn" style="display:none">⚡ 一键完整激活</button>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<div id="tab-countdown" class="tab-pane ">
|
||
|
||
<h1>📅倒计时先选择日期,再填写前缀,最后选择界面!</h1>
|
||
|
||
|
||
<div class="button-group">
|
||
<h2>📆选择终止日期:</h2>
|
||
<input type="date" id="datePicker">
|
||
</div>
|
||
<div class="button-group">
|
||
<h2>📝 填写前缀文字(时钟最多16个日历最多8个):</h2>
|
||
<input type="text" id="textInput" maxlength="16" value="距离成为首富还有" placeholder="请输入1-16个字符">
|
||
|
||
</div>
|
||
|
||
|
||
<h1>💟选择显示倒计时的界面</h1>
|
||
<div style="background: #e0e0e0; padding: 0.3rem; border-radius: 50px; display: flex; margin: 0.8rem 0; position: relative; cursor: pointer;" onclick="toggleSwitch(event)">
|
||
<div id="switchBg" style="position: absolute; width: 50%; height: 100%; background: white; border-radius: 50px; top: 0; left: 0; transition: 0.3s; box-shadow: 0 2px 5px rgba(0,0,0,0.2);"></div>
|
||
|
||
<div style="flex: 1; text-align: center; padding: 0.8rem; position: relative; z-index: 1;" id="opt16">⏰ 时钟倒计时界面</div>
|
||
<div style="flex: 1; text-align: center; padding: 0.8rem; position: relative; z-index: 1;" id="opt24">📅 日历倒计时界面</div>
|
||
</div>
|
||
|
||
|
||
<div class="input-group" style="display:none">
|
||
<label for="gridSizeSelect">倒计时界面选择</label>
|
||
<select id="gridSizeSelect">
|
||
<option value="16">时钟计时界面</option>
|
||
<option value="24">日历计时界面</option>
|
||
|
||
</select>
|
||
<div><span id="currentGridSize"></span></div>
|
||
</div>
|
||
<h1>🚧调整设置文字的字体和大小</h1>
|
||
<div class="button-group">
|
||
|
||
<h1>字体选择(电脑端生效)</h1>
|
||
<select id="fontFamily">
|
||
<option value="Arial">Arial</option>
|
||
<option value="SimSun" selected="">宋体</option>
|
||
<option value="Microsoft YaHei">微软雅黑</option>
|
||
<option value="SimHei">黑体</option>
|
||
<option value="KaiTi">楷体</option>
|
||
</select>
|
||
|
||
|
||
|
||
|
||
<h1>🔠字体大小 (50%-150%)</h1>
|
||
<input type="range" id="fontSizeSlider" min="50" max="150" value="100">
|
||
<span class="slider-value" id="fontSizeValue">100%</span>
|
||
|
||
<small style="color: #7f8c8d;">调节字体的显示比例,过大可能导致字符截断</small>
|
||
|
||
</div>
|
||
|
||
<div class="options" style="display:none">
|
||
<div class="option-item">
|
||
<input type="checkbox" id="invertColors" checked="">
|
||
<label for="invertColors">反色显示</label>
|
||
</div>
|
||
<div class="option-item" style="display:none">
|
||
<input type="checkbox" id="showGrid" checked="">
|
||
<label for="showGrid">显示网格</label>
|
||
</div>
|
||
</div>
|
||
<div class="preview-container">
|
||
<canvas id="previewCanvas" style="max-height: 300px; width: auto; display: block; margin-left: auto; margin-right: auto;"></canvas>
|
||
<div class="grid-info" id="gridInfoText"></div>
|
||
</div>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<h1>🚀开始将倒计时发送到墨水屏时钟</h1>
|
||
<div class="button-group">
|
||
<button id="generateBtn">✨启动倒计时日期</button>
|
||
<button class="copy-btn" id="upload_rili_text">📅设置日历中文字</button>
|
||
<button class="copy-btn" id="copyBtn">🔒关闭倒计时日期</button>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
|
||
<div id="tab-image" class="tab-pane ">
|
||
<h1>📤上传图片到屏幕</h1>
|
||
|
||
<div class="button-group">
|
||
<h1>📂上传图片:</h1>
|
||
<input type="file" id="image_file" onchange="update_image1()" accept=".png,.jpg,.bmp,.webp,.jpeg">
|
||
|
||
<h1>📱 屏幕尺寸:</h1>
|
||
<select id="screen-size" onchange="updateCanvasSize()">
|
||
<option value="4.2传图">4.2传图</option>
|
||
<option value="日历小图">4.2日历小图</option>
|
||
<option value="7.5传图">7.5传图</option>
|
||
<option value="7.5日历小图">7.5日历小图</option>
|
||
<option value="2.9传图">2.9传图</option>
|
||
<option value="2.13传图">2.13传图</option>
|
||
<option value="2.13高分传图">2.13高分传图</option>
|
||
</select>
|
||
|
||
|
||
|
||
<h1>👑抖动算法:</h1>
|
||
<select id="dithering" title="🎨抖动算法">
|
||
<optgroup label="黑白红三色">
|
||
<option value="bwr_none">黑白红不采用算法</option>
|
||
<option value="bwr_floydsteinberg">黑白红Floyd-Steinberg</option>
|
||
<option value="bwr_atkinson" selected>黑白红Atkinson</option>
|
||
<option value="bwr_bayer">黑白红Bayer</option>
|
||
<option value="bwr_stucki">黑白红Stucki</option>
|
||
<option value="bwr_jarvis">黑白红Jarvis-Judice-Ninke</option>
|
||
</optgroup>
|
||
<optgroup label="黑白">
|
||
<option value="none">不采用算法</option>
|
||
<option value="floydsteinberg">Floyd-Steinberg</option>
|
||
<option value="atkinson">Atkinson</option>
|
||
<option value="bayer">Bayer</option>
|
||
<option value="stucki">Stucki</option>
|
||
<option value="jarvis">Jarvis-Judice-Ninke</option>
|
||
</optgroup>
|
||
</select>
|
||
|
||
|
||
|
||
<h1>⚫阈值:</h1><input type="range" max="255" min="10" value="125" id="threshold">
|
||
</div>
|
||
|
||
<h1>🍕修改图片尺寸角度等参数</h1>
|
||
<div class="button-group">
|
||
<button onclick="resetAll()">✨重置图像设置</button>
|
||
<button onclick="stretchToCanvas()">📐适应尺寸</button>
|
||
<button onclick="updateScale('100')">1️⃣缩放到100%</button>
|
||
<button onclick="rotateImage(90)">↻顺时针旋转90°</button>
|
||
<button onclick="rotateImage(-90)">↺逆时针旋转90°</button>
|
||
<button onclick="rotateImage(0)">⤾旋转到0°</button>
|
||
</div>
|
||
<h1>🍳对图像的显示效果进行微调</h1>
|
||
<div class="button-group">
|
||
<canvas id="canvas" width="400" height="300" style="border: black solid 1px; width: 100%; height: auto; max-width: 800px;"></canvas>
|
||
|
||
|
||
<div class="image-adjustments">
|
||
<h3>🎛️图像调整</h3>
|
||
<div class="adjustment-row">
|
||
<label for="brightness">🔆亮度:</label>
|
||
<span class="adjustment-value" id="brightnessValue">0</span>
|
||
<input type="range" id="brightness" min="-100" max="100" value="0" style="width: 100px">
|
||
|
||
</div>
|
||
<div class="adjustment-row">
|
||
<label for="contrast">🥨对比度:</label>
|
||
<span class="adjustment-value" id="contrastValue">0</span>
|
||
<input type="range" id="contrast" min="0" max="100" value="10">
|
||
|
||
</div>
|
||
<div class="adjustment-row">
|
||
<label for="saturation">🍳饱和度:</label>
|
||
<span class="adjustment-value" id="saturationValue">35</span>
|
||
<input type="range" id="saturation" min="0" max="100" value="35">
|
||
|
||
</div>
|
||
<div class="adjustment-row">
|
||
<label for="diffusion">💢扩散强度:</label>
|
||
<span class="adjustment-value" id="diffusionValue">100</span>
|
||
<input type="range" id="diffusion" min="0" max="100" value="100">
|
||
|
||
</div>
|
||
<div class="adjustment-row">
|
||
🔄旋转角度:<span id="rotationValue">0°</span><input type="range" id="rotationSlider" min="0" max="360" value="0" oninput="updateRotation(this.value)">
|
||
</div>
|
||
<div class="adjustment-row">
|
||
<label>🔍缩放比例: <span id="scaleValue">100%</span></label>
|
||
<input type="range" id="scaleSlider" min="10" max="500" value="100" oninput="updateScale(this.value)">
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
<h1>🚀将设置好的图片上传到设备</h1>
|
||
<div class="button-group">
|
||
|
||
<button onclick=" upload_image()" style="font-weight: bold">📡上传到图片</button>
|
||
|
||
<!-- <button onclick="upload_image_lb(0)" style="font-weight: bold">📡上传到图片一</button>
|
||
<button onclick="upload_image_lb(1)" style="font-weight: bold">📡上传到图片二</button>
|
||
<button onclick="upload_image_lb(2)" style="font-weight: bold">📡上传到图片三</button>
|
||
<button onclick="upload_image_lbs(3)" style="font-weight: bold">📡上传到图片四</button>
|
||
</div>
|
||
|
||
<div class="button-group">
|
||
<h1>🛸轮播数量输入:</h1> <input type="text"min="0" max="4" value="4" id="lbnum" placeholder="设置轮播数量" style="flex:1">
|
||
<button onclick="upload_image_lb_num(document.getElementById('lbnum').value)">点击设置图片轮播数量(最多四个)</button>
|
||
-->
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<div id="tab-editor" class="tab-pane ">
|
||
<div class="button-group">
|
||
<div class="canvas-area">
|
||
<div class="canvas-stage">
|
||
<canvas id="unifiedCanvas" width="400" height="300" style="border: black solid 1px; width: 100%; height: auto; max-width: 800px;"></canvas>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="editor-panel">
|
||
|
||
<div class="panel-header">
|
||
<h2>◉ 模板设计·六版 注释:中文符号【】内的文字为红色!</h2>
|
||
<div class="template-buttons">
|
||
<button class="temp-btn" data-template="schedule">📅 日程</button>
|
||
<button class="temp-btn" data-template="businesscard">📇 名片</button>
|
||
<button class="temp-btn" data-template="memo">📋 备忘录</button>
|
||
<button class="temp-btn" data-template="course">📚 课程表</button>
|
||
<button class="temp-btn" data-template="qrcode">📱 二维码</button>
|
||
<button class="temp-btn" data-template="customText">✨ 自定义</button>
|
||
<div class="style-chip">
|
||
<label>屏幕尺寸</label>
|
||
<select id="epdwh">
|
||
<option value="400x300">400x300</option>
|
||
<option value="800x480">800x480</option>
|
||
<option value="296x128">296x128</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="title-section">
|
||
<span class="title-label">📌 画布标题</span>
|
||
<input type="text" id="globalTitleInput" placeholder="置顶标题" value="◉ 输入内容·页眉">
|
||
</div>
|
||
|
||
|
||
<div id="customBlock" class="custom-zone" style="display: none;">
|
||
<div class="zone-label">✍️ 自由文本输入 · 自动换行</div>
|
||
<textarea id="freeTextArea" class="custom-textarea" placeholder="输入任意文字,支持换行,自动换行完整显示……"></textarea>
|
||
<div class="style-row">
|
||
<div class="style-chip"><label>大小</label><input type="number" id="customFontSize" value="17" min="10" max="52" step="1"></div>
|
||
<div class="style-chip"><label>字体</label><select id="customFontFamily"></select></div>
|
||
<div class="style-chip"><label>颜色</label><select id="customBaseColor"><option value="#000000">黑</option><option value="#FF0000">红</option></select></div>
|
||
<div class="style-chip"><label>反色</label><select id="customInvertMode"></select></div>
|
||
<div class="style-chip"><label>对齐</label><select id="customAlign"><option value="left">左</option><option value="center" selected>中</option><option value="right">右</option></select></div>
|
||
|
||
</label>
|
||
</div>
|
||
<div class="auto-hint">⚡ 输入或修改样式实时更新画布,字体选项只有电脑端生效!</div>
|
||
</div>
|
||
|
||
|
||
<div id="qrcodeBlock" class="qrcode-zone" style="display: none;">
|
||
<div class="zone-label">🔲 二维码内容 & 下方文字</div>
|
||
<div class="qr-input-row">
|
||
<input type="text" id="qrContentInput" placeholder="输入文本/网址,生成二维码" value="https://mspppclock.tech/">
|
||
<button id="generateQRBtn">生成二维码</button>
|
||
</div>
|
||
<div class="style-row">
|
||
<div class="style-chip"><label>二维码大小</label><input type="number" id="qrSizeInput" value="150" min="50" max="200"></div>
|
||
</div>
|
||
<div class="zone-label" style="margin-top: 8px;">📝 二维码下方文字 (点击可编辑/添加)</div>
|
||
<textarea id="qrCaptionText" class="custom-textarea" placeholder="点击下方文字可编辑,点击空白区域添加新行……" rows="2" style="min-height: 60px;">扫码访问官网</textarea>
|
||
<div class="auto-hint">💡 点击画布中的文字行可编辑,点击空白区域添加说明行</div>
|
||
</div>
|
||
|
||
|
||
<div id="courseBlock" class="qrcode-zone" style="display: none;">
|
||
<div class="zone-label">📚 课程表设置</div>
|
||
<div class="style-row">
|
||
<div class="style-chip"><label>周天数</label><input type="number" id="courseDaysCount" value="5" min="3" max="7"></div>
|
||
<div class="style-chip"><label>节数</label><input type="number" id="coursePeriodsCount" value="4" min="2" max="9"></div>
|
||
</div>
|
||
<div class="course-grid-btn" id="applyCourseSettingBtn">应用设置(重新生成课程表)</div>
|
||
</div>
|
||
|
||
|
||
<div id="presetHintBlock" class="preset-hint" style="display: none;">
|
||
💡 提示:<span style="color:#FF0000;">点击画布文字行 → 编辑该行内容</span> |
|
||
<span style="color:#FF0000;">点击空白区域 → 直接添加新行</span>
|
||
<span style="display:inline-block; margin-left:10px;">📚 课程表:点击单元格编辑课程</span>
|
||
</div>
|
||
|
||
<div class="action-global">
|
||
<button id="forceRefreshBtn" class="global-btn">⟳ 刷新</button>
|
||
<button id="resetCurrentBtn" class="global-btn">↺ 重置当前模板</button>
|
||
</div>
|
||
<div class="tip-note">
|
||
<span>◉ 日程/名片/备忘录/课程表</span> 支持点击文字编辑、空白加行 | <span>二维码</span> 可生成黑白红二维码,下方文字互动 | <span>自定义文本</span> 自由换行
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<h1>🚀将设置好的模板上传到设备</h1>
|
||
<div class="button-group">
|
||
|
||
<!-- <button onclick="upload_image_moban(0)" style="font-weight: bold">📡上传到模板一</button>
|
||
<button onclick="upload_image_moban(1)" style="font-weight: bold">📡上传到模板二</button>
|
||
<button onclick="upload_image_moban(2)" style="font-weight: bold">📡上传到模板三</button>
|
||
<button onclick="upload_image_moban(3)" style="font-weight: bold">📡上传到模板四</button>
|
||
-->
|
||
<button onclick="upload_image_moban(0)" style="font-weight: bold">📡上传到模板</button>
|
||
|
||
</div>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<div id="log-box">
|
||
日志:
|
||
<br>
|
||
<div id="log"></div>
|
||
</div>
|
||
|
||
|
||
<script src="switch2.js"></script>
|
||
<script src="ble.js"></script>
|
||
|
||
<script src="hex.js"></script>
|
||
<script src="time.js"></script>
|
||
<script src="timedjs.js"></script>
|
||
<script src="timedjs2.js"></script>
|
||
<script src="moban.js"></script>
|
||
|
||
<script>
|
||
function toggleSwitch(e) {
|
||
const rect = e.currentTarget.getBoundingClientRect();
|
||
const clickX = e.clientX - rect.left;
|
||
|
||
|
||
if (clickX < rect.width / 2) {
|
||
// 选中时钟
|
||
switchBg.style.left = '0';
|
||
|
||
gridSizeSelect.value=16;
|
||
} else {
|
||
// 选中日历
|
||
|
||
switchBg.style.left = '50%';
|
||
gridSizeSelect.value=24;
|
||
}
|
||
|
||
drawPreview();
|
||
}
|
||
|
||
|
||
</script>
|
||
|
||
<script>
|
||
|
||
const tabs = document.querySelectorAll('.tab-btn');
|
||
const panes = document.querySelectorAll('.tab-pane');
|
||
tabs.forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
const tabId = btn.getAttribute('data-tab');
|
||
tabs.forEach(b => b.classList.remove('active'));
|
||
btn.classList.add('active');
|
||
panes.forEach(pane => {
|
||
pane.classList.remove('active');
|
||
if(pane.id === tabId) pane.classList.add('active');
|
||
});
|
||
});
|
||
});
|
||
|
||
</script>
|
||
|
||
</body>
|
||
</html> |