From da61152de79d2ab17ed193d8eb5ccce6e9b9b44f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=AF=E6=99=AE?= <18691763612@163.com> Date: Fri, 17 Apr 2026 08:35:38 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BF=AE=E6=94=B9=E5=91=98=E5=B7=A5APP?= =?UTF-8?q?=E5=92=A8=E8=AF=A2=E4=B8=9A=E5=8A=A1=E6=B5=81=E7=A8=8B=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../health-consult/consult-flowchart.html | 568 +++++++++--------- 1 file changed, 294 insertions(+), 274 deletions(-) diff --git a/employee-app/health-consult/consult-flowchart.html b/employee-app/health-consult/consult-flowchart.html index e02e516..f5ee2e8 100644 --- a/employee-app/health-consult/consult-flowchart.html +++ b/employee-app/health-consult/consult-flowchart.html @@ -3,292 +3,312 @@ - 健康咨询 - 员工咨询流程图 | 健康长庆原型 + 健康咨询 - 员工咨询业务流程图 -
-
入口 / 导航页
-
功能页面
-
操作 / 选择
-
弹窗 / 对话框
-
终态
-
进行中
-
已完成
-
已超时/待开始
-
已拒绝
-
待确认
-
- - -
-
健康咨询首页index.html
-
-
- - -
- - -
-
📝 咨询专家 — 图文咨询
- -
找专家find-expert.html
-
按医院/科室/疾病
- -
专家列表expert-list.html
-
- -
专家详情expert-profile.html
-
点击「图文咨询」
- -
选择咨询人 & 健康档案select-person.html
-
- -
进行中 — 图文聊天text-chat.html
- - - -
-
-
-
已超时record-detail-timeout.html
-
-
再次咨询
-
-
-
已完成·未评价record-detail-unrated.html
-
评价
-
评价医生rate-doctor.html
-
-
已完成·已评价record-detail-rated.html
-
-
-
结束咨询确认end-consult-dialog.html
-
确认结束
-
评价医生rate-doctor.html
-
-
+
+ 起止框
- - -
-
🎥 咨询专家 — 视频咨询
- -
找专家find-expert.html
-
按医院/科室/疾病
- -
专家列表expert-list.html
-
- -
专家详情expert-profile.html
-
点击「视频咨询」
- -
预约视频咨询video-booking.html
-
选择日期时段
- -
选择咨询人 & 健康档案select-person.html
-
- -
预约成功video-success.html
- - - -
-
待确认video-detail-confirming.html
-
医生确认
- -
待开始video-detail-pending.html
-
进入视频
- -
已完成video-detail-done.html
- - -
-
-
-
已取消video-detail-cancelled.html
-
-
重新预约
-
-
-
已拒绝video-detail-rejected.html
-
-
重新预约
-
-
+
+ 处理框
- - -
-
💬 咨询小助手
- -
首页点击「小助手」index.html
-
- -
进行中 — 小助手聊天assistant-chat.html
-
结束咨询
- -
已完成 — 历史记录assistant-chat-history.html
- - -
- -
我的咨询my-records.html
-
- 一级Tab:咨询专家 / 小助手
- 二级Tab(专家):图文咨询 / 视频咨询
- 列表按状态跳转到对应详情页 -
- - -
-
选择咨询人弹窗select-person-dialog.html
-
选择体检报告弹窗select-report-dialog.html
-
结束咨询确认弹窗end-consult-dialog.html
-
专家评价列表expert-reviews.html
-
医院详情hospital-detail.html
-
搜索页search.html
-
选择咨询记录select-record.html
-
咨询人详情consult-person-detail.html
-
添加健康档案add-health-record.html
-
+
+ 判断框 +
+
+ 注释框 +
+
+ 流程线
- - -
- 员工端 · 健康咨询模块 · 业务流程图  |  共 个页面 +
+
+ +/* ===== 注释连线(虚线)[from, to] ===== */ +const noteEdges=[ + ['tw_note1','tw_person'],['tw_note2','tw_chat'], + ['ai_note','ai_chat'],['my_vd_note','my_vd_detail'], +]; +/* ===== 渲染引擎 ===== */ +const NS='http://www.w3.org/2000/svg'; +const svg=document.getElementById('fc'); +const nMap={}; +nodes.forEach(n=>{nMap[n.id]=n;if(!n.w)n.w=W;if(!n.h)n.h=H;}); + +/* 创建SVG元素 */ +function el(tag,attrs){ + const e=document.createElementNS(NS,tag); + for(const k in attrs)e.setAttribute(k,attrs[k]); + return e; +} + +/* 多行文本 */ +function addText(g,txt,cx,cy,fs,fill,fw){ + const lines=txt.split('\n'); + const lh=fs*1.4; + const startY=cy-((lines.length-1)*lh)/2; + lines.forEach((line,i)=>{ + g.appendChild(el('text',{x:cx,y:startY+i*lh,'text-anchor':'middle','dominant-baseline':'central','font-size':fs,'fill':fill||'#333','font-weight':fw||'normal'})).textContent=line; + }); +} + +/* 获取节点锚点 */ +function anchor(n,side){ + const cx=n.x,cy=n.y,hw=n.w/2,hh=n.h/2; + if(n.t==='D'){ + const dhw=Math.max(n.w||DW,DW)/2,dhh=DH/2; + if(side==='t')return[cx,cy-dhh];if(side==='b')return[cx,cy+dhh]; + if(side==='l')return[cx-dhw,cy];if(side==='r')return[cx+dhw,cy]; + } + if(side==='t')return[cx,cy-hh];if(side==='b')return[cx,cy+hh]; + if(side==='l')return[cx-hw,cy];if(side==='r')return[cx+hw,cy]; + return[cx,cy]; +} + +/* 自动选择锚点方向 */ +function autoAnchors(fn,tn){ + const dx=tn.x-fn.x,dy=tn.y-fn.y; + const adx=Math.abs(dx),ady=Math.abs(dy); + if(ady>=adx){return dy>0?['b','t']:['t','b'];} + else{return dx>0?['r','l']:['l','r'];} +} + +/* 绘制箭头连线 */ +function drawEdge(fid,tid,label,waypoints){ + const fn=nMap[fid],tn=nMap[tid]; + if(!fn||!tn)return; + const[fs,ts]=autoAnchors(fn,tn); + const[x1,y1]=anchor(fn,fs); + const[x2,y2]=anchor(tn,ts); + const g=el('g',{}); + const mid=`fc-arrow-${fid}-${tid}`; + // 箭头标记 + if(!document.getElementById('ah')){ + const defs=el('defs',{}); + const mk=el('marker',{id:'ah',viewBox:'0 0 10 10',refX:'9',refY:'5',markerWidth:'8',markerHeight:'8',orient:'auto-start-reverse'}); + mk.appendChild(el('path',{d:'M 0 0 L 10 5 L 0 10 z',fill:'#999'})); + defs.appendChild(mk);svg.appendChild(defs); + } + if(waypoints&&waypoints.length>=4){ + let d=`M${x1},${y1}`; + for(let i=0;il.length*11))+8; + const bh=lines.length*lh+4; + g.appendChild(el('rect',{x:lx-bw/2,y:ly-bh/2,width:bw,height:bh,rx:'3',fill:'#fff',stroke:'none',opacity:'0.9'})); + addText(g,label,lx,ly,10,'#666'); + } + svg.appendChild(g); +} + +/* 绘制注释虚线 */ +function drawNoteEdge(fid,tid){ + const fn=nMap[fid],tn=nMap[tid]; + if(!fn||!tn)return; + const[fs,ts]=autoAnchors(fn,tn); + const[x1,y1]=anchor(fn,fs==='b'?'r':fs==='t'?'r':fs); + const[x2,y2]=anchor(tn,ts==='b'?'l':ts==='t'?'l':ts); + svg.appendChild(el('line',{x1,y1,x2,y2,stroke:'#bbb','stroke-width':'1','stroke-dasharray':'4 3'})); +} + +/* 绘制节点 */ +function drawNode(n){ + const g=el('g',{}); + const cx=n.x,cy=n.y; + if(n.t==='T'){ + const w=n.w,h=n.h; + const fill=n.c||'#e8f4ff',sc=n.sc||'#1677ff'; + g.appendChild(el('rect',{x:cx-w/2,y:cy-h/2,width:w,height:h,rx:h/2,fill:fill,stroke:sc,'stroke-width':'2'})); + addText(g,n.l,cx,cy,13,sc==='#52c41a'?'#389e0d':sc==='#cf1322'?'#cf1322':'#1677ff','600'); + }else if(n.t==='P'){ + const w=n.w,h=n.h; + const fill=n.c||'#fff',sc=n.sc||'#595959'; + g.appendChild(el('rect',{x:cx-w/2,y:cy-h/2,width:w,height:h,rx:6,fill:fill,stroke:sc,'stroke-width':'1.5'})); + addText(g,n.l,cx,cy,12,'#333','500'); + }else if(n.t==='D'){ + const dw=Math.max(n.w||DW,DW),dh=DH; + const pts=`${cx},${cy-dh/2} ${cx+dw/2},${cy} ${cx},${cy+dh/2} ${cx-dw/2},${cy}`; + g.appendChild(el('polygon',{points:pts,fill:'#fffbe6',stroke:'#d48806','stroke-width':'1.5'})); + addText(g,n.l,cx,cy,12,'#8B6914','600'); + }else if(n.t==='N'){ + const w=n.w||140,h=n.h||50; + g.appendChild(el('rect',{x:cx-w/2,y:cy-h/2,width:w,height:h,rx:4,fill:'#fafafa',stroke:'#ccc','stroke-width':'1','stroke-dasharray':'4 2'})); + addText(g,n.l,cx,cy,10,'#999'); + } + svg.appendChild(g); +} + +/* ===== 执行渲染 ===== */ +// 先画连线再画节点(节点覆盖连线) +edges.forEach(e=>drawEdge(e[0],e[1],e[2]||null,e[3]||null)); +noteEdges.forEach(e=>drawNoteEdge(e[0],e[1])); +nodes.forEach(n=>drawNode(n)); + +// 自动计算画布大小 +let maxX=0,maxY=0; +nodes.forEach(n=>{ + const hw=(n.w||W)/2+20,hh=(n.h||H)/2+20; + if(n.x+hw>maxX)maxX=n.x+hw; + if(n.y+hh>maxY)maxY=n.y+hh; +}); +svg.setAttribute('width',maxX+40); +svg.setAttribute('height',maxY+40); +svg.setAttribute('viewBox',`-100 0 ${maxX+160} ${maxY+40}`); + \ No newline at end of file