fix: 更新健康监测模块页面与文档,新增静态服务配置

This commit is contained in:
liuyunqin
2026-07-15 17:34:52 +08:00
parent ff11ee0e1c
commit c7096947e0
18 changed files with 756 additions and 472 deletions
+11 -2
View File
@@ -75,6 +75,14 @@ body { font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica
<img id="lightbox-img" src="" alt="放大预览">
</div>
<script>
/* ===== file:// 协议 → 自动跳转到本地服务器 ===== */
(function() {
if (location.protocol === 'file:') {
var search = location.search; /* 保留 ?file=...&title=... 参数 */
location.href = 'http://localhost:8080/_templates/md-viewer.html' + search;
}
})();
const params = new URLSearchParams(location.search);
const filePath = params.get('file');
const title = params.get('title');
@@ -113,7 +121,8 @@ if (title) {
}
if (filePath) {
document.getElementById('doc-path').textContent = filePath;
fetch(filePath)
/* 用绝对路径(/ 开头),避免 <base href="../"> 在不同浏览器中解析不一致 */
fetch('/' + filePath)
.then(res => {
if (!res.ok) throw new Error('文件未找到 (' + res.status + ')');
return res.text();
@@ -203,7 +212,7 @@ if (filePath) {
content.querySelectorAll('img').forEach(img => {
const src = img.getAttribute('src');
if (src && !src.startsWith('http') && !src.startsWith('/') && !src.startsWith('data:')) {
img.src = mdBase + src;
img.src = '/' + mdBase + src;
}
});
/* 绑定图片点击放大 */
+118 -6
View File
@@ -149,10 +149,40 @@ body { background: var(--background); font-family: -apple-system, BlinkMacSystem
.prd-item__status { font-size: 11px; padding: 2px 8px; border-radius: 10px; font-weight: 600; flex-shrink: 0; }
.prd-item__status--ready { background: var(--green-light); color: #389e0d; border: 1px solid var(--green-border); }
.prd-item__status--empty { background: #fffbe6; color: #d48806; border: 1px solid #ffe58f; }
</style>
</head>
<body>
<div class="header">
/* ===== file:// 协议 - 全屏启动遮罩 ===== */
.launch-overlay { display: none; position: fixed; inset: 0; z-index: 99999; background: rgba(15,23,42,0.85); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); flex-direction: column; align-items: center; justify-content: center; font-family: -apple-system,BlinkMacSystemFont,'PingFang SC','Helvetica Neue','Segoe UI',sans-serif; }
.launch-overlay--show { display: flex; }
.launch-card { background: #fff; border-radius: 20px; padding: 40px 48px; text-align: center; box-shadow: 0 24px 80px rgba(0,0,0,0.4); max-width: 480px; width: 90%; animation: popIn .35s ease; }
.launch-card__icon { width: 64px; height: 64px; border-radius: 50%; background: linear-gradient(135deg, #1677FF, #4facfe); display: flex; align-items: center; justify-content: center; margin: 0 auto 20px; font-size: 32px; color: #fff; }
.launch-card__icon--ok { background: linear-gradient(135deg, #52c41a, #95de64); }
.launch-card__title { font-size: 20px; font-weight: 700; color: #1a1a2e; margin-bottom: 8px; }
.launch-card__sub { font-size: 14px; color: #5a607f; margin-bottom: 24px; line-height: 1.6; }
.launch-card__btn { display: inline-flex; align-items: center; gap: 8px; padding: 12px 32px; font-size: 15px; font-weight: 600; color: #fff; background: linear-gradient(135deg, #1677FF, #4facfe); border: none; border-radius: 12px; cursor: pointer; text-decoration: none; transition: all .2s; box-shadow: 0 4px 16px rgba(22,119,255,0.35); }
.launch-card__btn:hover { transform: translateY(-1px); box-shadow: 0 8px 24px rgba(22,119,255,0.45); }
.launch-card__btn--outline { background: #fff; color: var(--primary); border: 1.5px solid var(--primary); box-shadow: none; }
.launch-card__btn--outline:hover { background: var(--primary-light); box-shadow: 0 4px 12px rgba(22,119,255,0.15); }
.launch-card__status { margin-top: 16px; font-size: 13px; color: var(--text-placeholder); }
.launch-card__spinner { display: inline-block; width: 16px; height: 16px; border: 2px solid #e8ecf1; border-top-color: var(--primary); border-radius: 50%; animation: spin .7s linear infinite; vertical-align: middle; margin-right: 6px; }
@keyframes spin { to { transform: rotate(360deg); } }
.launch-card__actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
</style>
</head>
<body>
<!-- 本地服务器启动遮罩 -->
<div class="launch-overlay" id="launch-overlay">
<div class="launch-card">
<div class="launch-card__icon" id="launch-icon">🚀</div>
<div class="launch-card__title" id="launch-title">需要启动本地服务器</div>
<div class="launch-card__sub" id="launch-sub">PRD文档预览等功能需要本地HTTP服务器</div>
<div class="launch-card__actions" id="launch-actions">
<a class="launch-card__btn" href="启动服务器.bat">⚡ 一键启动</a>
<a class="launch-card__btn launch-card__btn--outline" href="http://localhost:8080/index.html">📖 直接打开原型</a>
</div>
<div class="launch-card__status" id="launch-status"><span class="launch-card__spinner"></span>等待服务器就绪...</div>
</div>
</div>
<div class="header">
<div class="header__inner">
<div class="header__title">健康CQ升级项目 · 高保真交互原型</div>
<div class="header__sub">点击模块卡片跳转至对应模块主页,点击页数徽章查看全部页面,点击PRD文档在线预览详细功能说明</div>
@@ -162,8 +192,90 @@ body { background: var(--background); font-family: -apple-system, BlinkMacSystem
<div class="main-content">
<div id="tab-contents"></div>
</div>
<script>
/* ===== SVG 图标 ===== */
<script>
/* ===== file:// 协议检测 & 服务器自动启动 ===== */
(function() {
if (location.protocol !== 'file:') return; /* 非 file:// 协议,无需处理 */
var overlay = document.getElementById('launch-overlay');
var launchIcon = document.getElementById('launch-icon');
var launchTitle = document.getElementById('launch-title');
var launchSub = document.getElementById('launch-sub');
var launchStatus = document.getElementById('launch-status');
var launchActions = document.getElementById('launch-actions');
/* 步骤1: 先静默检测服务器是否已在运行(不显示遮罩) */
function checkServer(callback) {
var iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.src = 'http://localhost:8080/index.html';
var done = false;
var t = setTimeout(function() {
if (!done) { done = true; callback(false); }
}, 2000);
iframe.onload = function() {
if (!done) { done = true; clearTimeout(t); callback(true); }
};
iframe.onerror = function() {
if (!done) { done = true; clearTimeout(t); callback(false); }
};
document.body.appendChild(iframe);
}
/* 步骤2: 服务器已运行 → 无感跳转 */
function redirectToServer() {
location.replace('http://localhost:8080/index.html');
}
/* 步骤3: 显示遮罩 + 轮询 */
function showOverlay() {
overlay.classList.add('launch-overlay--show');
launchIcon.textContent = '🚀';
launchIcon.className = 'launch-card__icon';
launchTitle.textContent = '需要启动本地服务器';
launchSub.textContent = 'PRD文档预览等功能需要本地HTTP服务器,请双击项目根目录下的 启动服务器.bat';
launchStatus.innerHTML = '<span class="launch-card__spinner"></span>等待服务器就绪...';
launchActions.innerHTML = '<a class="launch-card__btn" href="启动服务器.bat">⚡ 一键启动</a> <a class="launch-card__btn launch-card__btn--outline" href="http://localhost:8080/index.html">📖 直接打开原型</a>';
/* 轮询:每2秒检测一次,最多30次(60秒) */
var attempts = 0;
var pollTimer = setInterval(function() {
attempts++;
checkServer(function(ok) {
if (ok) {
clearInterval(pollTimer);
launchIcon.textContent = '✅';
launchIcon.className = 'launch-card__icon launch-card__icon--ok';
launchTitle.textContent = '服务器已就绪';
launchSub.textContent = '即将自动跳转...';
launchStatus.innerHTML = '<a href="http://localhost:8080/index.html" style="color:var(--primary)">立即跳转</a>';
launchActions.innerHTML = '<a class="launch-card__btn launch-card__btn--outline" href="http://localhost:8080/index.html">📖 打开原型导航</a>';
setTimeout(redirectToServer, 500);
}
});
if (attempts >= 30) {
clearInterval(pollTimer);
launchTitle.textContent = '未检测到服务器';
launchSub.textContent = '请确认 启动服务器.bat 已运行,然后刷新页面';
launchStatus.innerHTML = '⏱ 等待超时(60秒)';
launchActions.innerHTML = '<button class="launch-card__btn" onclick="location.reload()">🔄 刷新重试</button>';
}
}, 2000);
}
/* === 主流程:先静默检测 === */
checkServer(function(running) {
if (running) {
/* 服务器已在运行 → 直接跳转,用户全程无感 */
redirectToServer();
} else {
/* 服务器未运行 → 显示遮罩引导手动启动 */
showOverlay();
}
});
})();
/* ===== SVG 图标 ===== */
const ICONS = {
web: '<svg class="tab-nav__icon" viewBox="0 0 18 18" fill="none"><rect x="1" y="2" width="16" height="12" rx="2" stroke="currentColor" stroke-width="1.5"/><line x1="5" y1="16" x2="13" y2="16" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><line x1="9" y1="14" x2="9" y2="16" stroke="currentColor" stroke-width="1.5"/></svg>',
app: '<svg class="tab-nav__icon" viewBox="0 0 18 18" fill="none"><rect x="4" y="1" width="10" height="16" rx="2" stroke="currentColor" stroke-width="1.5"/><line x1="7.5" y1="14" x2="10.5" y2="14" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>',
+7
View File
@@ -0,0 +1,7 @@
{
"cleanUrls": false,
"directoryListing": false,
"rewrites": [
{ "source": "/", "destination": "/index.html" }
]
}
@@ -69,11 +69,18 @@ tbody tr:hover{background:#F8FBFF;}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.detail-title{font-size:var(--font-lg);font-weight:600;margin-bottom:4px;}
.detail-meta{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:16px;}
.empty-state{text-align:center;padding:40px 20px;color:var(--text-placeholder);}
.empty-state svg{width:64px;height:64px;margin-bottom:12px;opacity:0.3;}
.empty-state__title{font-size:var(--font-sm);color:var(--text-secondary);}
/* 单位信息卡片 */
.info-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);padding:24px;margin-bottom:16px;display:flex;align-items:center;gap:32px;}
.info-card__avatar{width:56px;height:56px;border-radius:50%;background:var(--primary);color:#fff;display:flex;align-items:center;justify-content:center;font-size:20px;font-weight:600;flex-shrink:0;}
.info-card__detail{display:flex;flex-direction:column;gap:6px;}
.info-card__name{font-size:var(--font-lg);font-weight:600;color:var(--text-primary);}
.info-card__meta{display:flex;gap:24px;font-size:var(--font-sm);color:var(--text-secondary);}
.info-card__right{flex-shrink:0;margin-left:auto;}
.info-card__date-filter{display:flex;align-items:center;gap:8px;}
.info-card__date-filter label{font-size:var(--font-xs);color:var(--text-secondary);white-space:nowrap;}
</style>
</head>
<body>
@@ -126,16 +133,33 @@ tbody tr:hover{background:#F8FBFF;}
<span class="sep">/</span>
<span>健康现状</span>
</div>
<div class="detail-title" id="detailTitle"></div>
<div class="detail-meta" id="detailMeta"></div>
<!-- 单位信息卡片 -->
<div class="info-card">
<div class="info-card__detail">
<div class="info-card__name" id="unitName">采油一厂</div>
<div class="info-card__meta">
<span id="unitTotal">总人数:1280</span>
</div>
</div>
<div class="info-card__right">
<div class="info-card__date-filter">
<label>年份</label>
<select class="filter-select" id="filterYear" onchange="onYearChange()" style="height:32px;min-width:110px;font-size:var(--font-xs);">
<option value="2026">2026年</option>
<option value="2025">2025年</option>
<option value="2024">2024年</option>
</select>
</div>
</div>
</div>
<!-- Tab 切换 -->
<div class="tab-bar">
<div class="tab-item active" onclick="switchTab('a',this)">A类(人数)</div>
<div class="tab-item" onclick="switchTab('b',this)">B类(人数)</div>
<div class="tab-item" onclick="switchTab('c',this)">C类(人数)</div>
<div class="tab-item" onclick="switchTab('d',this)">D类(人数)</div>
<div class="tab-item" onclick="switchTab('e',this)">E类(人数)</div>
<div class="tab-item active" onclick="switchTab('a',this)">A类(768)</div>
<div class="tab-item" onclick="switchTab('b',this)">B类(256)</div>
<div class="tab-item" onclick="switchTab('c',this)">C类(128)</div>
<div class="tab-item" onclick="switchTab('d',this)">D类(89)</div>
<div class="tab-item" onclick="switchTab('e',this)">E类(39)</div>
</div>
<!-- A类面板 -->
@@ -511,15 +535,22 @@ function resetPanel(cat) {
renderPanel(cat, empData[cat]);
}
/* ===== 年份切换 ===== */
var currentYear = '2026';
function onYearChange(){
currentYear = document.getElementById('filterYear').value;
// 可根据年份刷新页面数据
}
/* ===== 初始化 ===== */
(function() {
var unit = getUrlParam('unit') || '采油一厂';
var dept = getUrlParam('dept') || '';
var displayName = unit + (dept ? ' - ' + dept : '');
document.getElementById('unitDept').textContent = displayName;
document.getElementById('detailTitle').textContent = displayName + ' — 健康现状 详情';
document.getElementById('detailMeta').textContent = '2026年 · A类768人 · B类256人 · C类128人 · D类89人 · E类39人';
document.getElementById('unitDept').textContent = displayName;
document.getElementById('unitName').textContent = displayName;
document.getElementById('unitTotal').textContent = '总人数:1280';
// 渲染所有面板
['a','b','c','d','e'].forEach(function(cat) { renderPanel(cat); });
@@ -63,8 +63,15 @@ tbody tr:hover{background:#F8FBFF;}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.detail-title{font-size:var(--font-lg);font-weight:600;margin-bottom:4px;}
.detail-meta{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:16px;}
/* 单位信息卡片 */
.info-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);padding:24px;margin-bottom:16px;display:flex;align-items:center;gap:32px;}
.info-card__avatar{width:56px;height:56px;border-radius:50%;background:var(--primary);color:#fff;display:flex;align-items:center;justify-content:center;font-size:20px;font-weight:600;flex-shrink:0;}
.info-card__detail{display:flex;flex-direction:column;gap:6px;}
.info-card__name{font-size:var(--font-lg);font-weight:600;color:var(--text-primary);}
.info-card__meta{display:flex;gap:24px;font-size:var(--font-sm);color:var(--text-secondary);}
.info-card__right{flex-shrink:0;margin-left:auto;}
.info-card__date-filter{display:flex;align-items:center;gap:8px;}
.info-card__date-filter label{font-size:var(--font-xs);color:var(--text-secondary);white-space:nowrap;}
</style>
</head>
<body>
@@ -117,16 +124,33 @@ tbody tr:hover{background:#F8FBFF;}
<span class="sep">/</span>
<span>健康环境</span>
</div>
<div class="detail-title" id="detailTitle"></div>
<div class="detail-meta" id="detailMeta"></div>
<!-- 单位信息卡片 -->
<div class="info-card">
<div class="info-card__detail">
<div class="info-card__name" id="unitName">采油一厂</div>
<div class="info-card__meta">
<span id="unitTotal">设备总数:39</span>
</div>
</div>
<div class="info-card__right">
<div class="info-card__date-filter">
<label>年份</label>
<select class="filter-select" id="filterYear" onchange="onYearChange()" style="height:32px;min-width:110px;font-size:var(--font-xs);">
<option value="2026">2026年</option>
<option value="2025">2025年</option>
<option value="2024">2024年</option>
</select>
</div>
</div>
</div>
<!-- [交互] Tab 切换 -->
<div class="tab-bar">
<div class="tab-item active" onclick="switchTab('indoor',this)">室内设备</div>
<div class="tab-item" onclick="switchTab('outdoor',this)">室外设备</div>
<div class="tab-item" onclick="switchTab('water',this)">水质设备</div>
<div class="tab-item" onclick="switchTab('pollen',this)">花粉设备</div>
<div class="tab-item" onclick="switchTab('alarm',this)">报警次数</div>
<div class="tab-item active" onclick="switchTab('indoor',this)">室内设备(24)</div>
<div class="tab-item" onclick="switchTab('outdoor',this)">室外设备(8)</div>
<div class="tab-item" onclick="switchTab('water',this)">水质设备(5)</div>
<div class="tab-item" onclick="switchTab('pollen',this)">花粉设备(2)</div>
<div class="tab-item" onclick="switchTab('alarm',this)">报警次数(12)</div>
</div>
<!-- 室内设备面板 -->
@@ -495,13 +519,20 @@ function switchTab(tabName, elem) {
document.getElementById('panel-' + tabName).classList.add('active');
}
/* ===== 年份切换 ===== */
var currentYear = '2026';
function onYearChange(){
currentYear = document.getElementById('filterYear').value;
// 可根据年份刷新页面数据
}
var unit = getUrlParam('unit') || '采油一厂';
var dept = getUrlParam('dept') || '';
var displayName = unit + (dept ? ' - ' + dept : '');
document.getElementById('unitDept').textContent = displayName;
document.getElementById('detailTitle').textContent = displayName + ' — 健康环境 详情';
document.getElementById('detailMeta').textContent = '2026年 · 设备总数 39';
document.getElementById('unitName').textContent = displayName;
document.getElementById('unitTotal').textContent = '设备总数39';
// 根据URL参数自动切换tab
var tab = getUrlParam('tab');
@@ -70,6 +70,15 @@ tbody tr:hover{background:#F8FBFF;}
.empty-state{text-align:center;padding:40px 20px;color:var(--text-placeholder);}
.empty-state svg{width:64px;height:64px;margin-bottom:12px;opacity:0.3;}
.empty-state__title{font-size:var(--font-sm);color:var(--text-secondary);}
/* 单位信息卡片 */
.info-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);padding:24px;margin-bottom:16px;display:flex;align-items:center;gap:32px;}
.info-card__avatar{width:56px;height:56px;border-radius:50%;background:var(--primary);color:#fff;display:flex;align-items:center;justify-content:center;font-size:20px;font-weight:600;flex-shrink:0;}
.info-card__detail{display:flex;flex-direction:column;gap:6px;}
.info-card__name{font-size:var(--font-lg);font-weight:600;color:var(--text-primary);}
.info-card__meta{display:flex;gap:24px;font-size:var(--font-sm);color:var(--text-secondary);}
.info-card__right{flex-shrink:0;margin-left:auto;}
.info-card__date-filter{display:flex;align-items:center;gap:8px;}
.info-card__date-filter label{font-size:var(--font-xs);color:var(--text-secondary);white-space:nowrap;}
/* 弹窗 */
.modal-mask{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.45);z-index:500;display:flex;align-items:center;justify-content:center;opacity:0;pointer-events:none;transition:opacity .15s;}
.modal-mask.show{opacity:1;pointer-events:auto;}
@@ -135,10 +144,30 @@ tbody tr:hover{background:#F8FBFF;}
<span>健康排查详情</span>
</div>
<!-- 单位信息卡片 -->
<div class="info-card">
<div class="info-card__detail">
<div class="info-card__name" id="unitName">采油一厂</div>
<div class="info-card__meta">
<span id="unitTotal">排查活动:5个</span>
</div>
</div>
<div class="info-card__right">
<div class="info-card__date-filter">
<label>年份</label>
<select class="filter-select" id="filterYear" onchange="onYearChange()" style="height:32px;min-width:110px;font-size:var(--font-xs);">
<option value="2026">2026年</option>
<option value="2025">2025年</option>
<option value="2024">2024年</option>
</select>
</div>
</div>
</div>
<!-- Tab 切换 -->
<div class="tab-bar">
<div class="tab-item active" onclick="switchTab('activity-list',this)">活动列表</div>
<div class="tab-item" onclick="switchTab('pending-emp',this)">未参加员工</div>
<div class="tab-item active" onclick="switchTab('activity-list',this)">活动列表(5)</div>
<div class="tab-item" onclick="switchTab('pending-emp',this)">未参加员工(8)</div>
</div>
<!-- Tab1: 活动列表 -->
@@ -731,14 +760,24 @@ function resetPendingEmpFilter(){
renderPendingEmpTable(buildPendingEmpList());
}
/* ===== 年份切换 ===== */
var currentYear = '2026';
function onYearChange(){
currentYear = document.getElementById('filterYear').value;
// 可根据年份刷新页面数据
}
/* ===== 初始化 ===== */
(function(){
var unit = getUrlParam('unit') || '采油一厂';
var dept = getUrlParam('dept') || '';
var displayName = unit + (dept ? ' - ' + dept : '');
document.getElementById('bcUnit').textContent = displayName;
renderActivityList(activities);
renderPendingEmpTable(buildPendingEmpList());
var unit = getUrlParam('unit') || '采油一厂';
var dept = getUrlParam('dept') || '';
var displayName = unit + (dept ? ' - ' + dept : '');
document.getElementById('bcUnit').textContent = displayName;
// 填充单位信息卡片
document.getElementById('unitName').textContent = displayName;
document.getElementById('unitTotal').textContent = '排查活动:'+activities.length+'个';
renderActivityList(activities);
renderPendingEmpTable(buildPendingEmpList());
// 根据URL参数自动切换tab
var tab = getUrlParam('tab');
if(tab){
@@ -63,8 +63,15 @@ tbody tr:hover{background:#F8FBFF;}
.pagination span{font-size:var(--font-sm);color:var(--text-secondary);}
.page-btn{width:32px;height:32px;border:1px solid var(--border);border-radius:var(--radius-sm);background:#fff;cursor:pointer;font-size:var(--font-sm);display:inline-flex;align-items:center;justify-content:center;transition:all .2s;}
.page-btn:hover,.page-btn.active{background:var(--primary);color:#fff;border-color:var(--primary);}
.detail-title{font-size:var(--font-lg);font-weight:600;margin-bottom:4px;}
.detail-meta{font-size:var(--font-sm);color:var(--text-secondary);margin-bottom:16px;}
/* 单位信息卡片 */
.info-card{background:#fff;border-radius:var(--radius-md);box-shadow:var(--shadow-sm);padding:24px;margin-bottom:16px;display:flex;align-items:center;gap:32px;}
.info-card__avatar{width:56px;height:56px;border-radius:50%;background:var(--primary);color:#fff;display:flex;align-items:center;justify-content:center;font-size:20px;font-weight:600;flex-shrink:0;}
.info-card__detail{display:flex;flex-direction:column;gap:6px;}
.info-card__name{font-size:var(--font-lg);font-weight:600;color:var(--text-primary);}
.info-card__meta{display:flex;gap:24px;font-size:var(--font-sm);color:var(--text-secondary);}
.info-card__right{flex-shrink:0;margin-left:auto;}
.info-card__date-filter{display:flex;align-items:center;gap:8px;}
.info-card__date-filter label{font-size:var(--font-xs);color:var(--text-secondary);white-space:nowrap;}
</style>
</head>
<body>
@@ -117,8 +124,25 @@ tbody tr:hover{background:#F8FBFF;}
<span class="sep">/</span>
<span>穿戴监测</span>
</div>
<div class="detail-title" id="detailTitle"></div>
<div class="detail-meta" id="detailMeta"></div>
<!-- 单位信息卡片 -->
<div class="info-card">
<div class="info-card__detail">
<div class="info-card__name" id="unitName">采油一厂</div>
<div class="info-card__meta">
<span id="unitTotal">总设备数:90</span>
</div>
</div>
<div class="info-card__right">
<div class="info-card__date-filter">
<label>年份</label>
<select class="filter-select" id="filterYear" onchange="onYearChange()" style="height:32px;min-width:110px;font-size:var(--font-xs);">
<option value="2026">2026年</option>
<option value="2025">2025年</option>
<option value="2024">2024年</option>
</select>
</div>
</div>
</div>
<!-- [交互] Tab 切换 -->
<div class="tab-bar">
@@ -473,13 +497,20 @@ function switchTab(tabName, elem) {
document.getElementById('panel-' + tabName).classList.add('active');
}
/* ===== 年份切换 ===== */
var currentYear = '2026';
function onYearChange(){
currentYear = document.getElementById('filterYear').value;
// 可根据年份刷新页面数据
}
var unit = getUrlParam('unit') || '采油一厂';
var dept = getUrlParam('dept') || '';
var displayName = unit + (dept ? ' - ' + dept : '');
document.getElementById('unitDept').textContent = displayName;
document.getElementById('detailTitle').textContent = displayName + ' — 穿戴监测 详情';
document.getElementById('detailMeta').textContent = '2026年 · 总设备数 90';
document.getElementById('unitName').textContent = displayName;
document.getElementById('unitTotal').textContent = '总设备数90';
// 根据URL参数自动切换tab
var tab = getUrlParam('tab');
File diff suppressed because it is too large Load Diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 55 KiB

@@ -707,6 +707,7 @@
<div style="background:#F0F7FF;border:1px solid #BAE0FF;border-radius:var(--radius-md);padding:10px 16px;flex-shrink:0;">
<span style="font-size:var(--font-sm);color:#0958D9;">设备编码:<strong id="msDeviceCode">WD-2024-001</strong></span>
</div>
<button class="btn btn-primary btn-sm" onclick="showAddTypeForm()" style="flex-shrink:0;">+ 新增类型配置</button>
</div>
<div class="monitor-setting-list" id="monitorSettingList">
<!-- 心率 -->
+62
View File
@@ -0,0 +1,62 @@
@echo off
chcp 65001 >nul
title 健康CQ原型 - 本地服务器
cd /d "%~dp0"
echo ============================================
echo 健康CQ升级项目 · 高保真交互原型
echo ============================================
echo.
:: ── 检查端口 8080 是否已被占用 ──
netstat -ano 2>nul | findstr ":8080" | findstr "LISTENING" >nul
if %errorlevel% equ 0 (
echo [跳过] 端口 8080 已被占用,服务器已在运行。
goto open_browser
)
:: ── 优先 npx serve(配置了 serve.json),备选 Python ──
where npx >nul 2>nul
if %errorlevel% equ 0 (
echo [启动] 使用 npx serve 启动服务器...
start "健康CQ原型-服务器" /min cmd /c "npx --yes serve . -p 8080 --no-clipboard"
goto wait_server
)
where python >nul 2>nul
if %errorlevel% equ 0 (
echo [启动] 使用 Python 启动服务器...
start "健康CQ原型-服务器" /min cmd /c "python -m http.server 8080"
goto wait_server
)
echo [错误] 未找到 Node.js (npx) 或 Python
echo 请安装 Node.js: https://nodejs.org/
pause
exit /b 1
:wait_server
echo [等待] 服务器启动中...
set /a COUNT=0
:wait_loop
set /a COUNT+=1
powershell -NoProfile -Command "try {$r=Invoke-WebRequest -Uri 'http://localhost:8080/' -TimeoutSec 2 -UseBasicParsing; exit 0} catch {exit 1}" >nul 2>&1
if %errorlevel% equ 0 (
echo [就绪] 启动成功!(%COUNT%秒)
goto open_browser
)
if %COUNT% geq 30 (
echo [超时] 30秒未就绪,请检查是否被防火墙拦截
pause
exit /b 1
)
timeout /t 1 /nobreak >nul
goto wait_loop
:open_browser
echo [打开] 打开浏览器...
start http://localhost:8080/
echo.
echo ✅ 完成!以后双击本文件即可一键启动。
timeout /t 2 /nobreak >nul
exit