fix: 更新健康检查、健康监测及体重管理页面,新增胃肠镜报告页面

This commit is contained in:
liuyunqin
2026-07-07 19:36:38 +08:00
parent e197cf8eb3
commit a55a918239
16 changed files with 1205 additions and 345 deletions
+31 -16
View File
@@ -1175,6 +1175,7 @@ function buildMeasureData(){
types.forEach(function(t){
var hasRecord = i % 5 !== 4;
var count = hasRecord ? (t==='weight' ? Math.floor(Math.random()*12)+2 : Math.floor(Math.random()*50)+10) : 0;
var days = hasRecord ? Math.min(count, Math.floor(Math.random()*daysSinceStart)+1) : 0;
var firstDay = new Date(today); firstDay.setDate(firstDay.getDate()-daysSinceStart);
var lastDay = hasRecord ? new Date(today) : null;
var fd = firstDay.getFullYear()+'-'+('0'+(firstDay.getMonth()+1)).slice(-2)+'-'+('0'+firstDay.getDate()).slice(-2);
@@ -1187,7 +1188,7 @@ function buildMeasureData(){
data[t].push({
planId: planIdVal, planName: planNameVal, org: e.org, dept: e.dept,
name: e.name, empId: e.empId, gender: e.gender, age: e.age,
measureType: t, checkinCount: count, firstDate: fd, lastDate: ld, hasRecord: hasRecord, source: source
measureType: t, checkinCount: count, checkinDays: days, firstDate: fd, lastDate: ld, hasRecord: hasRecord, source: source
});
});
});
@@ -1199,6 +1200,7 @@ var measureData = buildMeasureData();
var currentTab = 1;
var currentSubTab = 'weight';
var sortAsc = false;
var sortField = 'count';
var pageSize = 10;
var currentPage = 0;
var filteredData = [];
@@ -1435,7 +1437,8 @@ function applyFilter1(){
return true;
});
// 排序
filteredData.sort(function(a,b){ return sortAsc ? a.checkinCount - b.checkinCount : b.checkinCount - a.checkinCount; });
var fieldKey = sortField === 'days' ? 'checkinDays' : 'checkinCount';
filteredData.sort(function(a,b){ return sortAsc ? a[fieldKey] - b[fieldKey] : b[fieldKey] - a[fieldKey]; });
currentPage = 0;
renderOverviewTable();
updateTabBadges();
@@ -1460,8 +1463,9 @@ function resetFilter1(){
document.getElementById('filterDateFrom1').value = mon.getFullYear()+'-'+('0'+(mon.getMonth()+1)).slice(-2)+'-'+('0'+mon.getDate()).slice(-2);
document.getElementById('filterDateTo1').value = sun.getFullYear()+'-'+('0'+(sun.getMonth()+1)).slice(-2)+'-'+('0'+sun.getDate()).slice(-2);
document.querySelectorAll('.sub-tab-status .sub-tab-item').forEach(function(el){el.classList.toggle('active', el.dataset.status === 'all');});
sortAsc = false;
document.getElementById('sortCount').classList.remove('asc','desc');
sortAsc = false; sortField = 'count';
var sc = document.getElementById('sortCount'); if(sc){ sc.classList.remove('asc','desc'); var a = sc.querySelector('.sort-arrow'); if(a) a.textContent = '↕'; }
var sd = document.getElementById('sortDays'); if(sd){ sd.classList.remove('asc','desc'); var a = sd.querySelector('.sort-arrow'); if(a) a.textContent = '↕'; }
applyFilter1();
}
@@ -1623,7 +1627,8 @@ function renderDailyTable(){
/* ===== 渲染三测记录表头(体重tab为分组两行表头) ===== */
function renderOverviewHeader(){
var thead = document.getElementById('overviewThead');
var sortTh = '<th class="th-sortable" id="sortCount" '+(currentSubTab==='weight'?'rowspan="2" ':'')+'onclick="toggleSort()">打卡次数 <span class="sort-arrow">↕</span></th>';
var sortCountTh = '<th class="th-sortable" id="sortCount" '+(currentSubTab==='weight'?'rowspan="2" ':'')+'onclick="toggleSort(\'count\')">打卡次数 <span class="sort-arrow">↕</span></th>';
var sortDaysTh = '<th class="th-sortable" id="sortDays" '+(currentSubTab==='weight'?'rowspan="2" ':'')+'onclick="toggleSort(\'days\')">打卡天数 <span class="sort-arrow">↕</span></th>';
var html = '';
if(currentSubTab === 'weight'){
html += '<tr>';
@@ -1634,7 +1639,8 @@ function renderOverviewHeader(){
html += '<th rowspan="2">年龄</th>';
html += '<th rowspan="2">单位</th>';
html += '<th rowspan="2">部门</th>';
html += sortTh;
html += sortCountTh;
html += sortDaysTh;
html += '<th rowspan="2">首次记录日期</th>';
html += '<th rowspan="2">末次记录日期</th>';
html += '<th colspan="6">末次记录数据</th>';
@@ -1656,7 +1662,8 @@ function renderOverviewHeader(){
html += '<th>年龄</th>';
html += '<th>单位</th>';
html += '<th>部门</th>';
html += sortTh;
html += sortCountTh;
html += '<th class="th-sortable" id="sortDays" onclick="toggleSort(\'days\')">打卡天数 <span class="sort-arrow">↕</span></th>';
html += '<th>首次记录日期</th>';
html += '<th>末次记录日期</th>';
html += '</tr>';
@@ -1673,7 +1680,7 @@ function renderOverviewTable(){
document.getElementById('pageInfo1').textContent = '显示 ' + pageData.length + ' 条,共 ' + filteredData.length + ' 条记录';
document.getElementById('pageNum1').textContent = '第 ' + (currentPage + 1) + '/' + totalPages + ' 页';
var isWeight = currentSubTab === 'weight';
var colCount = isWeight ? 16 : 10;
var colCount = isWeight ? 17 : 11;
if(filteredData.length === 0){
tbody.innerHTML = '<tr><td colspan="'+colCount+'" class="td-empty">暂无匹配数据</td></tr>';
return;
@@ -1689,6 +1696,7 @@ function renderOverviewTable(){
html += '<td>'+esc(d.org)+'</td>';
html += '<td>'+esc(d.dept)+'</td>';
html += '<td>'+d.checkinCount+'</td>';
html += '<td>'+d.checkinDays+'</td>';
html += '<td>'+esc(d.firstDate)+'</td>';
html += '<td>'+esc(d.lastDate)+'</td>';
if(isWeight){
@@ -1713,9 +1721,11 @@ function switchSubTab(type){
});
// 体重tab为分组两行表头,其余为单行表头
renderOverviewHeader();
sortAsc = false;
sortAsc = false; sortField = 'count';
var sortTh = document.getElementById('sortCount');
if(sortTh){ sortTh.classList.remove('asc','desc'); var arrow = sortTh.querySelector('.sort-arrow'); if(arrow){ arrow.textContent = '↕'; } }
var sortDays = document.getElementById('sortDays');
if(sortDays){ sortDays.classList.remove('asc','desc'); var arrow = sortDays.querySelector('.sort-arrow'); if(arrow){ arrow.textContent = '↕'; } }
// 重置记录状态为全部
document.querySelectorAll('.sub-tab-status .sub-tab-item').forEach(function(el){el.classList.toggle('active', el.dataset.status === 'all');});
applyFilter1();
@@ -1729,13 +1739,18 @@ function switchRecordStatus(status){
applyFilter1();
}
/* [交互] 打卡次数排序切换 */
function toggleSort(){
sortAsc = !sortAsc;
var th = document.getElementById('sortCount');
th.classList.remove('asc','desc');
th.classList.add(sortAsc ? 'asc' : 'desc');
th.querySelector('.sort-arrow').textContent = sortAsc ? '↑' : '↓';
/* [交互] 打卡次数/天数排序切换 */
function toggleSort(field){
if(sortField !== field){ sortField = field; sortAsc = false; }
else { sortAsc = !sortAsc; }
// 清除两个排序列的样式
var thCount = document.getElementById('sortCount');
var thDays = document.getElementById('sortDays');
if(thCount){ thCount.classList.remove('asc','desc'); var a = thCount.querySelector('.sort-arrow'); if(a) a.textContent = '↕'; }
if(thDays){ thDays.classList.remove('asc','desc'); var a = thDays.querySelector('.sort-arrow'); if(a) a.textContent = '↕'; }
// 设置当前排序列样式
var th = document.getElementById(field === 'count' ? 'sortCount' : 'sortDays');
if(th){ th.classList.add(sortAsc ? 'asc' : 'desc'); th.querySelector('.sort-arrow').textContent = sortAsc ? '↑' : '↓'; }
applyFilter1();
}
@@ -160,7 +160,7 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
<div class="page-header__breadcrumb">体重管理 / 档案 / <span>个人体重数据</span></div>
</div>
<!-- [交互] 筛选栏 — 姓名 + 员工编号 + 单位部门 + 日期范围 -->
<!-- [交互] 筛选栏 — 姓名 + 员工编号 + 单位部门 + 年份 -->
<div class="filter-bar">
<div class="filter-item">
<label>姓名</label>
@@ -190,12 +190,16 @@ tbody tr:hover td:last-child{background:#F8FBFF;}
</div>
</div>
</div>
<div class="filter-item">
<label>日期范围</label>
<input class="filter-date" type="date" id="filterDateFrom">
<span style="font-size:var(--font-xs);color:var(--text-placeholder);"></span>
<input class="filter-date" type="date" id="filterDateTo">
</div>
<div class="filter-item">
<label>年份</label>
<select class="filter-select" id="filterYear">
<option>2026年</option>
<option>2025年</option>
<option>2024年</option>
<option>2023年</option>
<option>2022年</option>
</select>
</div>
<!-- [交互] 点击查询按钮筛选列表 -->
<button class="btn btn-primary" onclick="applyFilter()">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><circle cx="6" cy="6" r="4.5" stroke="#fff" stroke-width="1.3"/><path d="M9.5 9.5L13 13" stroke="#fff" stroke-width="1.3" stroke-linecap="round"/></svg>查询
@@ -361,45 +365,37 @@ function selectDept(elem, deptName, deptCode){
}
/* ===== 筛选 ===== */
function applyFilter(){
var name = document.getElementById('filterName').value.trim().toLowerCase();
var empId = document.getElementById('filterEmpId').value.trim().toLowerCase();
var unit = selUnitCode;
var dept = selDeptCode;
var dateFrom = document.getElementById('filterDateFrom').value;
var dateTo = document.getElementById('filterDateTo').value;
var data = personnelData.slice();
if(name){ data = data.filter(function(d){return d.name.toLowerCase().indexOf(name) !== -1;}); }
if(empId){ data = data.filter(function(d){return d.empId.toLowerCase().indexOf(empId) !== -1;}); }
if(unit){ data = data.filter(function(d){return d.unit === unit;}); }
if(dept){ data = data.filter(function(d){return d.dept === dept;}); }
// 日期范围筛选 — 基于记录日期(Mock 数据中没有日期字段,保留筛选逻辑用于后续对接真实数据)
if(dateFrom || dateTo){
// 当前 Mock 数据不含日期字段,日期筛选不影响结果
// 对接真实接口后启用:
// if(dateFrom){ data = data.filter(function(d){return d.recordDate >= dateFrom;}); }
// if(dateTo){ data = data.filter(function(d){return d.recordDate <= dateTo;}); }
}
filteredData = data;
currentPage = 0;
renderTable();
}
function applyFilter(){
var name = document.getElementById('filterName').value.trim().toLowerCase();
var empId = document.getElementById('filterEmpId').value.trim().toLowerCase();
var unit = selUnitCode;
var dept = selDeptCode;
var year = document.getElementById('filterYear').value.replace('年','');
var data = personnelData.slice();
if(name){ data = data.filter(function(d){return d.name.toLowerCase().indexOf(name) !== -1;}); }
if(empId){ data = data.filter(function(d){return d.empId.toLowerCase().indexOf(empId) !== -1;}); }
if(unit){ data = data.filter(function(d){return d.unit === unit;}); }
if(dept){ data = data.filter(function(d){return d.dept === dept;}); }
// 年份筛选 — Mock 数据不含年份字段,保留逻辑用于后续对接真实数据
// 对接真实接口后启用:data = data.filter(function(d){return d.recordYear === year;});
filteredData = data;
currentPage = 0;
renderTable();
}
function resetFilter(){
document.getElementById('filterName').value = '';
document.getElementById('filterEmpId').value = '';
selUnitName = ''; selUnitCode = '';
selDeptName = ''; selDeptCode = '';
document.getElementById('orgTrigger').textContent = '全部单位/部门';
document.querySelectorAll('#unitCol .org-item').forEach(function(item){item.classList.remove('active');});
var firstUnit = document.querySelector('#unitCol .org-item');
if(firstUnit) firstUnit.classList.add('active');
document.getElementById('deptCol').innerHTML = '<div class="org-col__title">部门</div><div class="org-item active" data-dept="" onclick="selectDept(this,\'全部部门\',\'\')">全部部门</div>';
var now = new Date();
document.getElementById('filterDateFrom').value = now.getFullYear() + '-01-01';
document.getElementById('filterDateTo').value = now.getFullYear() + '-' + String(now.getMonth()+1).padStart(2,'0') + '-' + String(now.getDate()).padStart(2,'0');
applyFilter();
}
function resetFilter(){
document.getElementById('filterName').value = '';
document.getElementById('filterEmpId').value = '';
selUnitName = ''; selUnitCode = '';
selDeptName = ''; selDeptCode = '';
document.getElementById('orgTrigger').textContent = '全部单位/部门';
document.querySelectorAll('#unitCol .org-item').forEach(function(item){item.classList.remove('active');});
var firstUnit = document.querySelector('#unitCol .org-item');
if(firstUnit) firstUnit.classList.add('active');
document.getElementById('deptCol').innerHTML = '<div class="org-col__title">部门</div><div class="org-item active" data-dept="" onclick="selectDept(this,\'全部部门\',\'\')">全部部门</div>';
document.getElementById('filterYear').value = new Date().getFullYear() + '年';
applyFilter();
}
/* ===== 渲染表格 ===== */
function renderTable(){
@@ -441,7 +437,7 @@ function renderTable(){
html += '<td>'+d.dietCount+'</td>';
html += '<td>'+d.sportCount+'</td>';
html += '<td>'+d.weightCount+'</td>';
html += '<td><a class="link" href="archive-personal-weight-detail.html?id='+esc(d.empId)+'&year='+encodeURIComponent(document.getElementById('filterDateFrom').value.substring(0,4))+'">查看</a></td>';
html += '<td><a class="link" href="archive-personal-weight-detail.html?id='+esc(d.empId)+'&year='+encodeURIComponent(document.getElementById('filterYear').value.replace('年',''))+'">查看</a></td>';
html += '</tr>';
});
tbody.innerHTML = html;
@@ -473,15 +469,11 @@ function showToast(msg){
setTimeout(function(){t.classList.remove('show');},2000);
}
/* ===== 初始化 ===== */
(function init(){
var now = new Date();
var yearStart = now.getFullYear() + '-01-01';
var today = now.getFullYear() + '-' + String(now.getMonth()+1).padStart(2,'0') + '-' + String(now.getDate()).padStart(2,'0');
document.getElementById('filterDateFrom').value = yearStart;
document.getElementById('filterDateTo').value = today;
renderTable();
})();
/* ===== 初始化 ===== */
(function init(){
document.getElementById('filterYear').value = new Date().getFullYear() + '年';
renderTable();
})();
</script>
</body>
</html>
@@ -143,6 +143,7 @@
</div>
<div class="filter-item"><label>姓名</label><input class="filter-input" placeholder="请输入姓名" style="min-width:120px;"></div>
<div class="filter-item"><label>员工编号</label><input class="filter-input" placeholder="请输入员工编号" style="min-width:140px;"></div>
<div class="filter-item"><label>是否设置个人目标</label><select class="filter-select"><option value="">全部</option><option value="yes">已设置</option><option value="no">未设置</option></select></div>
<button class="btn btn-primary">查询</button>
<button class="btn btn-default">重置</button>
</div>
@@ -225,50 +226,50 @@
<td class="change-down">-11.3</td><td class="change-down">-3.5</td><td class="change-down">-6.3</td><td class="change-down">-13</td>
<td class="col-fixed-r"><a class="btn-link" href="personal-target-detail.html?empId=EMP-10005">查看</a></td>
</tr>
<!-- 未设置目标的人员:目标周期/目标指标显示"-",当前指标和变化有实际称重数据 -->
<!-- 未设置目标的人员:目标周期/目标指标/初始指标/变化均显示"-"当前指标有实际称重数据 -->
<tr>
<td class="col-fixed-l1">孙磊</td><td class="col-fixed-l2">EMP-10101</td><td></td><td>29</td><td>采油一厂</td><td>生产运行科</td>
<td>-</td><td class="th-divider">-</td>
<td>172</td><td>78.0</td><td>26.4</td><td>24.5</td><td class="th-divider">92</td>
<td>-</td><td>-</td><td>-</td><td>-</td><td class="th-divider">-</td>
<td>-</td><td>-</td><td>-</td><td class="th-divider">-</td>
<td>77.5</td><td>26.2</td><td>24.0</td><td class="th-divider">91</td>
<td class="change-down">-0.5</td><td class="change-down">-0.2</td><td class="change-down">-0.5</td><td class="change-down">-1</td>
<td>-</td><td>-</td><td>-</td><td>-</td>
<td class="col-fixed-r"><a class="btn-link" href="personal-target-detail.html?empId=EMP-10101">查看</a></td>
</tr>
<tr>
<td class="col-fixed-l1">周婷</td><td class="col-fixed-l2">EMP-10102</td><td></td><td>33</td><td>采油二厂</td><td>安全环保科</td>
<td>-</td><td class="th-divider">-</td>
<td>158</td><td>65.2</td><td>26.1</td><td>31.0</td><td class="th-divider">80</td>
<td>-</td><td>-</td><td>-</td><td>-</td><td class="th-divider">-</td>
<td>-</td><td>-</td><td>-</td><td class="th-divider">-</td>
<td>64.5</td><td>25.8</td><td>30.2</td><td class="th-divider">78</td>
<td class="change-down">-0.7</td><td class="change-down">-0.3</td><td class="change-down">-0.8</td><td class="change-down">-2</td>
<td>-</td><td>-</td><td>-</td><td>-</td>
<td class="col-fixed-r"><a class="btn-link" href="personal-target-detail.html?empId=EMP-10102">查看</a></td>
</tr>
<tr>
<td class="col-fixed-l1">吴刚</td><td class="col-fixed-l2">EMP-10103</td><td></td><td>45</td><td>采气厂</td><td>综合管理科</td>
<td>-</td><td class="th-divider">-</td>
<td>168</td><td>90.5</td><td>32.1</td><td>33.5</td><td class="th-divider">108</td>
<td>-</td><td>-</td><td>-</td><td>-</td><td class="th-divider">-</td>
<td>-</td><td>-</td><td>-</td><td class="th-divider">-</td>
<td>91.2</td><td>32.3</td><td>34.2</td><td class="th-divider">110</td>
<td class="change-up">+0.7</td><td class="change-up">+0.2</td><td class="change-up">+0.7</td><td class="change-up">+2</td>
<td>-</td><td>-</td><td>-</td><td>-</td>
<td class="col-fixed-r"><a class="btn-link" href="personal-target-detail.html?empId=EMP-10103">查看</a></td>
</tr>
<tr>
<td class="col-fixed-l1">陈静</td><td class="col-fixed-l2">EMP-10104</td><td></td><td>26</td><td>采油一厂</td><td>综合管理科</td>
<td>-</td><td class="th-divider">-</td>
<td>165</td><td>58.0</td><td>21.3</td><td>25.0</td><td class="th-divider">72</td>
<td>-</td><td>-</td><td>-</td><td>-</td><td class="th-divider">-</td>
<td>-</td><td>-</td><td>-</td><td class="th-divider">-</td>
<td>57.3</td><td>21.0</td><td>24.2</td><td class="th-divider">71</td>
<td class="change-down">-0.7</td><td class="change-down">-0.3</td><td class="change-down">-0.8</td><td class="change-down">-1</td>
<td>-</td><td>-</td><td>-</td><td>-</td>
<td class="col-fixed-r"><a class="btn-link" href="personal-target-detail.html?empId=EMP-10104">查看</a></td>
</tr>
<tr>
<td class="col-fixed-l1">郑飞</td><td class="col-fixed-l2">EMP-10105</td><td></td><td>40</td><td>采油二厂</td><td>生产运行科</td>
<td>-</td><td class="th-divider">-</td>
<td>175</td><td>86.2</td><td>28.1</td><td>28.5</td><td class="th-divider">98</td>
<td>-</td><td>-</td><td>-</td><td>-</td><td class="th-divider">-</td>
<td>-</td><td>-</td><td>-</td><td class="th-divider">-</td>
<td>85.5</td><td>27.9</td><td>28.0</td><td class="th-divider">96</td>
<td class="change-down">-0.7</td><td class="change-down">-0.2</td><td class="change-down">-0.5</td><td class="change-down">-2</td>
<td>-</td><td>-</td><td>-</td><td>-</td>
<td class="col-fixed-r"><a class="btn-link" href="personal-target-detail.html?empId=EMP-10105">查看</a></td>
</tr>
</tbody>
+247 -91
View File
@@ -150,7 +150,28 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
.search-select__option.selected{color:var(--primary);background:var(--primary-light);}
.search-select__avatar{width:28px;height:28px;border-radius:50%;background:#E6F7FF;display:flex;align-items:center;justify-content:center;color:var(--primary);font-size:var(--font-xs);flex-shrink:0;}
/* 文件上传 */
/* 树形选择器(组织机构) */
.tree-select{position:relative;width:100%;}
.tree-select__trigger{width:100%;height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 32px 0 12px;font-size:var(--font-sm);background:#fff;cursor:pointer;display:flex;align-items:center;user-select:none;transition:border-color .2s;box-sizing:border-box;position:relative;}
.tree-select__trigger:hover{border-color:var(--primary);}
.tree-select__trigger::after{content:'';position:absolute;right:12px;top:50%;transform:translateY(-50%);border:4px solid transparent;border-top:5px solid #999;pointer-events:none;}
.tree-select__text{color:var(--text-placeholder);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.tree-select__text.has-value{color:var(--text-primary);}
.tree-select__panel{position:absolute;top:100%;left:0;right:0;margin-top:4px;background:#fff;border:1px solid var(--border);border-radius:var(--radius-md);box-shadow:var(--shadow-md);z-index:500;display:none;max-height:320px;overflow-y:auto;}
.tree-select__panel.show{display:block;}
.tree-select__group{border-bottom:1px solid #F5F5F5;}
.tree-select__group:last-child{border-bottom:none;}
.tree-select__group-header{display:flex;align-items:center;gap:6px;padding:9px 16px;font-size:var(--font-sm);font-weight:500;color:var(--text-primary);cursor:pointer;transition:background .1s;user-select:none;}
.tree-select__group-header:hover{background:#F5F7FA;}
.tree-select__group-arrow{width:16px;height:16px;display:flex;align-items:center;justify-content:center;transition:transform .2s;flex-shrink:0;color:var(--text-placeholder);}
.tree-select__group-arrow.expanded{transform:rotate(90deg);}
.tree-select__group-label{flex:1;}
.tree-select__option{padding:8px 16px 8px 38px;font-size:var(--font-sm);cursor:pointer;transition:background .1s;display:none;color:var(--text-secondary);}
.tree-select__option.show{display:block;}
.tree-select__option:hover{background:#F5F7FA;}
.tree-select__option.selected{color:var(--primary);background:var(--primary-light);}
/* 文件上传 */
.upload-area{border:2px dashed var(--border);border-radius:var(--radius-md);padding:32px;text-align:center;cursor:pointer;transition:all .2s;background:#FAFAFA;}
.upload-area:hover{border-color:var(--primary);background:var(--primary-light);}
.upload-area svg{width:40px;height:40px;color:var(--text-placeholder);margin-bottom:8px;}
@@ -208,17 +229,66 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
<span id="formCardTitle">新增计划</span>
</div>
<!-- 活动组织单位 -->
<div class="form-group">
<label>活动组织单位 <span class="req">*</span></label>
<select class="form-input" id="planOrg">
<option value="">请选择组织单位</option>
<option>第四采油厂</option>
<option>采油一厂</option>
<option>采油二厂</option>
<option>采气一厂</option>
</select>
</div>
<!-- 活动组织机构 -->
<div class="form-group">
<label>活动组织机构 <span class="req">*</span></label>
<div class="tree-select" id="orgTreeSelect">
<input type="hidden" id="planOrg" value="">
<div class="tree-select__trigger" onclick="toggleOrgTree()">
<span class="tree-select__text" id="orgTreeText">请选择组织机构</span>
</div>
<div class="tree-select__panel" id="orgTreePanel">
<div class="tree-select__group" data-unit="第四采油厂">
<div class="tree-select__group-header" onclick="toggleOrgGroup(this, event)">
<span class="tree-select__group-arrow"></span>
<span class="tree-select__group-label">第四采油厂</span>
</div>
<div class="tree-select__option" data-val="第四采油厂|健康管理部" onclick="selectOrgOption(this,'第四采油厂 / 健康管理部')">健康管理部</div>
<div class="tree-select__option" data-val="第四采油厂|安全环保科" onclick="selectOrgOption(this,'第四采油厂 / 安全环保科')">安全环保科</div>
<div class="tree-select__option" data-val="第四采油厂|工会办公室" onclick="selectOrgOption(this,'第四采油厂 / 工会办公室')">工会办公室</div>
<div class="tree-select__option" data-val="第四采油厂|生产技术部" onclick="selectOrgOption(this,'第四采油厂 / 生产技术部')">生产技术部</div>
<div class="tree-select__option" data-val="第四采油厂|财务部" onclick="selectOrgOption(this,'第四采油厂 / 财务部')">财务部</div>
<div class="tree-select__option" data-val="第四采油厂|信息中心" onclick="selectOrgOption(this,'第四采油厂 / 信息中心')">信息中心</div>
</div>
<div class="tree-select__group" data-unit="采油一厂">
<div class="tree-select__group-header" onclick="toggleOrgGroup(this, event)">
<span class="tree-select__group-arrow"></span>
<span class="tree-select__group-label">采油一厂</span>
</div>
<div class="tree-select__option" data-val="采油一厂|健康管理部" onclick="selectOrgOption(this,'采油一厂 / 健康管理部')">健康管理部</div>
<div class="tree-select__option" data-val="采油一厂|安全环保科" onclick="selectOrgOption(this,'采油一厂 / 安全环保科')">安全环保科</div>
<div class="tree-select__option" data-val="采油一厂|工会办公室" onclick="selectOrgOption(this,'采油一厂 / 工会办公室')">工会办公室</div>
<div class="tree-select__option" data-val="采油一厂|生产技术部" onclick="selectOrgOption(this,'采油一厂 / 生产技术部')">生产技术部</div>
<div class="tree-select__option" data-val="采油一厂|财务部" onclick="selectOrgOption(this,'采油一厂 / 财务部')">财务部</div>
<div class="tree-select__option" data-val="采油一厂|信息中心" onclick="selectOrgOption(this,'采油一厂 / 信息中心')">信息中心</div>
</div>
<div class="tree-select__group" data-unit="采油二厂">
<div class="tree-select__group-header" onclick="toggleOrgGroup(this, event)">
<span class="tree-select__group-arrow"></span>
<span class="tree-select__group-label">采油二厂</span>
</div>
<div class="tree-select__option" data-val="采油二厂|健康管理部" onclick="selectOrgOption(this,'采油二厂 / 健康管理部')">健康管理部</div>
<div class="tree-select__option" data-val="采油二厂|安全环保科" onclick="selectOrgOption(this,'采油二厂 / 安全环保科')">安全环保科</div>
<div class="tree-select__option" data-val="采油二厂|工会办公室" onclick="selectOrgOption(this,'采油二厂 / 工会办公室')">工会办公室</div>
<div class="tree-select__option" data-val="采油二厂|生产技术部" onclick="selectOrgOption(this,'采油二厂 / 生产技术部')">生产技术部</div>
<div class="tree-select__option" data-val="采油二厂|财务部" onclick="selectOrgOption(this,'采油二厂 / 财务部')">财务部</div>
<div class="tree-select__option" data-val="采油二厂|信息中心" onclick="selectOrgOption(this,'采油二厂 / 信息中心')">信息中心</div>
</div>
<div class="tree-select__group" data-unit="采气一厂">
<div class="tree-select__group-header" onclick="toggleOrgGroup(this, event)">
<span class="tree-select__group-arrow"></span>
<span class="tree-select__group-label">采气一厂</span>
</div>
<div class="tree-select__option" data-val="采气一厂|健康管理部" onclick="selectOrgOption(this,'采气一厂 / 健康管理部')">健康管理部</div>
<div class="tree-select__option" data-val="采气一厂|安全环保科" onclick="selectOrgOption(this,'采气一厂 / 安全环保科')">安全环保科</div>
<div class="tree-select__option" data-val="采气一厂|工会办公室" onclick="selectOrgOption(this,'采气一厂 / 工会办公室')">工会办公室</div>
<div class="tree-select__option" data-val="采气一厂|生产技术部" onclick="selectOrgOption(this,'采气一厂 / 生产技术部')">生产技术部</div>
<div class="tree-select__option" data-val="采气一厂|财务部" onclick="selectOrgOption(this,'采气一厂 / 财务部')">财务部</div>
<div class="tree-select__option" data-val="采气一厂|信息中心" onclick="selectOrgOption(this,'采气一厂 / 信息中心')">信息中心</div>
</div>
</div>
</div>
</div>
<!-- 计划名称 -->
<div class="form-group">
@@ -245,7 +315,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
<div class="person-panel__label">指定部门</div>
<div class="multi-select" id="deptSelect">
<!-- [交互] 点击展开部门多选下拉 -->
<div class="multi-select__trigger placeholder disabled" onclick="toggleDeptPanel()" id="deptTrigger">请先选择组织单位</div>
<div class="multi-select__trigger placeholder disabled" onclick="toggleDeptPanel()" id="deptTrigger">请先选择组织机构</div>
<div class="multi-select__panel" id="deptPanel">
<div class="multi-select__opt" data-val="健康管理部" onclick="toggleDeptOpt(this,'健康管理部')"><span class="multi-select__cb"></span>健康管理部</div>
<div class="multi-select__opt" data-val="安全环保科" onclick="toggleDeptOpt(this,'安全环保科')"><span class="multi-select__cb"></span>安全环保科</div>
@@ -260,7 +330,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
<div class="person-panel__label">指定员工</div>
<!-- [交互] 点击打开员工选择弹窗 -->
<div class="emp-trigger" id="empTrigger" onclick="openEmpModal()">
<span class="emp-trigger__text" id="empTriggerText">请先选择组织单位</span>
<span class="emp-trigger__text" id="empTriggerText">请先选择组织机构</span>
<svg class="emp-trigger__icon" width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M3 5l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
</div>
</div>
@@ -321,9 +391,9 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
<input type="hidden" id="leaderEmpId">
</div>
<!-- 审核人 -->
<div class="form-group">
<label>审核人 <span class="req">*</span></label>
<!-- 审核人 -->
<div class="form-group">
<label>审核人</label>
<div class="search-select" id="reviewerSelect2">
<!-- [交互] 按姓名搜索审核人 -->
<input class="search-select__input" id="reviewerInput" placeholder="搜索审核人姓名" oninput="searchReviewer2()" onfocus="showReviewerPanel()" autocomplete="off">
@@ -340,9 +410,9 @@ body{font-family:-apple-system,BlinkMacSystemFont,'PingFang SC','Microsoft YaHei
<input type="hidden" id="reviewerInfo">
</div>
<!-- 通知文件 -->
<div class="form-group">
<label>通知文件</label>
<!-- 通知文件 -->
<div class="form-group">
<label>通知文件 <span class="req">*</span></label>
<div class="upload-area" id="uploadArea" onclick="document.getElementById('fileInput').click()">
<svg viewBox="0 0 40 40" fill="none"><path d="M20 8v24M12 16l8-8 8 8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M8 28v4a2 2 0 002 2h20a2 2 0 002-2v-4" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
<div class="upload-area__text">点击或拖拽文件到此区域上传</div>
@@ -528,14 +598,14 @@ function togglePersonPanel(){
/* ===== 部门多选 ===== */
var selectedDepts = [];
function toggleDeptPanel(){
var org = document.getElementById('planOrg').value;
if(!org){showToast('请先选择组织单位');return;}
var panel = document.getElementById('deptPanel');
var isShow = panel.classList.contains('show');
closeAllPanels();
if(!isShow) panel.classList.add('show');
}
function toggleDeptPanel(){
var orgVal = document.getElementById('planOrg').value;
if(!orgVal){showToast('请先选择组织机构');return;}
var panel = document.getElementById('deptPanel');
var isShow = panel.classList.contains('show');
closeAllPanels();
if(!isShow) panel.classList.add('show');
}
function toggleDeptOpt(el, val){
var cb = el.querySelector('.multi-select__cb');
@@ -594,73 +664,157 @@ var mockEmployees = [
{org:'采气一厂',dept:'信息中心',name:'马超',id:'CQ001248',gender:'男',age:36,height:179,weight:95,bmi:29.6}
];
// 监听组织单位变化,同步更新部门和员工选择器状态
document.getElementById('planOrg').addEventListener('change', updateOrgDependent);
// 从组织机构值中提取单位名称(兼容"单位|部门"格式)
function getOrgUnit(val){
var idx = val.indexOf('|');
return idx > -1 ? val.substring(0, idx) : val;
}
// 从组织机构值中提取部门名称(兼容"单位|部门"格式)
function getOrgDept(val){
var idx = val.indexOf('|');
return idx > -1 ? val.substring(idx + 1) : '';
}
function updateOrgDependent(){
var org = document.getElementById('planOrg').value;
var deptTrigger = document.getElementById('deptTrigger');
if(org){
deptTrigger.classList.remove('disabled');
if(selectedDepts.length===0){
deptTrigger.textContent = '请选择部门(可多选)';
}
} else {
deptTrigger.classList.add('disabled');
deptTrigger.textContent = '请先选择组织单位';
selectedDepts = [];
updateDeptTrigger();
}
var empTrigger = document.getElementById('empTrigger');
var text = document.getElementById('empTriggerText');
if(org){
empTrigger.classList.remove('disabled');
text.className = 'emp-trigger__text';
text.textContent = '点击选择员工';
} else {
empTrigger.classList.add('disabled');
text.className = 'emp-trigger__text';
text.textContent = '请先选择组织单位';
selectedEmployees = [];
renderSelectedPersons();
}
}
/* ===== 组织机构树形选择器 ===== */
// [交互] 点击触发器展开/收起下拉面板
function toggleOrgTree(){
var panel = document.getElementById('orgTreePanel');
var isShow = panel.classList.contains('show');
closeAllPanels();
if(!isShow) panel.classList.add('show');
}
function openEmpModal(){
var org = document.getElementById('planOrg').value;
if(!org){showToast('请先选择组织单位');return;}
tempSelectedEmps = selectedEmployees.slice();
renderEmpTable();
document.getElementById('empModal').classList.add('show');
}
// [交互] 点击单位标题展开/收起部门列表
function toggleOrgGroup(headerEl, event){
event.stopPropagation();
var arrow = headerEl.querySelector('.tree-select__group-arrow');
var group = headerEl.parentElement;
var options = group.querySelectorAll('.tree-select__option');
var isExpanded = arrow.classList.contains('expanded');
if(isExpanded){
// 收起:隐藏部门选项,并选中该单位
arrow.classList.remove('expanded');
options.forEach(function(opt){ opt.classList.remove('show'); });
var unitName = group.getAttribute('data-unit');
selectOrgOptionInner(unitName, unitName);
} else {
// 收起其他已展开的分组
document.querySelectorAll('.tree-select__group-arrow.expanded').forEach(function(a){
a.classList.remove('expanded');
});
document.querySelectorAll('.tree-select__option.show').forEach(function(o){
o.classList.remove('show');
});
// 展开当前分组
arrow.classList.add('expanded');
options.forEach(function(opt){ opt.classList.add('show'); });
}
}
// [交互] 点击部门选项选中
function selectOrgOption(el, displayText){
var val = el.getAttribute('data-val');
selectOrgOptionInner(val, displayText);
}
// 内部选中逻辑
function selectOrgOptionInner(val, displayText){
// 更新隐藏域
var hidden = document.getElementById('planOrg');
var oldVal = hidden.value;
hidden.value = val;
// 更新触发器显示
var textEl = document.getElementById('orgTreeText');
textEl.textContent = displayText;
textEl.className = 'tree-select__text has-value';
// 更新面板选中态
document.querySelectorAll('#orgTreePanel .tree-select__option.selected').forEach(function(o){
o.classList.remove('selected');
});
var targetOpt = document.querySelector('#orgTreePanel .tree-select__option[data-val="' + val + '"]');
if(targetOpt){ targetOpt.classList.add('selected'); }
// 关闭面板
document.getElementById('orgTreePanel').classList.remove('show');
// 触发change事件
if(oldVal !== val){
var evt = document.createEvent('HTMLEvents');
evt.initEvent('change', true, false);
hidden.dispatchEvent(evt);
}
}
// 监听组织机构变化,同步更新部门和员工选择器状态
document.getElementById('planOrg').addEventListener('change', updateOrgDependent);
function updateOrgDependent(){
var orgVal = document.getElementById('planOrg').value;
var orgUnit = getOrgUnit(orgVal);
var deptTrigger = document.getElementById('deptTrigger');
if(orgUnit){
deptTrigger.classList.remove('disabled');
if(selectedDepts.length===0){
deptTrigger.textContent = '请选择部门(可多选)';
}
} else {
deptTrigger.classList.add('disabled');
deptTrigger.textContent = '请先选择组织机构';
selectedDepts = [];
updateDeptTrigger();
}
var empTrigger = document.getElementById('empTrigger');
var text = document.getElementById('empTriggerText');
if(orgUnit){
empTrigger.classList.remove('disabled');
text.className = 'emp-trigger__text';
text.textContent = '点击选择员工';
} else {
empTrigger.classList.add('disabled');
text.className = 'emp-trigger__text';
text.textContent = '请先选择组织机构';
selectedEmployees = [];
renderSelectedPersons();
}
}
function openEmpModal(){
var orgVal = document.getElementById('planOrg').value;
if(!orgVal){showToast('请先选择组织机构');return;}
tempSelectedEmps = selectedEmployees.slice();
renderEmpTable();
document.getElementById('empModal').classList.add('show');
}
function closeEmpModal(){
document.getElementById('empModal').classList.remove('show');
}
function renderEmpTable(){
var org = document.getElementById('planOrg').value;
var filterDept = document.getElementById('empFilterDept').value;
var filterName = document.getElementById('empFilterName').value.trim().toLowerCase();
var filterId = document.getElementById('empFilterId').value.trim().toLowerCase();
function renderEmpTable(){
var orgVal = document.getElementById('planOrg').value;
var orgUnit = getOrgUnit(orgVal);
var orgDept = getOrgDept(orgVal);
var filterDept = document.getElementById('empFilterDept').value;
var filterName = document.getElementById('empFilterName').value.trim().toLowerCase();
var filterId = document.getElementById('empFilterId').value.trim().toLowerCase();
var weightOp = document.getElementById('empFilterWeightOp').value;
var weightV1 = document.getElementById('empFilterWeightVal1').value;
var weightV2 = document.getElementById('empFilterWeightVal2').value;
var weightOp = document.getElementById('empFilterWeightOp').value;
var weightV1 = document.getElementById('empFilterWeightVal1').value;
var weightV2 = document.getElementById('empFilterWeightVal2').value;
var bmiOp = document.getElementById('empFilterBmiOp').value;
var bmiV1 = document.getElementById('empFilterBmiVal1').value;
var bmiV2 = document.getElementById('empFilterBmiVal2').value;
var bmiOp = document.getElementById('empFilterBmiOp').value;
var bmiV1 = document.getElementById('empFilterBmiVal1').value;
var bmiV2 = document.getElementById('empFilterBmiVal2').value;
var filtered = mockEmployees.filter(function(e){
if(e.org !== org) return false;
if(filterDept && e.dept !== filterDept) return false;
if(filterName && e.name.indexOf(filterName) === -1) return false;
if(filterId && e.id.toLowerCase().indexOf(filterId) === -1) return false;
if(!applyEmpOpFilter(e.weight, weightOp, weightV1, weightV2)) return false;
if(!applyEmpOpFilter(e.bmi, bmiOp, bmiV1, bmiV2)) return false;
return true;
});
var filtered = mockEmployees.filter(function(e){
if(e.org !== orgUnit) return false;
if(orgDept && e.dept !== orgDept) return false;
if(filterDept && e.dept !== filterDept) return false;
if(filterName && e.name.indexOf(filterName) === -1) return false;
if(filterId && e.id.toLowerCase().indexOf(filterId) === -1) return false;
if(!applyEmpOpFilter(e.weight, weightOp, weightV1, weightV2)) return false;
if(!applyEmpOpFilter(e.bmi, bmiOp, bmiV1, bmiV2)) return false;
return true;
});
var tbody = document.getElementById('empTableBody');
if(filtered.length===0){
@@ -933,12 +1087,13 @@ function closeAllPanels(){
document.getElementById('leaderPanel').classList.remove('show');
document.getElementById('reviewerPanel').classList.remove('show');
document.getElementById('deptPanel').classList.remove('show');
document.getElementById('orgTreePanel').classList.remove('show');
}
/* ===== 保存 ===== */
function savePlan(){
var org = document.getElementById('planOrg').value.trim();
if(!org){showToast('请选择活动组织单位');return;}
if(!org){showToast('请选择活动组织机构');return;}
var name = document.getElementById('planName').value.trim();
if(!name){showToast('请输入计划名称');return;}
var personType = document.querySelector('input[name="personType"]:checked').value;
@@ -950,8 +1105,8 @@ function savePlan(){
if(!dateFrom||!dateTo){showToast('请选择计划起止日期');return;}
var dept = document.getElementById('planDept').value.trim();
if(!dept){showToast('请选择组织部门');return;}
if(!selectedLeader){showToast('请选择负责人');return;}
if(!selectedReviewer){showToast('请选择审核人');return;}
if(!selectedLeader){showToast('请选择负责人');return;}
if(uploadedFiles.length === 0){showToast('请上传通知文件');return;}
showToast('保存成功!');
setTimeout(function(){window.location.href='plan-list.html';},1000);
@@ -969,6 +1124,7 @@ document.addEventListener('click',function(e){
if(!e.target.closest('#leaderSelect')) document.getElementById('leaderPanel').classList.remove('show');
if(!e.target.closest('#reviewerSelect2')) document.getElementById('reviewerPanel').classList.remove('show');
if(!e.target.closest('#deptSelect')) document.getElementById('deptPanel').classList.remove('show');
if(!e.target.closest('#orgTreeSelect')) document.getElementById('orgTreePanel').classList.remove('show');
});
/* 点击遮罩关闭员工弹窗 */
@@ -1000,9 +1156,9 @@ document.getElementById('empModal').addEventListener('click',function(e){
var data = editData[id];
if(!data) return;
// 回显表单字段
document.getElementById('planOrg').value = data.org;
document.getElementById('planName').value = data.name;
// 回显表单字段
selectOrgOptionInner(data.org, data.org);
document.getElementById('planName').value = data.name;
// 人员筛选 — 编辑时默认选中全体人员
var radioAll = document.querySelector('input[name="personType"][value="all"]');
@@ -673,26 +673,34 @@ function showToast(msg){var t=document.getElementById('toast');t.textContent=msg
/* ===== 审核操作 ===== */
/* 渲染基本信息卡片 */
function renderBasicInfoCard(row){
var items = [
{label:'计划名称',value:row.planName,span:4},
{label:'姓名',value:row.name},
{label:'员工编号',value:row.empId},
{label:'性别',value:row.gender},
{label:'年龄',value:row.age+' '},
{label:'身高',value:row.height+' cm'},
{label:'所属单位',value:row.org},
{label:'所属部门',value:row.dept},
{label:'提交时间',value:row.submitTime}
];
var html='';
items.forEach(function(item){
var s = item.span ? ' style="grid-column:span '+item.span+'"' : '';
html+='<div class="audit-info-card__item"'+s+'><span class="audit-info-card__label">'+item.label+'</span><span class="audit-info-card__value">'+esc(item.value)+'</span></div>';
});
document.getElementById('auditInfoGrid').innerHTML=html;
}
/* 渲染基本信息卡片 */
function renderBasicInfoCard(row){
var plan = plans.find(function(p){return p.id===row.planId;});
var dateRange = '';
if(plan){
var f = new Date(plan.dateFrom), e = new Date(plan.dateTo);
var totalDays = Math.ceil((e - f) / 86400000) + 1;
dateRange = plan.dateFrom + ' ~ ' + plan.dateTo + ' (' + totalDays + '天)';
}
var items = [
{label:'计划名称',value:row.planName,span:4},
{label:'姓名',value:row.name},
{label:'员工编号',value:row.empId},
{label:'性别',value:row.gender},
{label:'年龄',value:row.age+' 岁'},
{label:'身高',value:row.height+' cm'},
{label:'所属单位',value:row.org},
{label:'所属部门',value:row.dept},
{label:'提交时间',value:row.submitTime},
{label:'活动起止日期',value:dateRange,span:2}
];
var html='';
items.forEach(function(item){
var s = item.span ? ' style="grid-column:span '+item.span+'"' : '';
html+='<div class="audit-info-card__item"'+s+'><span class="audit-info-card__label">'+item.label+'</span><span class="audit-info-card__value">'+esc(item.value)+'</span></div>';
});
document.getElementById('auditInfoGrid').innerHTML=html;
}
/* 渲染指标对比表 */
function renderCmpTable(row){