Files
hms/docs/design/mp-10-mall-pkg.html
iven aa27c5174c docs(mp): 新增小程序全页面 HTML 原型 + UI 优化指南
- 新增 12 个核心页面原型(登录/首页/咨询/预约/商城/健康等)
- 新增医生端分包原型(核心 + 临床两个分包)
- 新增 AI 客服对话页原型
- 新增 MP UI 优化指南文档
- 更新 wiki 基础设施和小程序文档
2026-05-17 00:51:07 +08:00

211 lines
13 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HMS 小程序 — 积分商城分包</title>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{background:#1a1a1a;font-family:-apple-system,'PingFang SC',sans-serif;display:flex;flex-direction:column;align-items:center;padding:40px 20px;gap:24px}
.page-title{color:#999;font-size:13px;letter-spacing:.15em;text-transform:uppercase}
.note{color:#666;font-size:12px;max-width:800px;text-align:center;line-height:1.8}
.screens{display:flex;gap:32px;flex-wrap:wrap;justify-content:center;align-items:flex-start}
.screen-wrap{display:flex;flex-direction:column;align-items:center;gap:10px}
.screen-label{color:#888;font-size:11px;font-style:italic}
</style>
</head>
<body>
<div class="page-title">HMS 小程序 · 积分商城分包</div>
<div class="note">商品详情 + 兑换确认 + 订单列表 + 咨询聊天详情</div>
<div id="root"></div>
<script type="text/babel">
const T={pri:'#C4623A',priL:'#F0DDD4',priD:'#8B3E1F',bg:'#F5F0EB',card:'#FFFFFF',surface:'#EDE8E2',tx:'#2D2A26',tx2:'#5A554F',tx3:'#78716C',bd:'#E8E2DC',bdL:'#F0EBE5',acc:'#5B7A5E',accL:'#E8F0E8',wrn:'#C4873A',wrnL:'#FFF3E0',dan:'#B54A4A',danL:'#FDEAEA',serif:"Georgia,'Times New Roman',serif",sans:"-apple-system,'PingFang SC',sans-serif",r:16,rSm:12,rXs:8};
const F={w:{display:'inline-block',padding:12,background:'#000',borderRadius:60,boxShadow:'0 0 0 2px #1f2937, 0 20px 60px rgba(0,0,0,0.3)',position:'relative'},s:{position:'relative',borderRadius:48,overflow:'hidden',background:'#fff'},c:{position:'absolute',top:54,left:0,right:0,bottom:34,overflow:'auto'}};
function Frame({children,w=370,h=800}){
return(<div style={F.w}><div style={{...F.s,width:w,height:h}}>
<div style={{position:'absolute',top:0,left:0,right:0,height:54,display:'flex',alignItems:'center',justifyContent:'space-between',padding:'0 32px',fontSize:16,fontWeight:600,zIndex:20,pointerEvents:'none',color:'#000'}}>
<span>9:41</span>
<div style={{display:'flex',alignItems:'center',gap:6}}><div style={{width:26,height:12,border:'1.5px solid #000',borderRadius:3,padding:1}}><div style={{width:'85%',height:'100%',background:'#000',borderRadius:1}}/></div></div>
</div>
<div style={{position:'absolute',top:12,left:'50%',transform:'translateX(-50%)',width:124,height:36,background:'#000',borderRadius:999,zIndex:30}}/>
<div style={F.c}>{children}</div>
<div style={{position:'absolute',bottom:10,left:'50%',transform:'translateX(-50%)',width:140,height:5,background:'rgba(0,0,0,0.3)',borderRadius:999,zIndex:10}}/>
</div></div>);
}
function Nav({t}){
return(<div style={{height:44,display:'flex',alignItems:'center',justifyContent:'center',borderBottom:`1px solid ${T.bdL}`,position:'relative'}}>
<span style={{position:'absolute',left:16,color:T.pri,fontSize:20}}></span>
<span style={{fontFamily:T.serif,fontSize:18,fontWeight:700,color:T.tx}}>{t}</span>
</div>);
}
function Tag({label,color=T.acc,bg=T.accL}){
return <span style={{display:'inline-block',padding:'2px 8px',borderRadius:6,fontSize:11,fontWeight:600,color,background:bg}}>{label}</span>;
}
// ── 屏幕1: 商品详情 ──
function ProductDetail(){
return(<div style={{background:T.bg,fontFamily:T.sans}}>
<Nav t="商品详情"/>
<div style={{background:T.surface,height:280,display:'flex',alignItems:'center',justifyContent:'center'}}>
<div style={{width:180,height:180,borderRadius:T.r,background:T.bd,display:'flex',alignItems:'center',justifyContent:'center',flexDirection:'column',gap:8}}>
<div style={{fontSize:36,opacity:.3}}>🩺</div>
<span style={{fontSize:12,color:T.tx3}}>智能血压计</span>
</div>
</div>
<div style={{padding:20,background:T.card,borderRadius:'20px 20px 0 0',marginTop:-16,position:'relative'}}>
<div style={{fontFamily:T.serif,fontSize:20,fontWeight:700,color:T.tx,marginBottom:8}}>智能血压计</div>
<div style={{display:'flex',alignItems:'baseline',gap:10,marginBottom:16}}>
<span style={{fontFamily:T.serif,fontSize:24,fontWeight:700,color:T.pri}}>1,200 积分</span>
<span style={{fontSize:14,color:T.tx3,textDecoration:'line-through'}}>¥199</span>
</div>
<div style={{fontSize:13,color:T.tx2,lineHeight:1.8,marginBottom:20}}>医用级精度蓝牙连接手机自动记录数据支持多人使用大屏显示操作简便适合家庭日常监测</div>
<div style={{display:'flex',flexDirection:'column',gap:10,padding:'14px 16px',background:T.bg,borderRadius:T.rSm,marginBottom:16}}>
{[['品牌','乐心'],['规格','臂式'],['库存','36件']].map(([k,v])=>(
<div key={k} style={{display:'flex',justifyContent:'space-between',fontSize:13}}><span style={{color:T.tx3}}>{k}</span><span style={{color:T.tx,fontWeight:500}}>{v}</span></div>
))}
</div>
<div style={{padding:12,background:T.wrnL,borderRadius:T.rSm,borderLeft:`3px solid ${T.wrn}`}}>
<div style={{fontSize:12,color:T.wrn,fontWeight:600,marginBottom:4}}>温馨提示</div>
<div style={{fontSize:11,color:T.tx2,lineHeight:1.6}}>积分兑换商品不支持退换货请确认需求后再兑换商品将在 7 个工作日内寄出</div>
</div>
</div>
<div style={{position:'sticky',bottom:0,background:T.card,borderTop:`1px solid ${T.bdL}`,padding:'12px 20px',display:'flex',alignItems:'center',gap:12}}>
<div style={{width:48,height:48,border:`1px solid ${T.bd}`,borderRadius:T.rSm,display:'flex',alignItems:'center',justifyContent:'center',fontSize:20}}></div>
<div style={{flex:1,height:48,background:T.pri,borderRadius:T.r,display:'flex',alignItems:'center',justifyContent:'center',color:'#fff',fontFamily:T.serif,fontSize:16,fontWeight:700}}>立即兑换</div>
</div>
</div>);
}
// ── 屏幕2: 兑换确认 ──
function ExchangeConfirm(){
return(<div style={{background:T.bg,fontFamily:T.sans}}>
<Nav t="确认兑换"/>
<div style={{padding:16}}>
<div style={{display:'flex',gap:12,padding:14,background:T.card,borderRadius:T.r,marginBottom:16,boxShadow:'0 1px 4px rgba(0,0,0,0.04)'}}>
<div style={{width:72,height:72,borderRadius:T.rSm,background:T.surface,display:'flex',alignItems:'center',justifyContent:'center',fontSize:24}}>🩺</div>
<div style={{flex:1}}>
<div style={{fontFamily:T.serif,fontSize:15,fontWeight:700,color:T.tx,marginBottom:4}}>智能血压计</div>
<div style={{fontSize:13,color:T.pri,fontWeight:600}}>1,200 积分</div>
<div style={{fontSize:11,color:T.tx3,marginTop:2}}>×1</div>
</div>
</div>
<div style={{padding:16,background:T.card,borderRadius:T.r,marginBottom:16}}>
<div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:10}}>
<span style={{fontSize:14,fontWeight:600,color:T.tx}}>收货信息</span>
<span style={{fontSize:12,color:T.pri,fontWeight:500}}>修改地址 </span>
</div>
<div style={{fontSize:13,color:T.tx,fontWeight:500,marginBottom:2}}>张三 · 138****1234</div>
<div style={{fontSize:12,color:T.tx3,lineHeight:1.5}}>北京市朝阳区建国路88号健康大厦12层</div>
</div>
<div style={{padding:16,background:T.card,borderRadius:T.r,marginBottom:24}}>
<div style={{fontSize:14,fontWeight:600,color:T.tx,marginBottom:12}}>兑换明细</div>
{[['商品积分','1,200'],['运费','¥0.00'],['应扣积分','1,200'],['剩余积分','80']].map(([k,v],i)=>(
<div key={k} style={{display:'flex',justifyContent:'space-between',paddingBottom:i<3?8:0,marginBottom:i<3?8:0,borderBottom:i<3?`1px dashed ${T.bdL}`:'none'}}>
<span style={{fontSize:13,color:T.tx3}}>{k}</span>
<span style={{fontSize:13,color:i===2?T.pri:i===3?T.acc:T.tx,fontWeight:i>=2?600:400}}>{v}</span>
</div>
))}
</div>
<div style={{height:50,background:T.pri,borderRadius:T.r,display:'flex',alignItems:'center',justifyContent:'center',color:'#fff',fontFamily:T.serif,fontSize:16,fontWeight:700}}>确认兑换</div>
</div>
</div>);
}
// ── 屏幕3: 订单列表 ──
function OrderList(){
const tabs=['全部','待发货','已发货','已完成'];
const orders=[
{id:'HX20260515001',name:'智能血压计',pts:'1,200',status:'待发货',statusBg:T.wrnL,statusColor:T.wrn,date:'2026-05-15'},
{id:'HX20260510002',name:'维生素D3 60粒',pts:'360',status:'已发货',statusBg:T.accL,statusColor:T.acc,date:'2026-05-10'},
{id:'HX20260428003',name:'健康手册',pts:'150',status:'已完成',statusBg:T.bg,statusColor:T.tx3,date:'2026-04-28'},
];
return(<div style={{background:T.bg,fontFamily:T.sans}}>
<Nav t="兑换记录"/>
<div style={{display:'flex',padding:'0 16px',gap:0,background:T.card,borderBottom:`1px solid ${T.bdL}`}}>
{tabs.map((t,i)=>(
<div key={t} style={{flex:1,textAlign:'center',padding:'12px 0',fontSize:13,fontWeight:i===0?600:400,color:i===0?T.pri:T.tx3,borderBottom:i===0?`2px solid ${T.pri}`:'2px solid transparent'}}>{t}</div>
))}
</div>
<div style={{padding:16,display:'flex',flexDirection:'column',gap:12}}>
{orders.map(o=>(
<div key={o.id} style={{padding:16,background:T.card,borderRadius:T.r,boxShadow:'0 1px 4px rgba(0,0,0,0.04)'}}>
<div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:10}}>
<span style={{fontSize:11,color:T.tx3}}>订单号 {o.id}</span>
<Tag label={o.status} color={o.statusColor} bg={o.statusBg}/>
</div>
<div style={{display:'flex',justifyContent:'space-between',alignItems:'center'}}>
<div>
<div style={{fontSize:14,fontWeight:600,color:T.tx,marginBottom:2}}>{o.name}</div>
<div style={{fontSize:12,color:T.tx3}}>{o.date}</div>
</div>
<div style={{fontFamily:T.serif,fontSize:16,fontWeight:700,color:T.pri}}>{o.pts} <span style={{fontSize:11,fontWeight:400}}>积分</span></div>
</div>
</div>
))}
</div>
</div>);
}
// ── 屏幕4: 咨询聊天详情 ──
function ChatDetail(){
const Bubble=({left,children})=>(
<div style={{display:'flex',justifyContent:left?'flex-start':'flex-end',padding:'0 16px',marginBottom:10}}>
<div style={{maxWidth:'75%',padding:'10px 14px',borderRadius:left?'4px 16px 16px 16px':'16px 4px 16px 16px',background:left?T.card:T.priL,color:T.tx,fontSize:13,lineHeight:1.6}}>{children}</div>
</div>
);
return(<div style={{background:T.bg,fontFamily:T.sans,height:'100%',display:'flex',flexDirection:'column'}}>
<div style={{height:44,display:'flex',alignItems:'center',justifyContent:'center',borderBottom:`1px solid ${T.bdL}`,position:'relative',background:T.card}}>
<span style={{position:'absolute',left:16,color:T.pri,fontSize:20}}></span>
<div style={{display:'flex',alignItems:'center',gap:8}}>
<span style={{fontFamily:T.serif,fontSize:16,fontWeight:700,color:T.tx}}>王医生 · 心内科</span>
<div style={{width:8,height:8,background:T.acc,borderRadius:'50%'}}/>
</div>
</div>
<div style={{flex:1,overflow:'auto',padding:'16px 0'}}>
<div style={{textAlign:'center',fontSize:11,color:T.tx3,marginBottom:16}}>今天 10:32</div>
<Bubble left>化验结果已出您的血红蛋白偏低95g/L属于轻度贫血</Bubble>
<Bubble left={false}>需要怎么处理呢严重吗</Bubble>
<Bubble left>不算严重建议补充铁剂配合维生素C促进吸收我给您开个处方</Bubble>
<div style={{padding:'0 16px',marginBottom:10}}>
<div style={{padding:14,background:T.card,borderRadius:T.r,borderLeft:`3px solid ${T.acc}`}}>
<div style={{fontSize:12,color:T.acc,fontWeight:600,marginBottom:6}}>处方建议</div>
<div style={{fontSize:14,fontWeight:600,color:T.tx,marginBottom:4}}>硫酸亚铁片</div>
<div style={{fontSize:12,color:T.tx2,lineHeight:1.5}}>用法每次1片每日3次饭后服用</div>
<div style={{fontSize:11,color:T.tx3,marginTop:6}}>疗程4周后复查血常规</div>
</div>
</div>
<Bubble left={false}>好的谢谢王医生</Bubble>
</div>
<div style={{padding:'10px 16px',background:T.card,borderTop:`1px solid ${T.bdL}`,display:'flex',alignItems:'center',gap:10}}>
<div style={{flex:1,height:40,background:T.bg,borderRadius:20,padding:'0 16px',display:'flex',alignItems:'center',fontSize:13,color:T.tx3}}>输入消息</div>
<div style={{width:40,height:40,background:T.pri,borderRadius:20,display:'flex',alignItems:'center',justifyContent:'center',color:'#fff',fontSize:16}}></div>
</div>
</div>);
}
// ── 渲染 ──
const screens=[
{label:'1 · 商品详情',el:<ProductDetail/>},
{label:'2 · 兑换确认',el:<ExchangeConfirm/>},
{label:'3 · 订单列表',el:<OrderList/>},
{label:'4 · 咨询聊天详情',el:<ChatDetail/>},
];
ReactDOM.createRoot(document.getElementById('root')).render(
<div class="screens">
{screens.map((s,i)=>(
<div class="screen-wrap" key={i}>
<Frame w={370} h={800}>{s.el}</Frame>
<div class="screen-label">{s.label}</div>
</div>
))}
</div>
);
</script>
</body>
</html>