feat: 导航页卡片增加设计状态标识(待设计/设计中/已完成)

- 卡片右上角显示状态pill标签,三种颜色区分
- 设计中的模块卡片中央显示圆形虚线水印"暂未定稿"
- 页数徽章移至右下角,PRD链接左下角,底部行水平对齐
- 健康应急APP改为grid布局与其他tab统一
- 标记各模块设计完成状态(done字段控制)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
冯普
2026-05-09 18:19:52 +08:00
co-authored by Claude Opus 4.6
parent 77edb95669
commit f15bfed853
+69 -49
View File
@@ -56,9 +56,8 @@ body { background: var(--background); font-family: -apple-system, BlinkMacSystem
@keyframes fadeUp { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
/* ===== 模块网格 ===== */
.module-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 20px; }
.module-grid--center { justify-content: center; display: flex; flex-wrap: wrap; gap: 20px; }
.module-grid--center .module-card { width: 320px; flex-shrink: 0; }
.module-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 20px; align-items: stretch; }
.module-grid--center { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 20px; max-width: 960px; margin: 0 auto; align-items: stretch; }
/* ===== 角色分组 ===== */
.role-group { margin-bottom: 28px; text-align: center; }
@@ -80,20 +79,32 @@ body { background: var(--background); font-family: -apple-system, BlinkMacSystem
}
/* ===== 模块卡片 ===== */
.module-card { position: relative; background: var(--card-bg); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm); padding: 20px; transition: all .25s ease; border: 1.5px solid var(--border); cursor: pointer; z-index: 1; }
.module-card { position: relative; background: var(--card-bg); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm); padding: 16px 20px; transition: all .25s ease; border: 1.5px solid var(--border); cursor: pointer; z-index: 1; display: flex; flex-direction: column; justify-content: space-between; }
.module-card--pop-open { z-index: 200; }
.module-card:hover { box-shadow: var(--shadow-lg); transform: translateY(-3px); }
.module-card--ready { border-color: var(--green-border); animation: breathe 3s ease-in-out infinite; }
.module-card--ready:hover { border-color: var(--green); animation: none; box-shadow: 0 8px 24px rgba(82,196,26,0.2); }
.module-card--wip { border-color: #ffe58f; }
.module-card--wip:hover { border-color: var(--warning); box-shadow: 0 8px 24px rgba(250,173,20,0.15); }
.module-card--empty { opacity: 0.55; border-style: dashed; border-color: #d0d5dd; cursor: default; }
.module-card--empty:hover { transform: none; box-shadow: var(--shadow-sm); }
.module-card__header { display: flex; align-items: center; justify-content: space-between; }
/* ===== 圆形水印 ===== */
.module-card__watermark { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 64px; height: 64px; border-radius: 50%; border: 2px dashed rgba(250,173,20,0.28); display: flex; align-items: center; justify-content: center; pointer-events: none; z-index: 0; }
.module-card__watermark-text { font-size: 11px; font-weight: 700; color: rgba(250,140,22,0.28); text-align: center; line-height: 1.3; letter-spacing: 0.5px; }
/* ===== 卡片头部行:左名称 + 右状态标签 ===== */
.module-card__header { display: flex; align-items: center; justify-content: space-between; position: relative; z-index: 1; }
.module-card__name { font-size: 15px; font-weight: 700; color: var(--text-primary); }
.module-card__tag { position: relative; font-size: 11px; padding: 3px 10px; border-radius: 12px; font-weight: 600; letter-spacing: 0.3px; }
.module-card__tag--ready { background: var(--green-light); color: #389e0d; border: 1px solid var(--green-border); cursor: pointer; transition: all .15s; }
.module-card__tag--ready:hover { background: #d9f7be; transform: scale(1.05); }
.module-card__tag--pending { background: #fffbe6; color: #d48806; border: 1px solid #ffe58f; }
.module-card__empty-hint { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text-placeholder); margin-top: 10px; }
.module-card__status { font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 10px; letter-spacing: 0.3px; flex-shrink: 0; }
.module-card__status--pending { background: #f5f5f5; color: #999; border: 1px solid #e8e8e8; }
.module-card__status--wip { background: #fff7e6; color: #d46b08; border: 1px solid #ffd591; }
.module-card__status--done { background: var(--green-light); color: #389e0d; border: 1px solid var(--green-border); }
/* ===== 底部行:PRD左 + 页数右 ===== */
.module-card__bottom { display: flex; align-items: center; justify-content: space-between; margin-top: 12px; position: relative; z-index: 1; }
.module-card__page-count { font-size: 11px; padding: 3px 10px; border-radius: 12px; font-weight: 600; letter-spacing: 0.3px; background: var(--primary-light); color: var(--primary); border: 1px solid #91caff; cursor: pointer; transition: all .15s; position: relative; margin-left: auto; }
.module-card__page-count:hover { background: #bae0ff; transform: scale(1.05); }
/* ===== 悬浮页面列表 ===== */
.page-popover { display: none; position: absolute; top: 100%; right: 0; margin-top: 6px; background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--radius-md); box-shadow: 0 8px 30px rgba(0,0,0,0.15); padding: 8px 0; z-index: 100; min-width: 200px; max-height: 320px; overflow-y: auto; animation: popIn .2s ease; }
@@ -107,7 +118,6 @@ body { background: var(--background); font-family: -apple-system, BlinkMacSystem
.page-popover__item--dialog:hover { background: #fff7e6; color: #ad4e00; }
/* ===== 卡片底部 PRD 链接 ===== */
.module-card__footer { display: flex; justify-content: flex-start; margin-top: 10px; }
.module-card__prd { font-size: 12px; color: var(--primary); cursor: pointer; text-decoration: none; display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border-radius: var(--radius-sm); transition: all .15s; }
.module-card__prd:hover { background: var(--primary-light); color: var(--primary-dark); }
.module-card__prd svg { flex-shrink: 0; }
@@ -222,7 +232,7 @@ const SITE_MAP = [
{ name:'心脑血管病预防', dir:'web-admin/cardiovascular', pages:[] },
{ name:'糖尿病预防', dir:'web-admin/diabetes', pages:[] },
{ name:'癌症预防', dir:'web-admin/cancer', pages:[] },
{ name:'专家咨询(管理员)', dir:'web-admin/health-consult', entry:'history-expert.html', prd:'web-admin/health-consult/doc/PRD.md', pages:[
{ name:'专家咨询(管理员)', dir:'web-admin/health-consult', entry:'history-expert.html', prd:'web-admin/health-consult/doc/PRD.md', done:true, pages:[
{ file:'history-expert.html', label:'专家咨询记录' },
{ file:'video-detail-pending-confirm.html', label:'视频详情-待确认' },
{ file:'video-detail-pending-start.html', label:'视频详情-待开始' },
@@ -254,7 +264,7 @@ const SITE_MAP = [
{ file:'config-disease-dialog.html', label:'疾病配置弹窗', dialog:true },
{ file:'config-phrase-dialog.html', label:'常用语弹窗', dialog:true }
]},
{ name:'专家咨询(小助手)', dir:'web-admin/health-consult/assistant', entry:'current-consult.html', prd:'web-admin/health-consult/assistant/doc/PRD.md', pages:[
{ name:'专家咨询(小助手)', dir:'web-admin/health-consult/assistant', entry:'current-consult.html', prd:'web-admin/health-consult/assistant/doc/PRD.md', done:true, pages:[
{ file:'current-consult.html', label:'当前咨询' },
{ file:'chat-message.html', label:'对话消息' },
{ file:'history-consult.html', label:'历史咨询' },
@@ -279,7 +289,7 @@ const SITE_MAP = [
{ file:'report-detail-dialog.html', label:'报表详情弹窗', dialog:true },
{ file:'expert-schedule-dialog.html', label:'专家排班弹窗', dialog:true }
]},
{ name:'应急就医(管理员)', dir:'web-admin/emergency-dispatch/admin', entry:'archive-personal.html', prd:'web-admin/emergency-dispatch/admin/doc/PRD.md', pages:[
{ name:'应急就医(管理员)', dir:'web-admin/emergency-dispatch/admin', entry:'archive-personal.html', prd:'web-admin/emergency-dispatch/admin/doc/PRD.md', done:true, pages:[
{ file:'archive-personal.html', label:'个人应急数据' },
{ file:'archive-personal-detail.html', label:'个人应急数据详情' },
{ file:'archive-personal-detail-illness.html', label:'个人大病就医详情' },
@@ -327,7 +337,7 @@ const SITE_MAP = [
{ file:'exception-dirty.html', label:'系统脏数据' },
{ file:'exception-result.html', label:'结果异常' }
]},
{ name:'应急就医(操作人员)', dir:'web-admin/emergency-dispatch/operator', entry:'emergency-active.html', prd:'web-admin/emergency-dispatch/operator/doc/PRD.md', pages:[
{ name:'应急就医(操作人员)', dir:'web-admin/emergency-dispatch/operator', entry:'emergency-active.html', prd:'web-admin/emergency-dispatch/operator/doc/PRD.md', done:true, pages:[
{ file:'emergency-active.html', label:'正在应急' },
{ file:'work-order.html', label:'应急工单' },
{ file:'call-record.html', label:'通话记录' },
@@ -335,14 +345,14 @@ const SITE_MAP = [
{ file:'serious-illness.html', label:'大病就医' },
{ file:'chat-message.html', label:'对话消息' }
]},
{ name:'应急就医(专业人员)', dir:'web-admin/emergency-dispatch/professional', entry:'professional.html', prd:'web-admin/emergency-dispatch/professional/doc/PRD.md', pages:[
{ name:'应急就医(专业人员)', dir:'web-admin/emergency-dispatch/professional', entry:'professional.html', prd:'web-admin/emergency-dispatch/professional/doc/PRD.md', done:true, pages:[
{ file:'professional.html', label:'正在应急' },
{ file:'chat-message.html', label:'对话消息' }
]},
{ name:'一线医疗', dir:'web-admin/frontline-medical', pages:[] }
]},
{ id:'employee-app', label:'员工端 APP', icon:'app', color:'#95de64', modules:[
{ name:'AI', dir:'employee-app/ai', pages:[] },
{ name:'AI会话', dir:'employee-app/ai', pages:[] },
{ name:'应用主页', dir:'employee-app/home', entry:'index.html', pages:[
{n:'应用主页(收起态)',f:'index.html'},
] },
@@ -388,7 +398,7 @@ const SITE_MAP = [
{ name:'心脑血管病预防', dir:'employee-app/cardiovascular', pages:[] },
{ name:'糖尿病预防', dir:'employee-app/diabetes', pages:[] },
{ name:'癌症预防', dir:'employee-app/cancer', pages:[] },
{ name:'健康咨询', dir:'employee-app/health-consult', prd:'employee-app/health-consult/doc/PRD.md', pages:[
{ name:'健康咨询', dir:'employee-app/health-consult', prd:'employee-app/health-consult/doc/PRD.md', done:true, pages:[
{ file:'index.html', label:'咨询首页' }, { file:'search.html', label:'综合搜索' },
{ file:'find-expert.html', label:'找专家' }, { file:'expert-list.html', label:'专家列表' },
{ file:'expert-profile.html', label:'专家主页' }, { file:'expert-reviews.html', label:'专家评价' },
@@ -409,7 +419,7 @@ const SITE_MAP = [
{ file:'select-report-dialog.html', label:'选择报告弹窗', dialog:true },
{ file:'consult-flowchart.html', label:'咨询流程图' }
]},
{ name:'应急就医', dir:'employee-app/emergency-medical', entry:'index.html', prd:'employee-app/emergency-medical/doc/PRD.md', pages:[
{ name:'应急就医', dir:'employee-app/emergency-medical', entry:'index.html', prd:'employee-app/emergency-medical/doc/PRD.md', done:true, pages:[
{ file:'index.html', label:'应急就医主页' },
{ file:'emergency-chat.html', label:'应急对话' },
{ file:'resource-map.html', label:'应急资源地图' },
@@ -457,7 +467,7 @@ const SITE_MAP = [
{ id:'emergency-app', label:'健康应急 APP', icon:'emergency', color:'#ffc069',
roles:[
{ role:'咨询专家', id:'expert', modules:[
{ name:'工作台', dir:'emergency-app/expert/workbench', prd:'emergency-app/expert/doc/PRD.md', pages:[
{ name:'工作台', dir:'emergency-app/expert/workbench', prd:'emergency-app/expert/doc/PRD.md', done:true, pages:[
{file:'index.html',label:'工作台首页'},{file:'text-chat.html',label:'图文咨询'},
{file:'text-chat-done.html',label:'图文咨询完成'},
{file:'text-consult-done.html',label:'咨询完成'},{file:'text-consult-timeout.html',label:'咨询超时'},
@@ -467,10 +477,10 @@ const SITE_MAP = [
{file:'video-done.html',label:'视频完成'},
{file:'video-cancelled.html',label:'视频已取消'},{file:'video-rejected.html',label:'视频已拒绝'}
]},
{ name:'知识库', dir:'emergency-app/expert/knowledge', pages:[
{ name:'知识库', dir:'emergency-app/expert/knowledge', done:true, pages:[
{file:'index.html',label:'知识库首页'},{file:'detail.html',label:'知识详情'}
]},
{ name:'我的', dir:'emergency-app/expert/profile', pages:[
{ name:'我的', dir:'emergency-app/expert/profile', done:true, pages:[
{file:'index.html',label:'个人中心'},{file:'edit-profile.html',label:'编辑资料'},
{file:'edit-diseases.html',label:'擅长疾病'},
{file:'change-pwd.html',label:'修改密码'},{file:'schedule.html',label:'排班设置'},
@@ -478,7 +488,7 @@ const SITE_MAP = [
]}
]},
{ role:'咨询小助手', id:'assistant', modules:[
{ name:'工作台', dir:'emergency-app/assistant/workbench', prd:'emergency-app/assistant/doc/PRD.md', pages:[
{ name:'工作台', dir:'emergency-app/assistant/workbench', prd:'emergency-app/assistant/doc/PRD.md', done:true, pages:[
{file:'index.html',label:'工作台首页'},{file:'text-chat.html',label:'图文咨询'},
{file:'text-chat-done.html',label:'图文咨询完成'},
{file:'text-consult-done.html',label:'咨询完成'},{file:'text-consult-timeout.html',label:'咨询超时'},
@@ -486,16 +496,16 @@ const SITE_MAP = [
{file:'end-consult-dialog.html',label:'结束咨询弹窗',dialog:true},
{file:'push-expert.html',label:'推送专家'}
]},
{ name:'知识库', dir:'emergency-app/assistant/knowledge', pages:[
{ name:'知识库', dir:'emergency-app/assistant/knowledge', done:true, pages:[
{file:'index.html',label:'知识库首页'},{file:'detail.html',label:'知识详情'}
]},
{ name:'我的', dir:'emergency-app/assistant/profile', pages:[
{ name:'我的', dir:'emergency-app/assistant/profile', done:true, pages:[
{file:'index.html',label:'个人中心'},{file:'edit-profile.html',label:'编辑资料'},
{file:'change-pwd.html',label:'修改密码'}
] }
]},
{ role:'应急操作人员', id:'operator', modules:[
{name:'工作台',dir:'emergency-app/operator/workbench',prd:'emergency-app/operator/doc/PRD.md',pages:[
{name:'工作台',dir:'emergency-app/operator/workbench',prd:'emergency-app/operator/doc/PRD.md',done:true,pages:[
{file:'index.html',label:'工作台首页(应急求助)'},
{file:'serious-illness-list.html',label:'大病就医首页'},
{file:'emergency-chat.html',label:'应急聊天'},
@@ -511,10 +521,10 @@ const SITE_MAP = [
{file:'serious-illness-detail-done.html',label:'大病就医详情(已完成)'},
{file:'serious-illness-detail-cancelled.html',label:'大病就医详情(已取消)'}
]},
{name:'知识库',dir:'emergency-app/operator/knowledge',pages:[
{name:'知识库',dir:'emergency-app/operator/knowledge',done:true,pages:[
{file:'index.html',label:'知识库首页'},{file:'article-detail.html',label:'知识详情'}
]},
{name:'我的',dir:'emergency-app/operator/profile',pages:[
{name:'我的',dir:'emergency-app/operator/profile',done:true,pages:[
{file:'index.html',label:'我的主页'},
{file:'duty-schedule.html',label:'值班信息'},
{file:'duty-config.html',label:'排班配置'},
@@ -523,7 +533,7 @@ const SITE_MAP = [
]}
]},
{ role:'应急专业人员', id:'professional', modules:[
{ name:'工作台', dir:'emergency-app/professional/workbench', prd:'emergency-app/professional/doc/PRD.md', pages:[
{ name:'工作台', dir:'emergency-app/professional/workbench', prd:'emergency-app/professional/doc/PRD.md', done:true, pages:[
{file:'index.html',label:'工作台首页'},
{file:'emergency-chat-ongoing.html',label:'应急聊天(进行中)'},
{file:'emergency-chat-done.html',label:'应急聊天(已结束)'},
@@ -532,17 +542,17 @@ const SITE_MAP = [
{file:'work-order-detail.html',label:'工单详情(已完成)'},
{file:'work-order-detail-ongoing.html',label:'工单详情(进行中)'}
]},
{ name:'知识库', dir:'emergency-app/professional/knowledge', pages:[
{ name:'知识库', dir:'emergency-app/professional/knowledge', done:true, pages:[
{file:'index.html',label:'知识库首页'},{file:'article-detail.html',label:'知识详情'}
]},
{ name:'我的', dir:'emergency-app/professional/profile', pages:[
{ name:'我的', dir:'emergency-app/professional/profile', done:true, pages:[
{file:'index.html',label:'个人中心'},
{file:'duty-schedule.html',label:'值班信息'},
{file:'edit-profile.html',label:'修改个人信息'},{file:'change-pwd.html',label:'修改密码'}
]}
]},
{ role:'应急驻场人员', id:'onsite', modules:[
{name:'工作台',dir:'emergency-app/onsite/workbench',prd:'emergency-app/onsite/doc/PRD.md',pages:[
{name:'工作台',dir:'emergency-app/onsite/workbench',prd:'emergency-app/onsite/doc/PRD.md',done:true,pages:[
{file:'index.html',label:'工作台首页(应急求助)'},
{file:'serious-illness-list.html',label:'大病就医首页'},
{file:'work-order-detail-ongoing.html',label:'工单详情(待处理)'},
@@ -551,10 +561,10 @@ const SITE_MAP = [
{file:'serious-illness-detail-done.html',label:'大病就医详情(已完成)'},
{file:'serious-illness-detail-cancelled.html',label:'大病就医详情(已取消)'}
]},
{name:'知识库',dir:'emergency-app/onsite/knowledge',pages:[
{name:'知识库',dir:'emergency-app/onsite/knowledge',done:true,pages:[
{file:'index.html',label:'知识库首页'},{file:'article-detail.html',label:'知识详情'}
]},
{name:'我的',dir:'emergency-app/onsite/profile',pages:[
{name:'我的',dir:'emergency-app/onsite/profile',done:true,pages:[
{file:'index.html',label:'个人中心'},
{file:'edit-profile.html',label:'修改个人信息'},{file:'change-pwd.html',label:'修改密码'}
]}
@@ -566,8 +576,8 @@ const SITE_MAP = [
]}
],
shared:[
{ name:'AI助手', dir:'emergency-app/ai-assistant', pages:[{file:'index.html',label:'AI助手'}] },
{ name:'消息', dir:'emergency-app/message', pages:[
{ name:'AI助手', dir:'emergency-app/ai-assistant', done:true, pages:[{file:'index.html',label:'AI助手'}] },
{ name:'消息', dir:'emergency-app/message', done:true, pages:[
{file:'index.html',label:'消息列表'},{file:'contacts.html',label:'通讯录'},{file:'im-chat.html',label:'聊天'}
]}
]
@@ -598,30 +608,40 @@ tabNav.innerHTML += `<div class="tab-nav__item" data-idx="${prdTabIdx}">${ICONS.
let openPopover = null;
function cardHTML(mod, uid) {
const has = mod.pages.length > 0;
const cls = has ? 'module-card module-card--ready' : 'module-card module-card--empty';
const isDone = has && mod.done;
const isWip = has && !mod.done;
const cls = isDone ? 'module-card module-card--ready' : isWip ? 'module-card module-card--wip' : 'module-card module-card--empty';
const mainHref = has ? `${mod.dir}/${mod.entry || 'index.html'}` : '';
const onclick = has ? `onclick="window.open('${mainHref}','_blank')"` : '';
let tagHtml = '';
/* 右上角状态标签 */
let statusHtml = '';
if (isDone) statusHtml = '<span class="module-card__status module-card__status--done">已完成</span>';
else if (isWip) statusHtml = '<span class="module-card__status module-card__status--wip">设计中</span>';
else statusHtml = '<span class="module-card__status module-card__status--pending">待设计</span>';
/* 圆形水印(仅设计中) */
let watermarkHtml = '';
if (isWip) watermarkHtml = '<div class="module-card__watermark"><span class="module-card__watermark-text">暂未<br>定稿</span></div>';
/* 底部行:左PRD + 右页数 */
let prdLink = '';
if (mod.prd) {
prdLink = `<a class="module-card__prd" onclick="event.stopPropagation();openMdPreview('${mod.prd}','${mod.name} PRD')">${ICONS.prdSmall}PRD文档</a>`;
}
let pageCountHtml = '';
if (has) {
/* 生成悬浮列表 */
let popItems = mod.pages.map(p => {
const dcls = p.dialog ? ' page-popover__item--dialog' : '';
const icon = p.dialog ? ICONS.dialog : ICONS.page;
return `<a class="page-popover__item${dcls}" href="${mod.dir}/${p.file}" target="_blank">${icon}${p.label}</a>`;
}).join('');
tagHtml = `<span class="module-card__tag module-card__tag--ready" data-pop="${uid}" onclick="event.stopPropagation();togglePop('${uid}')">${mod.pages.length} 页</span><div class="page-popover" id="pop-${uid}" onclick="event.stopPropagation()"><div class="page-popover__title">页面列表</div>${popItems}</div>`;
} else {
tagHtml = '<span class="module-card__tag module-card__tag--pending">待设计</span>';
pageCountHtml = `<span class="module-card__page-count" data-pop="${uid}" onclick="event.stopPropagation();togglePop('${uid}')">${mod.pages.length} 页</span><div class="page-popover" id="pop-${uid}" onclick="event.stopPropagation()"><div class="page-popover__title">页面列表</div>${popItems}</div>`;
}
const body = has ? '' : `<div class="module-card__empty-hint">${ICONS.empty}暂无原型页面</div>`;
/* PRD 文档链接(右下角) */
let prdHtml = '';
if (mod.prd) {
prdHtml = `<div class="module-card__footer"><a class="module-card__prd" onclick="event.stopPropagation();openMdPreview('${mod.prd}','${mod.name} PRD')">${ICONS.prdSmall}PRD文档</a></div>`;
}
return `<div class="${cls}" ${onclick}><div class="module-card__header"><span class="module-card__name">${mod.name}</span>${tagHtml}</div>${body}${prdHtml}</div>`;
/* 底部行占位:无内容时保持高度一致 */
const bottomPlaceholder = (!prdLink && !pageCountHtml) ? '<span>&nbsp;</span>' : '';
return `<div class="${cls}" ${onclick}>${watermarkHtml}<div class="module-card__header"><span class="module-card__name">${mod.name}</span>${statusHtml}</div><div class="module-card__bottom">${prdLink}${pageCountHtml}${bottomPlaceholder}</div></div>`;
}
function togglePop(uid) {