Files
qianbian/analysis/web/index.html
T

1310 lines
45 KiB
HTML
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="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> &nbsp;|&nbsp;
<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>