fix: 同步导航页SITE_MAP与实际文件,优化多模块原型页面

- 校正index.html中6处SITE_MAP页面注册与磁盘文件的差异
- 新增应急就医员工端23个页面原型及资源详情页
- 新增管理端AED子模块7个页面及大病就医详情页
- 优化健康咨询多端页面交互与PRD文档

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-21 14:24:47 +08:00
co-authored by Claude Opus 4.6
parent ac87b887d2
commit f51e598781
67 changed files with 5997 additions and 819 deletions
+1 -1
View File
@@ -35,7 +35,6 @@
stateDiagram-v2
[*] --> 待回复 : 员工发起咨询
待回复 --> 进行中 : 小助手首次回复
进行中 --> 进行中 : 推送专家名片
进行中 --> 已完成 : 任一方结束咨询/有回复但是7天无更新自动变为已完成
进行中 --> 已超时 : 7天首次未回复自动关闭
```
@@ -105,6 +104,7 @@ stateDiagram-v2
- 常用语面板支持分类 Tab:全部 / 问候语 / 注意事项 / 结束语/ 引导语
- 媒体选择面板提供:拍照、图库、推送专家三个选项
- 推送专家后,聊天区自动插入专家名片气泡(含头像、姓名、科室、职称、医院、擅长病种)
- 咨询专家时,没有右上角“结束咨询”和+号里面的“发送专家”功能
**交互说明:**
- 点击咨询人档案卡片或"查看档案":跳转到咨询人健康档案页
@@ -19,6 +19,34 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
.expert-card { background: #fff; border-radius: 12px; margin: 10px 16px 0; padding: 14px; cursor: pointer; box-shadow: 0 1px 4px rgba(0,0,0,0.06); transition: transform 0.15s; }
.expert-card:active { transform: scale(0.98); }
.tag { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 500; background: #e6f4ff; color: #1677ff; margin: 2px 4px 2px 0; }
/* 筛选栏 */
.filter-bar { display: flex; gap: 8px; padding: 10px 16px; background: #fff; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; }
.filter-btn { display: flex; align-items: center; gap: 4px; padding: 6px 12px; border-radius: 6px; background: #f5f5f5; border: none; font-size: 13px; color: #333; cursor: pointer; transition: all 0.2s; }
.filter-btn.active { background: #e6f4ff; color: #1677ff; }
.filter-btn__arrow { font-size: 10px; transition: transform 0.2s; }
.filter-btn.active .filter-btn__arrow { transform: rotate(180deg); }
.filter-selected { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 16px 10px; background: #fff; border-bottom: 1px solid #f0f0f0; flex-shrink: 0; }
.filter-tag { display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px; border-radius: 12px; background: #e6f4ff; color: #1677ff; font-size: 12px; }
.filter-tag__close { cursor: pointer; font-size: 14px; line-height: 1; }
/* 底部筛选面板 */
.filter-panel { display: none; position: absolute; bottom: 0; left: 0; right: 0; height: 55%; background: #fff; border-radius: 16px 16px 0 0; box-shadow: 0 -4px 20px rgba(0,0,0,0.1); z-index: 100; flex-direction: column; }
.filter-panel.active { display: flex; }
.filter-panel__header { display: flex; align-items: center; justify-content: space-between; padding: 14px 16px; border-bottom: 1px solid #f0f0f0; }
.filter-panel__title { font-size: 16px; font-weight: 600; color: #1a1a1a; }
.filter-panel__close { background: none; border: none; font-size: 20px; color: #999; cursor: pointer; padding: 4px; }
.filter-panel__body { display: flex; flex: 1; overflow: hidden; }
.filter-panel__left { width: 110px; background: #f7f8fa; overflow-y: auto; border-right: 1px solid #f0f0f0; }
.filter-panel__left::-webkit-scrollbar { display: none; }
.filter-left-item { padding: 12px 14px; font-size: 13px; color: #666; cursor: pointer; border-left: 3px solid transparent; }
.filter-left-item.active { background: #fff; color: #1677ff; font-weight: 600; border-left-color: #1677ff; }
.filter-panel__right { flex: 1; overflow-y: auto; padding: 12px 14px; }
.filter-panel__right::-webkit-scrollbar { display: none; }
.filter-right-item { display: inline-block; padding: 6px 14px; margin: 4px 6px 4px 0; border-radius: 16px; font-size: 13px; color: #333; background: #f5f5f5; cursor: pointer; transition: all 0.2s; }
.filter-right-item.active { background: #e6f4ff; color: #1677ff; font-weight: 500; }
.filter-overlay { display: none; position: absolute; inset: 0; background: rgba(0,0,0,0.3); z-index: 99; }
.filter-overlay.active { display: block; }
</style>
</head>
<body>
@@ -47,6 +75,14 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
</div>
</div>
<!-- 筛选栏 -->
<div class="filter-bar">
<button class="filter-btn" id="filterDeptBtn" onclick="openFilter('dept')">所属科室 <span class="filter-btn__arrow"></span></button>
<button class="filter-btn" id="filterDiseaseBtn" onclick="openFilter('disease')">擅长疾病 <span class="filter-btn__arrow"></span></button>
</div>
<!-- 已选筛选标签 -->
<div class="filter-selected" id="filterSelectedArea" style="display:none;"></div>
<!-- 专家列表 -->
<div class="scroll-content">
@@ -164,18 +200,116 @@ body { background: #f0f2f5; display: flex; justify-content: center; align-items:
<div style="height:20px;"></div>
</div>
<!-- 筛选遮罩 -->
<div class="filter-overlay" id="filterOverlay" onclick="closeFilter()"></div>
<!-- 筛选面板 -->
<div class="filter-panel" id="filterPanel">
<div class="filter-panel__header">
<span class="filter-panel__title" id="filterPanelTitle">所属科室</span>
<button class="filter-panel__close" onclick="closeFilter()"></button>
</div>
<div class="filter-panel__body">
<div class="filter-panel__left" id="filterLeft"></div>
<div class="filter-panel__right" id="filterRight"></div>
</div>
</div>
</div>
<script>
/**
* 将专家数据存入 sessionStorage,然后跳回聊天页
* text-chat.html 页面加载时会读取并发送名片气泡
* @param {Object} expert - 专家信息对象
*/
/* 推送专家 */
function pushExpert(expert) {
sessionStorage.setItem('pendingExpertCard', JSON.stringify(expert));
location.href = './text-chat.html';
}
/* 筛选数据 */
var DEPT_DATA = {
'内科': ['心内科','神经内科','消化内科','呼吸内科','内分泌科'],
'外科': ['骨科','普外科','神经外科','泌尿外科','心胸外科'],
'妇产科': ['妇科','产科','生殖医学科'],
'儿科': ['小儿内科','小儿外科','新生儿科'],
'五官科': ['眼科','耳鼻喉科','口腔科']
};
var DISEASE_DATA = {
'内科': ['高血压','冠心病','心律失常','偏头痛','脑梗','眩晕症','胃炎','胃溃疡','肠易激综合征','哮喘','慢阻肺','肺炎','糖尿病'],
'外科': ['腰椎间盘突出','颈椎病','骨折','阑尾炎','疝气','胆结石','前列腺增生'],
'妇产科': ['月经不调','子宫肌瘤','多囊卵巢','妊娠高血压'],
'儿科': ['小儿感冒','小儿腹泻','手足口病','新生儿黄疸'],
'五官科': ['近视','白内障','鼻炎','中耳炎','龋齿']
};
var currentFilterType = '';
var currentLeftIdx = 0;
var selectedDept = '';
var selectedDisease = '';
function openFilter(type) {
currentFilterType = type;
currentLeftIdx = 0;
document.getElementById('filterPanelTitle').textContent = type === 'dept' ? '所属科室' : '擅长疾病';
document.getElementById('filterDeptBtn').classList.toggle('active', type === 'dept');
document.getElementById('filterDiseaseBtn').classList.toggle('active', type === 'disease');
renderLeft();
document.getElementById('filterOverlay').classList.add('active');
document.getElementById('filterPanel').classList.add('active');
}
function closeFilter() {
document.getElementById('filterOverlay').classList.remove('active');
document.getElementById('filterPanel').classList.remove('active');
document.getElementById('filterDeptBtn').classList.remove('active');
document.getElementById('filterDiseaseBtn').classList.remove('active');
}
function renderLeft() {
var data = currentFilterType === 'dept' ? DEPT_DATA : DISEASE_DATA;
var keys = Object.keys(data);
var html = '';
keys.forEach(function(k, i) {
html += '<div class="filter-left-item' + (i === currentLeftIdx ? ' active' : '') + '" onclick="selectLeft(' + i + ')">' + k + '</div>';
});
document.getElementById('filterLeft').innerHTML = html;
renderRight(keys[currentLeftIdx]);
}
function selectLeft(idx) {
currentLeftIdx = idx;
renderLeft();
}
function renderRight(parentKey) {
var data = currentFilterType === 'dept' ? DEPT_DATA : DISEASE_DATA;
var items = data[parentKey] || [];
var current = currentFilterType === 'dept' ? selectedDept : selectedDisease;
var html = '';
items.forEach(function(item) {
html += '<div class="filter-right-item' + (item === current ? ' active' : '') + '" onclick="selectRight(\'' + item + '\')">' + item + '</div>';
});
document.getElementById('filterRight').innerHTML = html;
}
function selectRight(val) {
if (currentFilterType === 'dept') { selectedDept = val; }
else { selectedDisease = val; }
closeFilter();
renderSelectedTags();
}
function renderSelectedTags() {
var area = document.getElementById('filterSelectedArea');
var html = '';
if (selectedDept) { html += '<span class="filter-tag">' + selectedDept + ' <span class="filter-tag__close" onclick="clearFilter(\'dept\')">×</span></span>'; }
if (selectedDisease) { html += '<span class="filter-tag">' + selectedDisease + ' <span class="filter-tag__close" onclick="clearFilter(\'disease\')">×</span></span>'; }
area.innerHTML = html;
area.style.display = html ? 'flex' : 'none';
}
function clearFilter(type) {
if (type === 'dept') { selectedDept = ''; }
else { selectedDisease = ''; }
renderSelectedTags();
}
</script>
</body>
</html>