-
💬 咨询小助手
-
-
首页点击「小助手」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;i
l.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}`);
+