mixer-fleet-saas 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/assets/AIAnalysis-B72xP247.js +1 -0
  2. package/dist/assets/AlarmCenter-BXG9KGDz.js +1 -0
  3. package/dist/assets/AlarmCenter-Czx19Tz0.css +1 -0
  4. package/dist/assets/Dashboard-CzDG19QP.js +1 -0
  5. package/dist/assets/DispatchCenter-CVEUKvRg.js +1 -0
  6. package/dist/assets/DriverView-s0dPZfR2.js +1 -0
  7. package/dist/assets/GeoFenceManager-CA0xN86V.js +1 -0
  8. package/dist/assets/GeoFenceManager-DvJ2wJrC.css +1 -0
  9. package/dist/assets/LoginView-BEVVJ0LE.css +1 -0
  10. package/dist/assets/LoginView-DOWsZFRb.js +1 -0
  11. package/dist/assets/MixerPumpBoard-CoZIvC8C.js +1 -0
  12. package/dist/assets/NotificationCenter-76QmpN-V.js +1 -0
  13. package/dist/assets/OrderManager-A3Ve7uqU.js +1 -0
  14. package/dist/assets/OrderManager-zLpKlv20.css +1 -0
  15. package/dist/assets/PumpMonitor-BaiicxGn.js +1 -0
  16. package/dist/assets/RealtimeMonitor-C8DVeOGh.js +6 -0
  17. package/dist/assets/ReportStats-_tEI6F6B.js +1 -0
  18. package/dist/assets/SmartDispatch-Dku4FMuz.js +5 -0
  19. package/dist/assets/StatsBar-dmdFex0_.js +1 -0
  20. package/dist/assets/StatusBadge-kISgaxfW.js +1 -0
  21. package/dist/assets/SystemSettings-DHobRs1O.js +1 -0
  22. package/dist/assets/TBoxManager-Db-20bHT.css +1 -0
  23. package/dist/assets/TBoxManager-jNHaSMgA.js +1 -0
  24. package/dist/assets/UserManager-BJih20EP.js +1 -0
  25. package/dist/assets/VehicleProfile-BQCwo2z_.css +1 -0
  26. package/dist/assets/VehicleProfile-CUo83gvc.js +95 -0
  27. package/dist/assets/VehicleTypeManager-Q8OMaue6.js +1 -0
  28. package/dist/assets/_plugin-vue_export-helper-S3RvzygF.js +1 -0
  29. package/dist/assets/deepseek-kuCyKxoN.js +14 -0
  30. package/dist/assets/export-LCWayDfi.js +10 -0
  31. package/dist/assets/index-CNJwmlwe.css +2 -0
  32. package/dist/assets/index-CTrnN2TM.js +9 -0
  33. package/dist/favicon.svg +1 -0
  34. package/dist/icons.svg +24 -0
  35. package/dist/index.html +27 -0
  36. package/dist/manifest.json +17 -0
  37. package/dist/offline.html +98 -0
  38. package/dist/sw.js +124 -0
  39. package/package.json +38 -0
  40. package/server/src/db.js +273 -0
  41. package/server/src/index.js +748 -0
  42. package/start.mjs +102 -0
@@ -0,0 +1 @@
1
+ import{A as e,B as t,E as n,F as r,G as i,I as a,K as o,M as s,N as c,P as l,Q as u,U as d,W as f,X as p,d as m,et as h,l as g,nt as _,s as v,tt as y}from"./index-CTrnN2TM.js";var b={class:`space-y-4`},x={class:`bg-white rounded-lg border shadow-sm p-4`},S={class:`flex items-center gap-4`},C={class:`flex gap-1 bg-gray-100 rounded-lg p-1`},w=[`onClick`],ee={key:0,class:`bg-white rounded-lg border shadow-sm p-8 text-center text-gray-400`},T={key:1,class:`bg-white rounded-lg border shadow-sm`},E={class:`px-4 py-3 border-b flex items-center justify-between`},D={class:`font-semibold text-sm text-gray-700`},O={class:`text-xs text-gray-400`},k={class:`overflow-x-auto`},A={class:`w-full text-sm`},j={class:`divide-y`},M={class:`py-2.5 px-4 font-medium text-gray-700`},N={class:`py-2.5 px-4 text-gray-600`},P={class:`py-2.5 px-4 text-gray-600`},F={class:`py-2.5 px-4 text-right text-gray-600`},I={class:`py-2.5 px-4 text-right text-gray-600`},L={class:`py-2.5 px-4 text-right text-gray-600`},R={class:`py-2.5 px-4 text-right`},z={class:`py-2.5 px-4 text-center`},B=t({__name:`ArrivalPredict`,setup(t){let n=g(),r=m(),l=v(),d=u(.9);function p(e,t,n,r){let i=(n-e)*Math.PI/180,a=(r-t)*Math.PI/180,o=Math.sin(i/2)*Math.sin(i/2)+Math.cos(e*Math.PI/180)*Math.cos(n*Math.PI/180)*Math.sin(a/2)*Math.sin(a/2);return 6371*2*Math.atan2(Math.sqrt(o),Math.sqrt(1-o))}let y=s(()=>{let e=[];for(let t of n.transportingOrders){let n=r.getByVin(t.vin??``);if(!n?.last_gps)continue;let i=n.last_gps,a=t.destination_fence_id?l.getById(t.destination_fence_id):null,o=a?.geometry?.center?.lat,s=a?.geometry?.center?.lng;if(o==null||s==null)continue;let c=p(i.lat,i.lng,o,s),u=i.speed>2?i.speed:30,f=c/(u*d.value)*60,m=`medium`;c<2?m=`high`:c>30&&(m=`low`);let h;if(f<1)h=`< 1 分钟`;else if(f<60)h=`约 ${Math.round(f)} 分钟`;else{let e=Math.floor(f/60),t=Math.round(f%60);h=`约 ${e}h${t>0?t+`m`:``}`}e.push({orderId:t.order_id,plateNumber:n.plate_number||t.vin?.slice(-6)||`-`,destination:t.destination_name||`未知`,concreteGrade:t.concrete_grade,volume:t.volume_m3,distanceKm:c,currentSpeed:u,etaMinutes:Math.round(f),confidence:m,etaDisplay:h})}return e.sort((e,t)=>e.etaMinutes-t.etaMinutes),e}),B=u(0),V=setInterval(()=>{B.value++},1e3);f(()=>{clearInterval(V)});let H=[{label:`🚦 拥堵 (×0.6)`,value:.6},{label:`🚗 城区 (×0.9)`,value:.9},{label:`🛣️ 郊区 (×1.1)`,value:1.1},{label:`🏎️ 高速 (×1.3)`,value:1.3}];return(t,n)=>(i(),a(`div`,b,[c(`div`,x,[c(`div`,S,[n[0]||=c(`span`,{class:`text-sm text-gray-600 font-medium`},`交通状况:`,-1),c(`div`,C,[(i(),a(e,null,o(H,e=>c(`button`,{key:e.value,class:h([`px-3 py-1 text-xs rounded-md transition-colors`,d.value===e.value?`bg-white text-blue-600 shadow-sm font-medium`:`text-gray-500`]),onClick:t=>d.value=e.value},_(e.label),11,w)),64))])])]),y.value.length===0?(i(),a(`div`,ee,[...n[1]||=[c(`div`,{class:`text-4xl mb-3`},`🚚`,-1),c(`p`,{class:`text-sm`},`暂无运输中的订单`,-1),c(`p`,{class:`text-xs mt-1`},`当有车辆处于运输状态时,将在此显示到货预测`,-1)]])):(i(),a(`div`,T,[c(`div`,E,[c(`h3`,D,` 🚚 运输中订单 — 到货预测 (`+_(y.value.length)+`) `,1),c(`span`,O,` 基于实时 GPS 速度 · 交通因子 `+_(d.value),1)]),c(`div`,k,[c(`table`,A,[n[2]||=c(`thead`,{class:`text-gray-400 border-b bg-gray-50`},[c(`tr`,null,[c(`th`,{class:`text-left py-2 px-4`},`车辆`),c(`th`,{class:`text-left py-2 px-4`},`目的地`),c(`th`,{class:`text-left py-2 px-4`},`标号`),c(`th`,{class:`text-right py-2 px-4`},`方量`),c(`th`,{class:`text-right py-2 px-4`},`距离`),c(`th`,{class:`text-right py-2 px-4`},`车速`),c(`th`,{class:`text-right py-2 px-4`},`预计到达`),c(`th`,{class:`text-center py-2 px-4`},`置信度`)])],-1),c(`tbody`,j,[(i(!0),a(e,null,o(y.value,e=>(i(),a(`tr`,{key:e.orderId,class:`hover:bg-gray-50 transition-colors`},[c(`td`,M,_(e.plateNumber),1),c(`td`,N,_(e.destination),1),c(`td`,P,_(e.concreteGrade),1),c(`td`,F,_(e.volume)+` m³`,1),c(`td`,I,_(e.distanceKm.toFixed(1))+` km`,1),c(`td`,L,_(e.currentSpeed.toFixed(0))+` km/h`,1),c(`td`,R,[c(`span`,{class:h([`font-semibold`,{"text-green-600":e.etaMinutes<10,"text-yellow-600":e.etaMinutes>=10&&e.etaMinutes<30,"text-red-600":e.etaMinutes>=30}])},_(e.etaDisplay),3)]),c(`td`,z,[c(`span`,{class:h([`inline-flex items-center gap-1 text-xs rounded-full px-2 py-0.5`,{"bg-green-50 text-green-700":e.confidence===`high`,"bg-yellow-50 text-yellow-700":e.confidence===`medium`,"bg-red-50 text-red-700":e.confidence===`low`}])},_(e.confidence===`high`?`🟢 高`:e.confidence===`medium`?`🟡 中`:`🔴 低`),3)])]))),128))])])])])),n[3]||=c(`div`,{class:`bg-blue-50 rounded-lg border border-blue-200 p-3 text-xs text-blue-700`},[c(`p`,{class:`font-medium mb-1`},`💡 预测说明`),c(`ul`,{class:`space-y-0.5 text-blue-600`},[c(`li`,null,`• 基于车辆当前 GPS 位置与目的地围栏坐标的直线距离计算`),c(`li`,null,`• 实际路况可能因道路限行、红绿灯、卸料排队等因素偏差`),c(`li`,null,`• 置信度:近距离 <2km 高 / 2-30km 中 / >30km 低`),c(`li`,null,`• 车速 <2km/h 时默认采用 30km/h 估算`)])],-1)]))}}),V={class:`space-y-4`},H={class:`bg-white rounded-lg border shadow-sm p-4`},U={class:`flex items-center gap-4 flex-wrap`},W={class:`flex gap-1 bg-gray-100 rounded-lg p-1`},te=[`onClick`],G={class:`flex items-center gap-2`},K={class:`bg-white rounded-lg border shadow-sm p-4`},q={class:`font-semibold text-sm text-gray-700 mb-3`},J={class:`h-40 flex items-end gap-px bg-gray-50 rounded p-2`},Y=[`title`],X={class:`text-xs text-gray-400 mt-2 text-center`},Z={key:0,class:`bg-white rounded-lg border shadow-sm p-8 text-center text-gray-400`},Q={key:1,class:`bg-white rounded-lg border shadow-sm`},ne={class:`px-4 py-3 border-b`},re={class:`font-semibold text-sm text-gray-700`},ie={class:`overflow-x-auto`},ae={class:`w-full text-sm`},oe={class:`divide-y`},se={class:`py-2.5 px-4 font-medium text-gray-700`},ce={class:`py-2.5 px-4 text-gray-600`},le={class:`py-2.5 px-4 text-right text-gray-600`},ue={class:`py-2.5 px-4 text-right text-gray-600`},de={class:`py-2.5 px-4 text-right text-gray-600`},fe={class:`py-2.5 px-4 text-right`},pe={class:`py-2.5 px-4 text-right`},$={class:`py-2.5 px-4 text-center`},me=t({__name:`SlumpEstimate`,setup(t){let r=g(),l=m(),d=u(25),f=s(()=>{let e=[],t=[...r.transportingOrders,...r.orders.filter(e=>e.status===`arrived`||e.status===`discharging`)];for(let n of t){let t=l.getByVin(n.vin??``),r=n.concrete_grade||`C30`,i=v(r),a=n.loaded_at||n.departed_at||n.created_at,o=(Date.now()-a)/6e4,s=d.value,c=b(i,s,o),u=(i-c)/i*100,f=`normal`;u>40?f=`critical`:u>25&&(f=`warning`),e.push({orderId:n.order_id,plateNumber:t?.plate_number||n.vin?.slice(-6)||`-`,concreteGrade:r,volume:n.volume_m3,initialSlump:i,elapsedMin:Math.round(o),temperature:s,currentSlump:Math.round(c),lossPercent:Math.round(u*10)/10,status:f})}return e.sort((e,t)=>t.lossPercent-e.lossPercent),e});function v(e){return{C10:200,C15:190,C20:180,C25:180,C30:180,C35:160,C40:160,C45:150,C50:140,C55:130,C60:120}[e]??180}function b(e,t,n){let r=.0015*2.3**((t-20)/10),i=n;return e*Math.exp(-r*i)}let x=[{label:`❄️ 5°C 冬季`,value:5},{label:`🌤️ 15°C 春秋`,value:15},{label:`☀️ 25°C 常温`,value:25},{label:`🔥 35°C 夏季`,value:35}];return(t,r)=>(i(),a(`div`,V,[c(`div`,H,[c(`div`,U,[r[2]||=c(`span`,{class:`text-sm text-gray-600 font-medium`},`环境温度:`,-1),c(`div`,W,[(i(),a(e,null,o(x,e=>c(`button`,{key:e.value,class:h([`px-3 py-1 text-xs rounded-md transition-colors`,d.value===e.value?`bg-white text-blue-600 shadow-sm font-medium`:`text-gray-500`]),onClick:t=>d.value=e.value},_(e.label),11,te)),64))]),c(`div`,G,[p(c(`input`,{"onUpdate:modelValue":r[0]||=e=>d.value=e,type:`number`,min:`-10`,max:`50`,class:`w-16 border rounded px-2 py-1 text-sm text-center`},null,512),[[n,d.value,void 0,{number:!0}]]),r[1]||=c(`span`,{class:`text-xs text-gray-400`},`°C`,-1)])])]),c(`div`,K,[c(`h3`,q,`📈 C30 坍落度经时曲线 (`+_(d.value)+`°C)`,1),c(`div`,J,[(i(),a(e,null,o(25,e=>c(`div`,{key:e,class:`flex-1 bg-blue-400 rounded-t transition-all`,style:y({height:`${Math.max(3,b(180,d.value,(e-1)*5)/180*100)}%`}),title:`${(e-1)*5}min: ${Math.round(b(180,d.value,(e-1)*5))}mm`},null,12,Y)),64))]),r[3]||=c(`div`,{class:`flex justify-between text-xs text-gray-400 mt-1`},[c(`span`,null,`0min`),c(`span`,null,`30min`),c(`span`,null,`60min`),c(`span`,null,`90min`),c(`span`,null,`120min`)],-1),c(`p`,X,` 模拟 C30 (初始 180mm) 在 `+_(d.value)+`°C 环境下的坍落度衰减趋势 `,1)]),f.value.length===0?(i(),a(`div`,Z,[...r[4]||=[c(`div`,{class:`text-4xl mb-3`},`🧪`,-1),c(`p`,{class:`text-sm`},`暂无运输/到达中的订单`,-1),c(`p`,{class:`text-xs mt-1`},`当有车辆装料完成出发后,将在此推算坍落度变化`,-1)]])):(i(),a(`div`,Q,[c(`div`,ne,[c(`h3`,re,` 🧪 坍落度推算 (`+_(f.value.length)+` 单) `,1)]),c(`div`,ie,[c(`table`,ae,[r[5]||=c(`thead`,{class:`text-gray-400 border-b bg-gray-50`},[c(`tr`,null,[c(`th`,{class:`text-left py-2 px-4`},`车辆`),c(`th`,{class:`text-left py-2 px-4`},`标号`),c(`th`,{class:`text-right py-2 px-4`},`方量`),c(`th`,{class:`text-right py-2 px-4`},`初始`),c(`th`,{class:`text-right py-2 px-4`},`已过`),c(`th`,{class:`text-right py-2 px-4`},`当前推算`),c(`th`,{class:`text-right py-2 px-4`},`损失率`),c(`th`,{class:`text-center py-2 px-4`},`状态`)])],-1),c(`tbody`,oe,[(i(!0),a(e,null,o(f.value,e=>(i(),a(`tr`,{key:e.orderId,class:h([`hover:bg-gray-50 transition-colors`,{"bg-red-50/30":e.status===`critical`,"bg-yellow-50/30":e.status===`warning`}])},[c(`td`,se,_(e.plateNumber),1),c(`td`,ce,_(e.concreteGrade),1),c(`td`,le,_(e.volume)+` m³`,1),c(`td`,ue,_(e.initialSlump)+` mm`,1),c(`td`,de,_(e.elapsedMin)+` min`,1),c(`td`,fe,[c(`span`,{class:h([`font-semibold`,{"text-green-600":e.status===`normal`,"text-yellow-600":e.status===`warning`,"text-red-600":e.status===`critical`}])},_(e.currentSlump)+` mm `,3)]),c(`td`,pe,[c(`span`,{class:h([`font-semibold`,{"text-green-600":e.status===`normal`,"text-yellow-600":e.status===`warning`,"text-red-600":e.status===`critical`}])},_(e.lossPercent)+`% `,3)]),c(`td`,$,[c(`span`,{class:h([`inline-flex items-center gap-1 text-xs rounded-full px-2 py-0.5`,{"bg-green-50 text-green-700":e.status===`normal`,"bg-yellow-50 text-yellow-700":e.status===`warning`,"bg-red-50 text-red-700":e.status===`critical`}])},_(e.status===`normal`?`✅ 正常`:e.status===`warning`?`⚠️ 注意`:`🔴 告警`),3)])],2))),128))])])])])),r[6]||=c(`div`,{class:`bg-indigo-50 rounded-lg border border-indigo-200 p-3 text-xs text-indigo-700`},[c(`p`,{class:`font-medium mb-1`},`🧪 推算方法说明`),c(`ul`,{class:`space-y-0.5 text-indigo-600`},[c(`li`,null,`• 公式:S(t) = S₀ × exp(-k(T) × t),基于 Arrhenius 方程`),c(`li`,null,`• k(T) 温度系数 Q₁₀ = 2.3(温度每升高 10°C,衰减速率加倍)`),c(`li`,null,`• 损失率 >25% 黄色预警,>40% 红色告警`),c(`li`,null,`• 实际坍落度受外加剂、水泥品种、水胶比等多因素影响,此为理论推算`),c(`li`,null,`• 建议实测数据积累后标定 k₀ 参数`)])],-1)]))}}),he={class:`space-y-4`},ge={class:`flex gap-1 bg-gray-100 rounded-lg p-1 w-fit`},_e=t({__name:`AIAnalysis`,setup(e){let t=g(),n=m(),o=u(`arrival`);return d(async()=>{t.loaded||await t.load(),n.loaded||await n.load()}),(e,t)=>(i(),a(`div`,he,[t[2]||=c(`div`,{class:`flex items-center gap-3`},[c(`h1`,{class:`text-2xl font-bold`},`🤖 AI 分析`),c(`span`,{class:`text-xs text-gray-400 bg-gray-100 rounded-full px-2 py-0.5`},`Beta`)],-1),t[3]||=c(`p`,{class:`text-sm text-gray-500`},` 基于实时 GPS 轨迹、CAN 传感器数据与历史统计,智能预测到货时间与混凝土坍落度变化。 `,-1),c(`div`,ge,[c(`button`,{class:h([`px-4 py-1.5 text-sm rounded-md transition-colors`,o.value===`arrival`?`bg-white text-blue-600 shadow-sm font-medium`:`text-gray-500`]),onClick:t[0]||=e=>o.value=`arrival`},` 🚚 到货预测 `,2),c(`button`,{class:h([`px-4 py-1.5 text-sm rounded-md transition-colors`,o.value===`slump`?`bg-white text-blue-600 shadow-sm font-medium`:`text-gray-500`]),onClick:t[1]||=e=>o.value=`slump`},` 🧪 坍落度推算 `,2)]),o.value===`arrival`?(i(),l(B,{key:0})):r(``,!0),o.value===`slump`?(i(),l(me,{key:1})):r(``,!0)]))}});export{_e as default};
@@ -0,0 +1 @@
1
+ import{$ as e,A as t,B as n,F as r,G as i,I as a,J as o,K as s,M as c,N as l,P as u,Q as d,S as f,U as p,Y as ee,c as m,et as h,j as g,nt as _,z as v}from"./index-CTrnN2TM.js";import{n as y,t as b}from"./export-LCWayDfi.js";import{t as x}from"./_plugin-vue_export-helper-S3RvzygF.js";import{t as S}from"./StatusBadge-kISgaxfW.js";var C={class:`flex items-start justify-between`},w={class:`flex-1`},T={class:`flex items-center gap-2 mb-1`},E={class:`text-lg`},D={class:`font-bold text-sm text-gray-900`},O={class:`text-sm text-gray-700`},k={class:`text-xs text-gray-400 mt-1`},A=x(n({__name:`AlarmPopup`,setup(e){let t=m(),n=d(!1),s=d(null);o(()=>t.recentAlarms.length,()=>{let e=t.recentAlarms[0];e&&e.severity===`critical`&&e.status===`active`&&(s.value=e,n.value=!0,c())});function c(){try{let e=new AudioContext,t=e.createOscillator(),n=e.createGain();t.connect(n),n.connect(e.destination),t.frequency.value=800,t.type=`square`,n.gain.value=.1,t.start(),setTimeout(()=>{t.frequency.value=600,setTimeout(()=>t.stop(),300)},300)}catch{}}function p(){s.value&&t.acknowledge(s.value.alarm_id),n.value=!1}function y(){n.value=!1}function b(e){return e===`critical`?`border-red-500 bg-red-50`:`border-orange-400 bg-orange-50`}return(e,t)=>(i(),u(g,{to:`body`},[v(f,{name:`slide`},{default:ee(()=>[n.value&&s.value?(i(),a(`div`,{key:0,class:h([`fixed top-4 right-4 z-50 max-w-sm w-full border-l-4 rounded-lg shadow-lg p-4`,b(s.value.severity)])},[l(`div`,C,[l(`div`,w,[l(`div`,T,[l(`span`,E,_(s.value.severity===`critical`?`🔴`:`🟠`),1),l(`span`,D,_(s.value.severity===`critical`?`紧急告警`:`严重告警`),1)]),l(`p`,O,_(s.value.description),1),l(`div`,k,` VIN: `+_(s.value.vin)+` | `+_(new Date(s.value.occurred_at).toLocaleTimeString()),1)]),l(`button`,{class:`text-gray-400 hover:text-gray-600 text-lg leading-none`,onClick:y},` ✕ `)]),l(`div`,{class:`flex gap-2 mt-3`},[l(`button`,{class:`flex-1 py-1.5 text-xs font-medium rounded bg-blue-600 text-white hover:bg-blue-700`,onClick:p},` 已知悉 `),l(`button`,{class:`flex-1 py-1.5 text-xs font-medium rounded bg-gray-200 text-gray-600 hover:bg-gray-300`,onClick:y},` 关闭 `)])],2)):r(``,!0)]),_:1})]))}}),[[`__scopeId`,`data-v-c20089ad`]]),j={class:`bg-white rounded-lg border shadow-sm overflow-hidden`},M={class:`overflow-x-auto`},N={class:`w-full text-sm`},P={class:`divide-y`},F={class:`px-3 py-2.5`},I={class:`px-3 py-2.5 text-gray-700`},L=[`title`],R={class:`px-3 py-2.5 font-mono text-xs text-gray-500`},te={class:`px-3 py-2.5 text-xs text-gray-400`},z={class:`px-3 py-2.5`},B={class:`px-3 py-2.5`},V={class:`flex gap-1`},H=[`onClick`],U=[`onClick`],W=[`onClick`],G={key:0},K=n({__name:`AlarmList`,props:{alarms:{}},setup(e){let n=m(),o={drum_abnormal_stop:`搅拌筒停转`,concrete_timeout:`超时未卸料`,fence_timeout:`围栏超时`,theft_warning:`盗料预警`,deviation:`偏离目的地`,fatigue_driving:`疲劳驾驶`,tbox_offline:`TBox离线`,overspeed:`超速`,unbound_moving:`未绑定移动`,emergency:`紧急`};function c(e){return o[e]??e}function u(e){return new Date(e).toLocaleString(`zh-CN`,{month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`})}function d(e,t){n.handle(e,t,`operator`)}return(n,o)=>(i(),a(`div`,j,[l(`div`,M,[l(`table`,N,[o[1]||=l(`thead`,{class:`bg-gray-50 text-xs text-gray-500 uppercase`},[l(`tr`,null,[l(`th`,{class:`px-3 py-2 text-left`},`级别`),l(`th`,{class:`px-3 py-2 text-left`},`类型`),l(`th`,{class:`px-3 py-2 text-left`},`描述`),l(`th`,{class:`px-3 py-2 text-left`},`车辆`),l(`th`,{class:`px-3 py-2 text-left`},`时间`),l(`th`,{class:`px-3 py-2 text-left`},`状态`),l(`th`,{class:`px-3 py-2 text-left`},`操作`)])],-1),l(`tbody`,P,[(i(!0),a(t,null,s(e.alarms,e=>(i(),a(`tr`,{key:e.alarm_id,class:h([`hover:bg-gray-50`,{"bg-red-50/30":e.severity===`critical`&&e.status===`active`}])},[l(`td`,F,[l(`span`,{class:h({"text-red-600":e.severity===`critical`,"text-orange-500":e.severity===`warning`,"text-blue-500":e.severity===`info`})},_(e.severity===`critical`?`🔴`:e.severity===`warning`?`🟡`:`🔵`),3)]),l(`td`,I,_(c(e.alarm_type)),1),l(`td`,{class:`px-3 py-2.5 text-gray-600 max-w-xs truncate`,title:e.description},_(e.description),9,L),l(`td`,R,_(e.vin.slice(-8)),1),l(`td`,te,_(u(e.occurred_at)),1),l(`td`,z,[v(S,{status:e.status,size:`sm`},null,8,[`status`])]),l(`td`,B,[l(`div`,V,[e.status===`active`?(i(),a(`button`,{key:0,class:`px-2 py-0.5 text-xs rounded bg-blue-50 text-blue-600 hover:bg-blue-100`,onClick:t=>d(e.alarm_id,`acknowledged`)},` 知悉 `,8,H)):r(``,!0),e.status===`active`||e.status===`acknowledged`?(i(),a(`button`,{key:1,class:`px-2 py-0.5 text-xs rounded bg-green-50 text-green-600 hover:bg-green-100`,onClick:t=>d(e.alarm_id,`resolved`)},` 解决 `,8,U)):r(``,!0),e.status===`active`?(i(),a(`button`,{key:2,class:`px-2 py-0.5 text-xs rounded bg-gray-100 text-gray-500 hover:bg-gray-200`,onClick:t=>d(e.alarm_id,`ignored`)},` 忽略 `,8,W)):r(``,!0)])])],2))),128)),e.alarms.length===0?(i(),a(`tr`,G,[...o[0]||=[l(`td`,{colspan:`7`,class:`px-4 py-8 text-center text-gray-400`},` 暂无告警记录 `,-1)]])):r(``,!0)])])])]))}}),q={class:`flex gap-3 flex-wrap`},J=[`value`],Y=[`value`],X=[`value`],Z=[`value`],Q=[`value`],ne=[`value`],re=n({__name:`AlarmFilter`,props:{typeFilter:{},severityFilter:{},statusFilter:{}},emits:[`update:typeFilter`,`update:severityFilter`,`update:statusFilter`],setup(e,{emit:n}){let r=n,o=[{value:``,label:`全部类型`},{value:`drum_abnormal_stop`,label:`搅拌筒停转`},{value:`concrete_timeout`,label:`超时未卸料`},{value:`fence_timeout`,label:`围栏超时`},{value:`theft_warning`,label:`盗料预警`},{value:`deviation`,label:`偏离目的地`},{value:`fatigue_driving`,label:`疲劳驾驶`},{value:`tbox_offline`,label:`TBox离线`},{value:`overspeed`,label:`超速`},{value:`unbound_moving`,label:`未绑定移动`},{value:`emergency`,label:`紧急`}],c=[{value:``,label:`全部级别`},{value:`critical`,label:`🔴 紧急`},{value:`warning`,label:`🟡 警告`},{value:`info`,label:`🔵 提示`}],u=[{value:``,label:`全部状态`},{value:`active`,label:`未处理`},{value:`acknowledged`,label:`已知悉`},{value:`resolved`,label:`已解决`},{value:`ignored`,label:`已忽略`}];return(n,d)=>(i(),a(`div`,q,[l(`select`,{value:e.typeFilter,class:`border rounded-lg px-3 py-1.5 text-xs focus:outline-none focus:ring-2 focus:ring-blue-500`,onChange:d[0]||=e=>r(`update:typeFilter`,e.target.value)},[(i(),a(t,null,s(o,e=>l(`option`,{key:e.value,value:e.value},_(e.label),9,Y)),64))],40,J),l(`select`,{value:e.severityFilter,class:`border rounded-lg px-3 py-1.5 text-xs focus:outline-none focus:ring-2 focus:ring-blue-500`,onChange:d[1]||=e=>r(`update:severityFilter`,e.target.value)},[(i(),a(t,null,s(c,e=>l(`option`,{key:e.value,value:e.value},_(e.label),9,Z)),64))],40,X),l(`select`,{value:e.statusFilter,class:`border rounded-lg px-3 py-1.5 text-xs focus:outline-none focus:ring-2 focus:ring-blue-500`,onChange:d[2]||=e=>r(`update:statusFilter`,e.target.value)},[(i(),a(t,null,s(u,e=>l(`option`,{key:e.value,value:e.value},_(e.label),9,ne)),64))],40,Q)]))}}),ie={class:`space-y-4`},ae={class:`flex items-center justify-between`},oe={class:`flex gap-4 text-sm`},$={class:`text-red-600 font-semibold`},se={class:`text-orange-500 font-semibold`},ce={class:`text-gray-500`},le=n({__name:`AlarmCenter`,setup(t){let n=m(),r=d(``),o=d(``),s=d(``);p(async()=>{n.loaded||await n.load()});let u=c(()=>{let e=[...n.alarms];return r.value&&(e=e.filter(e=>e.alarm_type===r.value)),o.value&&(e=e.filter(e=>e.severity===o.value)),s.value&&(e=e.filter(e=>e.status===s.value)),e.sort((e,t)=>t.occurred_at-e.occurred_at),e});return(t,c)=>(i(),a(`div`,ie,[v(A),l(`div`,ae,[c[5]||=l(`h1`,{class:`text-2xl font-bold`},`🔔 告警中心`,-1),l(`div`,oe,[l(`span`,$,` 🔴 紧急: `+_(e(n).alarms.filter(e=>e.severity===`critical`&&e.status===`active`).length),1),l(`span`,se,` 🟡 未处理: `+_(e(n).activeCount),1),l(`span`,ce,` 总计: `+_(e(n).alarms.length),1),l(`button`,{class:`px-2 py-0.5 text-xs text-blue-600 border border-blue-200 rounded hover:bg-blue-50`,onClick:c[0]||=t=>e(y)(e(n).alarms)},`JSON`),l(`button`,{class:`px-2 py-0.5 text-xs text-green-600 border border-green-200 rounded hover:bg-green-50`,onClick:c[1]||=t=>e(b)(e(n).alarms)},`CSV`)])]),v(re,{typeFilter:r.value,"onUpdate:typeFilter":c[2]||=e=>r.value=e,severityFilter:o.value,"onUpdate:severityFilter":c[3]||=e=>o.value=e,statusFilter:s.value,"onUpdate:statusFilter":c[4]||=e=>s.value=e},null,8,[`typeFilter`,`severityFilter`,`statusFilter`]),v(K,{alarms:u.value},null,8,[`alarms`])]))}});export{le as default};
@@ -0,0 +1 @@
1
+ .slide-enter-active[data-v-c20089ad],.slide-leave-active[data-v-c20089ad]{transition:all .3s}.slide-enter-from[data-v-c20089ad],.slide-leave-to[data-v-c20089ad]{opacity:0;transform:translate(100%)}
@@ -0,0 +1 @@
1
+ import{$ as e,A as t,B as n,F as r,G as i,H as a,I as o,K as s,L as c,M as l,N as u,Q as d,R as ee,U as te,W as f,c as p,d as ne,et as re,i as ie,l as ae,nt as m,s as oe,t as h,x as se,z as g}from"./index-CTrnN2TM.js";import{t as _}from"./StatsBar-dmdFex0_.js";var v={class:`space-y-6`},ce={class:`flex items-center justify-between`},le={class:`flex items-center gap-2`},ue={class:`text-sm text-gray-500`},de={key:0,class:`text-xs text-yellow-500 ml-2`},y={class:`grid grid-cols-1 sm:grid-cols-2 gap-3 md:gap-4`},b={class:`bg-white rounded-lg border shadow-sm p-4`},x={class:`bg-white rounded-lg border shadow-sm p-4`},S={class:`bg-blue-50 rounded-lg border border-blue-200 p-4`},C={class:`flex items-center justify-between flex-wrap gap-2`},w={class:`flex items-center gap-1 shrink-0`},T=[`value`],E={class:`grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-3`},D=[`onClick`],O={class:`text-2xl mb-2`},k={class:`font-semibold text-sm text-gray-800`},A={class:`text-xs text-gray-400 mt-1`},j={class:`bg-white rounded-lg border shadow-sm p-4`},M={class:`bg-white rounded-lg border shadow-sm p-4`},N={class:`font-semibold text-sm text-gray-700 mb-3`},P={key:0,class:`ml-2 text-red-500`},F={key:0,class:`space-y-2`},I={class:`text-gray-700 flex-1`},L={class:`text-xs text-gray-400`},fe={key:1,class:`text-sm text-gray-400 text-center py-4`},R=n({__name:`Dashboard`,setup(n){let R=ne(),z=ae(),B=p(),V=oe(),pe=se(),H=ie.connectionState,U=d(h.isStarted),W=l(()=>`${window.location.origin}/#/driver`),G=d(!1);async function me(){try{await navigator.clipboard.writeText(W.value),G.value=!0,setTimeout(()=>{G.value=!1},2e3)}catch{let e=document.createElement(`textarea`);e.value=W.value,e.style.position=`fixed`,e.style.opacity=`0`,document.body.appendChild(e),e.select(),document.execCommand(`copy`),document.body.removeChild(e),G.value=!0,setTimeout(()=>{G.value=!1},2e3)}}let K=setInterval(()=>{U.value=h.isStarted},500),q=d(null),J=d(null),Y=d(null),X=null,Z=[];te(()=>{U.value=h.isStarted,ge(),a(()=>he())}),f(()=>{clearInterval(K),X&&=(X.destroy(),null)});function he(){if(!Y.value||typeof AMap>`u`)return;let e=[R.vehicles[0]?.last_gps?.lng??116.4,R.vehicles[0]?.last_gps?.lat??39.9];X=new AMap.Map(Y.value,{zoom:10,center:e,resizeEnable:!0,zoomEnable:!1}),Q(),setInterval(Q,1e4)}function Q(){if(X){Z.forEach(e=>X.remove(e)),Z=[];for(let e of R.vehicles){if(!e.last_gps)continue;let t=new AMap.Marker({position:[e.last_gps.lng,e.last_gps.lat],title:e.plate_number||e.vin.slice(-6)});X.add(t),Z.push(t)}Z.length>0&&X.setFitView()}}f(()=>{clearInterval(K)});function ge(){let e=Date.now(),t=Array.from({length:24},(t,n)=>e-(23-n)*36e5),n=t.map(e=>{let t=e+36e5;return z.orders.filter(n=>n.completed_at&&n.completed_at>=e&&n.completed_at<t).reduce((e,t)=>e+t.volume_m3,0)}),r=t.map(e=>{let t=e+36e5;return B.alarms.filter(n=>n.timestamp>=e&&n.timestamp<t).length});$(q.value,n,`#3b82f6`),$(J.value,r,`#ef4444`)}function $(e,t,n){if(!e)return;let r=(e.parentElement?.clientWidth??200)-32;e.width=r,e.height=96;let i=e.getContext(`2d`);if(!i)return;let a=Math.max(...t,1),o=r/t.length*.7,s=r/t.length*.3;i.clearRect(0,0,r,96),t.forEach((e,t)=>{let r=e/a*72,c=t*(o+s)+s/2,l=96-r-16;i.fillStyle=e>0?n:`#e5e7eb`,i.fillRect(c,l,o,r),e>0&&(i.fillStyle=`#6b7280`,i.font=`9px sans-serif`,i.textAlign=`center`,i.fillText(String(e),c+o/2,l-2))}),i.strokeStyle=`#e5e7eb`,i.lineWidth=1,i.beginPath(),i.moveTo(0,80),i.lineTo(r,80),i.stroke()}let _e=l(()=>[{path:`/monitor`,label:`实时监控`,icon:`🗺️`,desc:`车辆位置 & 搅拌筒状态`},{path:`/dispatch`,label:`调度中心`,icon:`📋`,desc:`派单 & 调度看板`},{path:`/alarms`,label:`告警中心`,icon:`🔔`,desc:`${B.activeCount} 条活跃告警`},{path:`/fences`,label:`围栏管理`,icon:`📍`,desc:`${V.activeCount} 个活跃围栏`},{path:`/settings`,label:`系统设置`,icon:`⚙️`,desc:`EMQX / 告警 / 地图配置`}]);return(n,a)=>(i(),o(`div`,v,[u(`div`,ce,[a[1]||=u(`h1`,{class:`text-2xl font-bold`},`📊 仪表盘`,-1),u(`div`,le,[u(`span`,{class:re([`w-2 h-2 rounded-full`,{"bg-green-500":e(H)===`connected`,"bg-yellow-500 animate-pulse":e(H)===`connecting`,"bg-red-500":e(H)===`disconnected`||e(H)===`error`}])},null,2),u(`span`,ue,` MQTT: `+m(U.value?`✅ 已连接`:{connected:`已连接`,connecting:`连接中...`,disconnected:`未连接`,error:`错误`}[e(H)]),1),U.value?r(``,!0):(i(),o(`span`,de,`等待连接...`))])]),g(_),u(`div`,y,[u(`div`,b,[a[2]||=u(`h3`,{class:`text-xs text-gray-500 mb-2`},`📦 今日方量趋势 (过去24h)`,-1),u(`canvas`,{ref_key:`volumeCanvas`,ref:q,class:`w-full h-24`},null,512)]),u(`div`,x,[a[3]||=u(`h3`,{class:`text-xs text-gray-500 mb-2`},`🔔 告警趋势 (过去24h)`,-1),u(`canvas`,{ref_key:`alarmCanvas`,ref:J,class:`w-full h-24`},null,512)])]),u(`div`,S,[u(`div`,C,[a[4]||=c(`<div class="flex items-center gap-2 min-w-0"><span class="text-lg">🚛</span><div class="min-w-0"><div class="font-semibold text-sm text-gray-800">司机面板链接</div><div class="text-[11px] text-gray-400">将此链接发给司机,在手机浏览器打开即可使用司机面板</div></div></div>`,1),u(`div`,w,[u(`input`,{value:W.value,readonly:``,class:`w-48 sm:w-64 border border-blue-200 rounded px-2.5 py-1.5 text-xs bg-white text-gray-600 truncate`,onFocus:a[0]||=e=>e.target.select()},null,40,T),u(`button`,{class:`bg-blue-600 text-white rounded px-3 py-1.5 text-xs font-medium hover:bg-blue-700 whitespace-nowrap`,onClick:me},m(G.value?`✅ 已复制`:`📋 复制`),1)])])]),u(`div`,E,[(i(!0),o(t,null,s(_e.value,t=>(i(),o(`div`,{key:t.path,class:`bg-white rounded-lg border shadow-sm p-4 cursor-pointer hover:shadow-md hover:border-blue-300 transition-all`,onClick:n=>e(pe).push(t.path)},[u(`div`,O,m(t.icon),1),u(`div`,k,m(t.label),1),u(`div`,A,m(t.desc),1)],8,D))),128))]),u(`div`,j,[a[5]||=u(`h3`,{class:`font-semibold text-sm text-gray-700 mb-3`},`🌍 实时位置预览`,-1),u(`div`,{ref_key:`miniMapContainer`,ref:Y,class:`h-48 w-full rounded-lg bg-gray-100`},null,512)]),u(`div`,M,[u(`h3`,N,[a[6]||=ee(` 最近告警 `,-1),e(B).activeCount>0?(i(),o(`span`,P,`(`+m(e(B).activeCount)+` 未处理)`,1)):r(``,!0)]),e(B).recentAlarms.length>0?(i(),o(`div`,F,[(i(!0),o(t,null,s(e(B).recentAlarms.slice(0,5),e=>(i(),o(`div`,{key:e.alarm_id,class:`flex items-center gap-3 text-sm py-1.5 border-b border-gray-50 last:border-0`},[u(`span`,null,m(e.severity===`critical`?`🔴`:e.severity===`warning`?`🟡`:`🔵`),1),u(`span`,I,m(e.description),1),u(`span`,L,m(new Date(e.occurred_at).toLocaleTimeString()),1)]))),128))])):(i(),o(`div`,fe,`🎉 暂无告警`))])]))}});export{R as default};
@@ -0,0 +1 @@
1
+ import{$ as e,A as t,B as n,C as r,E as i,F as a,G as o,I as s,K as c,M as l,N as u,Q as d,R as f,T as p,X as m,d as h,et as g,k as _,l as v,n as y,nt as b,s as x,z as S}from"./index-CTrnN2TM.js";import{t as C}from"./StatusBadge-kISgaxfW.js";var w={class:`border rounded-lg bg-white overflow-hidden`},T={class:`px-3 py-2 bg-gray-50 border-b text-xs font-semibold text-gray-600`},E={class:`max-h-80 overflow-y-auto`},D=[`onClick`],O={class:`flex items-center gap-2`},k=[`checked`,`onChange`],A={class:`text-sm font-medium text-gray-800`},j={key:0,class:`px-3 py-8 text-center text-sm text-gray-400`},M=n({__name:`VehicleSelector`,props:{selectedVins:{}},emits:[`update:selectedVins`],setup(e,{emit:n}){let r=h(),i=e,d=n,f=l(()=>r.idleVehicles);function p(e){let t=[...i.selectedVins],n=t.indexOf(e);n>=0?t.splice(n,1):t.push(e),d(`update:selectedVins`,t)}function m(e){return i.selectedVins.includes(e)}return(e,n)=>(o(),s(`div`,w,[u(`div`,T,` 待命车辆 (`+b(f.value.length)+`) `,1),u(`div`,E,[(o(!0),s(t,null,c(f.value,e=>(o(),s(`div`,{key:e.vin,class:g([`flex items-center justify-between px-3 py-2 border-b border-gray-50 cursor-pointer hover:bg-blue-50 transition-colors`,{"bg-blue-50":m(e.vin)}]),onClick:t=>p(e.vin)},[u(`div`,O,[u(`input`,{type:`checkbox`,checked:m(e.vin),class:`w-4 h-4 rounded border-gray-300 text-blue-600`,onClick:n[0]||=_(()=>{},[`stop`]),onChange:t=>p(e.vin)},null,40,k),u(`span`,A,b(e.plate_number||e.vin.slice(-6)),1)]),S(C,{status:e.status,size:`sm`},null,8,[`status`])],10,D))),128)),f.value.length===0?(o(),s(`div`,j,` 暂无待命车辆 `)):a(``,!0)])]))}}),N={class:`bg-white rounded-lg border shadow-sm p-4 space-y-4`},P={class:`text-sm font-medium mt-1`},ee={key:0,class:`text-gray-400`},F={key:1,class:`text-blue-600`},I=[`value`],L={key:0,class:`text-xs text-gray-400 mt-1`},R={class:`grid grid-cols-3 gap-3`},z=[`value`],B={key:0,class:`flex items-center gap-2`},V={key:1,class:`text-xs text-gray-400`},H=[`disabled`],U=n({__name:`DispatchPanel`,props:{selectedVins:{}},emits:[`dispatched`,`update:selectedVins`],setup(e,{emit:n}){let f=e,h=n,_=x();v();let S=d(``),C=d(`C30`),w=d(8),T=d(180),E=d(!0),D=d(15),O=d(!1),k=d(``),A=l(()=>_.sites),j=[`C15`,`C20`,`C25`,`C30`,`C35`,`C40`,`C45`,`C50`],M=l(()=>A.value.find(e=>e.fence_id===S.value)),U=l(()=>f.selectedVins.length>0&&S.value&&!O.value);async function W(){if(!U.value)return;O.value=!0,k.value=``;let e=M.value;if(e)try{let t=[];for(let n=0;n<f.selectedVins.length;n++){let r=f.selectedVins[n],i={station_id:e.station_id,destination_fence_id:e.fence_id,destination_name:e.name,concrete_grade:C.value,volume_m3:w.value,slump:T.value},a=await y.createOrder(i);await y.acceptOrder(a.order_id,r),t.push(a.order_id),E.value&&n<f.selectedVins.length-1&&await new Promise(e=>setTimeout(e,200))}k.value=`✅ 已派单 ${t.length} 台车 → ${e.name}`,h(`dispatched`),h(`update:selectedVins`,[])}catch(e){k.value=`❌ 派单失败: ${e.message}`}finally{O.value=!1}}return(n,l)=>(o(),s(`div`,N,[l[13]||=u(`h3`,{class:`font-semibold text-sm text-gray-700`},`派单信息`,-1),u(`div`,null,[l[6]||=u(`label`,{class:`text-xs text-gray-500`},`已选车辆`,-1),u(`div`,P,[e.selectedVins.length===0?(o(),s(`span`,ee,`请从左侧选择车辆`)):(o(),s(`span`,F,b(e.selectedVins.length)+` 台`,1))])]),u(`div`,null,[l[8]||=u(`label`,{class:`text-xs text-gray-500 block mb-1`},`目的地围栏`,-1),m(u(`select`,{"onUpdate:modelValue":l[0]||=e=>S.value=e,class:`w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500`},[l[7]||=u(`option`,{value:``,disabled:``},`请选择围栏`,-1),(o(!0),s(t,null,c(A.value,e=>(o(),s(`option`,{key:e.fence_id,value:e.fence_id},b(e.name)+` (`+b(e.group)+`) `,9,I))),128))],512),[[p,S.value]]),A.value.length===0?(o(),s(`div`,L,` 暂无可用围栏,请先创建工地围栏 `)):a(``,!0)]),u(`div`,R,[u(`div`,null,[l[9]||=u(`label`,{class:`text-xs text-gray-500 block mb-1`},`标号`,-1),m(u(`select`,{"onUpdate:modelValue":l[1]||=e=>C.value=e,class:`w-full border rounded-lg px-2 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500`},[(o(),s(t,null,c(j,e=>u(`option`,{key:e,value:e},b(e),9,z)),64))],512),[[p,C.value]])]),u(`div`,null,[l[10]||=u(`label`,{class:`text-xs text-gray-500 block mb-1`},`方量 (m³)`,-1),m(u(`input`,{"onUpdate:modelValue":l[2]||=e=>w.value=e,type:`number`,min:`1`,max:`20`,class:`w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500`},null,512),[[i,w.value,void 0,{number:!0}]])]),u(`div`,null,[l[11]||=u(`label`,{class:`text-xs text-gray-500 block mb-1`},`坍落度 (mm)`,-1),m(u(`input`,{"onUpdate:modelValue":l[3]||=e=>T.value=e,type:`number`,min:`80`,max:`240`,class:`w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500`},null,512),[[i,T.value,void 0,{number:!0}]])])]),e.selectedVins.length>1?(o(),s(`div`,B,[m(u(`input`,{type:`checkbox`,"onUpdate:modelValue":l[4]||=e=>E.value=e,class:`w-4 h-4 text-blue-600`},null,512),[[r,E.value]]),l[12]||=u(`label`,{class:`text-xs text-gray-600`},`自动错开发车`,-1),E.value?m((o(),s(`input`,{key:0,"onUpdate:modelValue":l[5]||=e=>D.value=e,type:`number`,min:`1`,max:`60`,class:`w-16 border rounded px-2 py-1 text-xs`},null,512)),[[i,D.value,void 0,{number:!0}]]):a(``,!0),E.value?(o(),s(`span`,V,`分钟/辆`)):a(``,!0)])):a(``,!0),k.value?(o(),s(`div`,{key:1,class:g([`text-sm`,k.value.startsWith(`✅`)?`text-green-600`:`text-red-500`])},b(k.value),3)):a(``,!0),u(`button`,{class:g([`w-full py-2.5 rounded-lg font-medium text-sm transition-colors`,U.value?`bg-blue-600 text-white hover:bg-blue-700`:`bg-gray-200 text-gray-400 cursor-not-allowed`]),disabled:!U.value,onClick:W},b(O.value?`派单中...`:`🚀 派单 (${e.selectedVins.length}台)`),11,H)]))}}),W={class:`bg-white rounded-lg border shadow-sm overflow-hidden`},G={class:`px-4 py-3 bg-gray-50 border-b`},K={class:`font-semibold text-sm text-gray-700`},q={class:`overflow-x-auto`},J={class:`w-full text-sm`},Y={class:`divide-y`},X={class:`px-4 py-2.5 font-medium text-gray-800`},te={class:`px-4 py-2.5`},Z={class:`px-4 py-2.5 text-gray-600`},Q={class:`px-4 py-2.5 text-gray-600`},ne={class:`px-4 py-2.5`},re={class:`flex gap-1`},ie=[`onClick`],ae=[`onClick`],oe={key:0},$={class:`bg-white rounded-xl shadow-2xl w-full max-w-sm p-6`},se={class:`text-center`},ce={class:`text-sm font-medium text-gray-700 mb-4`},le={class:`flex justify-center gap-3`},ue=[`disabled`],de=[`disabled`],fe=n({__name:`DispatchBoard`,setup(n){let r=v(),i=h(),p=l(()=>r.activeOrders);function m(e){return e?i.getByVin(e)?.plate_number||e.slice(-6):`-`}function x(e){return e?Math.round(y.getRemainingTime(e)/6e4):null}function w(e){return e===null?``:e<0?`text-red-600 font-bold`:e<30?`text-red-500`:e<60?`text-yellow-500`:`text-green-600`}let T=d(null),E=d(!1);function D(e,t){T.value={orderId:e,label:t}}function O(){T.value=null}async function k(){if(!(!T.value||E.value)){E.value=!0;try{await y.cancelOrder(T.value.orderId,`手动撤单`)}finally{E.value=!1,O()}}}return(n,r)=>(o(),s(t,null,[u(`div`,W,[u(`div`,G,[u(`h3`,K,` 调度看板 (`+b(p.value.length)+`) `,1)]),u(`div`,q,[u(`table`,J,[r[1]||=u(`thead`,{class:`bg-gray-50 text-xs text-gray-500 uppercase`},[u(`tr`,null,[u(`th`,{class:`px-4 py-2 text-left`},`车辆`),u(`th`,{class:`px-4 py-2 text-left`},`状态`),u(`th`,{class:`px-4 py-2 text-left`},`目的地`),u(`th`,{class:`px-4 py-2 text-left`},`标号/方量`),u(`th`,{class:`px-4 py-2 text-left`},`初凝倒计时`),u(`th`,{class:`px-4 py-2 text-left`},`操作`)])],-1),u(`tbody`,Y,[(o(!0),s(t,null,c(p.value,n=>(o(),s(`tr`,{key:n.order_id,class:`hover:bg-gray-50`},[u(`td`,X,b(m(n.vin)),1),u(`td`,te,[S(C,{status:n.status,size:`sm`},null,8,[`status`])]),u(`td`,Z,b(n.destination_name),1),u(`td`,Q,b(n.concrete_grade)+` / `+b(n.volume_m3)+`m³ `,1),u(`td`,{class:g([`px-4 py-2.5 font-mono`,w(x(n))])},[x(n)===null?(o(),s(t,{key:1},[f(`-`)],64)):(o(),s(t,{key:0},[f(b(x(n)<0?`⚠ 已超时`:x(n)+` min`),1)],64))],2),u(`td`,ne,[u(`div`,re,[n.status!==`cancelled`&&n.status!==`completed`?(o(),s(`button`,{key:0,class:`px-2 py-1 text-xs rounded bg-red-50 text-red-600 hover:bg-red-100`,onClick:e=>D(n.order_id,`${m(n.vin)} → ${n.destination_name}`)},` 撤单 `,8,ie)):a(``,!0),n.status===`paused`?(o(),s(`button`,{key:1,class:`px-2 py-1 text-xs rounded bg-green-50 text-green-600 hover:bg-green-100`,onClick:t=>e(y).resumeOrder(n.order_id)},` 恢复 `,8,ae)):a(``,!0)])])]))),128)),p.value.length===0?(o(),s(`tr`,oe,[...r[0]||=[u(`td`,{colspan:`6`,class:`px-4 py-8 text-center text-gray-400`},` 暂无进行中订单 `,-1)]])):a(``,!0)])])])]),T.value?(o(),s(`div`,{key:0,class:`fixed inset-0 bg-black/30 z-50 flex items-center justify-center`,onClick:_(O,[`self`])},[u(`div`,$,[u(`div`,se,[r[2]||=u(`div`,{class:`text-4xl mb-3`},`⚠️`,-1),r[3]||=u(`h3`,{class:`text-lg font-semibold text-gray-800 mb-2`},`确认撤单`,-1),r[4]||=u(`p`,{class:`text-sm text-gray-500 mb-1`},` 确定要撤销订单吗? `,-1),u(`p`,ce,b(T.value.label),1),u(`div`,le,[u(`button`,{class:`px-4 py-2 text-sm text-gray-600 bg-white border rounded-lg hover:bg-gray-100`,disabled:E.value,onClick:O},` 取消 `,8,ue),u(`button`,{class:`px-4 py-2 text-sm text-white bg-red-600 rounded-lg hover:bg-red-700 disabled:opacity-50`,disabled:E.value,onClick:k},b(E.value?`撤单中...`:`确认撤单`),9,de)])])])])):a(``,!0)],64))}}),pe={class:`space-y-4`},me={class:`grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3 md:gap-4`},he=n({__name:`DispatchCenter`,setup(e){let t=d([]);function n(){t.value=[]}return(e,r)=>(o(),s(`div`,pe,[r[2]||=u(`h1`,{class:`text-2xl font-bold`},`📋 调度中心`,-1),u(`div`,me,[S(M,{selectedVins:t.value,"onUpdate:selectedVins":r[0]||=e=>t.value=e},null,8,[`selectedVins`]),S(U,{selectedVins:t.value,onDispatched:n,"onUpdate:selectedVins":r[1]||=e=>t.value=e},null,8,[`selectedVins`])]),S(fe)]))}});export{he as default};
@@ -0,0 +1 @@
1
+ import{$ as e,A as t,B as ee,E as n,F as r,G as i,I as a,J as o,K as s,M as c,N as l,O as te,Q as u,R as d,U as ne,W as re,X as f,_ as ie,d as ae,et as p,k as oe,l as se,n as m,nt as h,tt as g,x as ce}from"./index-CTrnN2TM.js";var le={class:`flex items-center justify-between`},ue={class:`flex items-center gap-2`},de={class:`relative`},fe={class:`flex items-center justify-between mb-2`},pe={class:`flex gap-1`},me=[`value`],he={class:`text-xs text-gray-400`},ge={class:`bg-white rounded-xl border shadow-sm p-4`},_e={class:`flex items-center gap-3`},ve={class:`text-3xl`},ye={class:`flex-1 min-w-0`},be={class:`truncate`},xe={key:0,class:`mt-3 pt-3 border-t border-gray-100`},Se={key:0,class:`text-xs text-gray-400 text-center py-3`},Ce={class:`space-y-1 max-h-48 overflow-y-auto`},we=[`onClick`],Te={class:`font-medium`},Ee={class:`text-xs text-gray-400 ml-auto`},De={key:1,class:`space-y-3`},Oe={class:`text-sm font-semibold text-orange-700`},ke={class:`flex items-center justify-between mb-2`},Ae={class:`font-semibold text-sm`},je={class:`text-xs text-gray-500 mb-3`},Me={key:0,class:`ml-2 text-orange-500`},Ne={class:`flex gap-2`},Pe=[`disabled`,`onClick`],_=[`disabled`,`onClick`],v=[`disabled`,`onClick`],y={key:2,class:`space-y-3`},Fe={class:`text-sm font-semibold text-blue-700`},Ie={class:`flex items-center justify-between mb-2`},Le={class:`font-semibold text-sm`},Re={class:`text-xs text-gray-500 mb-2`},ze={key:0,class:`ml-2 text-orange-500`},Be={class:`w-full bg-gray-200 rounded-full h-1.5 mb-3`},Ve={class:`flex gap-2 flex-wrap`},He=[`disabled`,`onClick`],Ue=[`disabled`,`onClick`],We=[`disabled`,`onClick`],Ge={key:3,class:`bg-gray-50 border border-gray-200 rounded-xl p-6 text-center text-gray-400`},Ke={key:4,class:`bg-amber-50 border border-amber-200 rounded-xl p-6 text-center`},qe={key:5,class:`space-y-2`},Je={class:`text-sm font-semibold text-gray-500`},Ye={class:`flex items-center justify-between`},Xe={class:`text-xs font-medium text-gray-600`},Ze={class:`text-[11px] text-gray-400`},Qe={class:`grid grid-cols-2 gap-3`},$e={key:6,class:`bg-white rounded-xl border shadow-sm p-4 space-y-3`},et={class:`flex items-center justify-between`},tt={key:0,class:`text-xs text-red-500`},nt=[`disabled`],rt={key:7,class:`bg-white rounded-xl border shadow-sm p-4 space-y-3`},it={class:`flex items-center justify-between`},at={class:`flex flex-wrap gap-2`},ot=[`onClick`],st={class:`flex gap-2`},ct=[`disabled`],b=ee({__name:`DriverView`,setup(ee){let b=ce(),x=ie(),S=se(),C=ae(),w=u(!1),T=u(!1),E=u(!1),D=u(!1),O=u(!1),k=u(``),A=u(``),j=u(null),M=u(``),N=u(``),P=u(`other`),F=u(!1),I=c(()=>`${window.location.origin}/#/driver`);async function lt(){try{await navigator.clipboard.writeText(I.value),O.value=!0,setTimeout(()=>{O.value=!1},2e3)}catch{let e=document.createElement(`textarea`);e.value=I.value,e.style.position=`fixed`,e.style.opacity=`0`,document.body.appendChild(e),e.select(),document.execCommand(`copy`),document.body.removeChild(e),O.value=!0,setTimeout(()=>{O.value=!1},2e3)}}let L=u(localStorage.getItem(`__mf_driver_vin`)||``),R=c(()=>x.currentUser?.assigned_vin?x.currentUser.assigned_vin:L.value?L.value:x.currentUser?.role===`driver`?C.archiveVehicles.find(e=>C.isVehicleOnline(e))?.vin??``:``),z=c(()=>R.value?C.getByVin(R.value):null),B=c(()=>C.archiveVehicles.filter(e=>e.tbox_id));async function ut(e){L.value=e,localStorage.setItem(`__mf_driver_vin`,e),E.value=!1,x.currentUser?.role===`driver`&&await x.setAssignedVin(e)}let V=c(()=>S.orders.filter(e=>e.vin===R.value&&[`pending`,`accepted`].includes(e.status))),H=c(()=>S.orders.filter(e=>e.vin===R.value&&![`completed`,`cancelled`,`pending`,`accepted`].includes(e.status))),U=c(()=>S.orders.filter(e=>e.vin===R.value&&[`completed`].includes(e.status)).slice(-5).reverse()),W={pending:`待接单`,accepted:`已接单`,loading:`装料中`,transporting:`运输中`,arrived:`已到达`,discharging:`卸料中`,completed:`已完成`,returning:`返回中`,paused:`已暂停`,cancelled:`已取消`},G={pending:`bg-amber-100 text-amber-700`,accepted:`bg-blue-100 text-blue-700`,loading:`bg-cyan-100 text-cyan-700`,transporting:`bg-sky-100 text-sky-700`,arrived:`bg-teal-100 text-teal-700`,discharging:`bg-green-100 text-green-700`,completed:`bg-gray-200 text-gray-500`,returning:`bg-purple-100 text-purple-700`,paused:`bg-yellow-100 text-yellow-700`,cancelled:`bg-red-100 text-red-500`};async function K(e){j.value=e;try{await m.driverAccept(e,x.currentUser?.id,x.currentUser?.username),Y([100,50,100]),X(`接单成功`,`订单 ${e.slice(-8)} 已确认`)}catch(e){console.error(`Accept failed:`,e)}j.value=null}async function q(e){let t=M.value||`司机主动拒绝`;j.value=e;try{await m.rejectOrder(e,t),M.value=``,X(`已拒单`,`订单 ${e.slice(-8)} 已取消`)}catch(e){console.error(`Reject failed:`,e)}j.value=null}async function dt(e){if(R.value){j.value=e;try{await m.acceptOrder(e,R.value,x.currentUser?.id,x.currentUser?.username),Y([100,50,100]),X(`开始装料`,`订单 ${e.slice(-8)} 进入装料流程`)}catch(e){console.error(`Start loading failed:`,e)}j.value=null}}async function ft(e){j.value=e;try{await m.complete(e),Y([200,100,200]),X(`卸料完成`,`订单 ${e.slice(-8)} 已完成`)}catch(e){console.error(`Complete failed:`,e)}j.value=null}async function pt(e){j.value=e;try{await m.pauseOrder(e,`司机主动暂停`),X(`任务暂停`,`订单 ${e.slice(-8)} 已暂停`)}catch(e){console.error(`Pause failed:`,e)}j.value=null}async function mt(e){j.value=e;try{await m.resumeOrder(e),X(`任务恢复`,`订单 ${e.slice(-8)} 已恢复`)}catch(e){console.error(`Resume failed:`,e)}j.value=null}async function ht(){if(N.value.trim()){F.value=!0;try{let e=H.value[0];e&&await m.pauseOrder(e.order_id,`故障上报: ${N.value}`),X(`故障已上报`,`${{mechanical:`机械故障`,pump:`泵送故障`,drum:`搅拌筒故障`,engine:`发动机故障`,other:`其他`}[P.value]}: ${N.value}`),Y([300,100,300]),N.value=``,P.value=`other`,T.value=!1}catch(e){console.error(`Fault report failed:`,e)}F.value=!1}}function J(){if(!k.value.trim())return;let e=S.orders.find(e=>e.qr_data===k.value.trim()||e.order_id===k.value.trim());if(!e){A.value=`未找到匹配订单,请检查编码`;return}A.value=``,K(e.order_id),w.value=!1,k.value=``}function Y(e){`vibrate`in navigator&&navigator.vibrate(e)}function X(e,t){`Notification`in window&&Notification.permission===`granted`&&new Notification(e,{body:t,icon:`/favicon.svg`})}let Z=u(0),Q=u(!1),$=0;function gt(e){window.scrollY===0&&($=e.touches[0].clientY,Q.value=!0)}function _t(e){Q.value&&(Z.value=Math.max(0,e.touches[0].clientY-$))}function vt(){Z.value>80&&(S.load(),Y(50)),Z.value=0,Q.value=!1}return o(()=>x.currentUser?.assigned_vin,e=>{e&&e!==L.value&&(L.value=e,localStorage.setItem(`__mf_driver_vin`,e))}),ne(async()=>{S.loaded||await S.load()}),re(()=>{}),(ee,o)=>(i(),a(`div`,{class:`space-y-4 max-w-md mx-auto`,onTouchstart:gt,onTouchmove:_t,onTouchend:vt},[Q.value&&Z.value>20?(i(),a(`div`,{key:0,class:`text-center text-xs text-blue-500 transition-all`,style:g({opacity:Math.min(1,Z.value/80)})},h(Z.value>80?`✅ 释放刷新`:`⬇️ 下拉刷新`),5)):r(``,!0),l(`div`,le,[o[18]||=l(`h1`,{class:`text-xl font-bold`},`🚛 司机面板`,-1),l(`div`,ue,[l(`div`,de,[l(`button`,{class:`text-xs text-blue-500 hover:text-blue-700 bg-blue-50 hover:bg-blue-100 rounded-lg px-2.5 py-1.5 transition-colors min-h-[36px] flex items-center gap-1`,onClick:o[0]||=e=>D.value=!D.value},h(O.value?`✅ 已复制`:`🔗 分享`),1),D.value?(i(),a(`div`,{key:0,class:`absolute right-0 top-full mt-1 bg-white border shadow-lg rounded-lg p-3 z-50 w-72`,onClick:o[3]||=oe(()=>{},[`stop`])},[l(`div`,fe,[o[16]||=l(`span`,{class:`text-xs font-medium text-gray-600`},`司机面板链接`,-1),l(`button`,{class:`text-xs text-gray-400 hover:text-gray-600`,onClick:o[1]||=e=>D.value=!1},`✕`)]),o[17]||=l(`p`,{class:`text-[11px] text-gray-400 mb-2`},`将此链接发给司机,在浏览器中打开即可使用`,-1),l(`div`,pe,[l(`input`,{value:I.value,readonly:``,class:`flex-1 border rounded px-2 py-1.5 text-[11px] bg-gray-50 text-gray-600 truncate`,onFocus:o[2]||=e=>e.target.select()},null,40,me),l(`button`,{class:`bg-blue-600 text-white rounded px-3 py-1.5 text-xs font-medium hover:bg-blue-700 shrink-0`,onClick:lt},h(O.value?`已复制`:`复制`),1)])])):r(``,!0)]),l(`span`,he,h(e(x).currentUser?.username),1)])]),l(`div`,ge,[l(`div`,_e,[l(`span`,ve,h(H.value.length>0?`🔵`:`🟢`),1),l(`div`,ye,[l(`button`,{class:`text-lg font-bold hover:text-blue-600 transition-colors flex items-center gap-1`,onClick:o[4]||=e=>E.value=!E.value},[l(`span`,be,h(z.value?.plate_number||`选择车辆`),1),o[19]||=l(`span`,{class:`text-xs text-gray-300`},`▼`,-1)]),l(`div`,{class:p([`text-xs`,z.value&&e(C).isVehicleOnline(z.value)?`text-green-600`:`text-red-500`])},[l(`span`,{class:p([`inline-block w-1.5 h-1.5 rounded-full mr-1`,z.value&&e(C).isVehicleOnline(z.value)?`bg-green-500`:`bg-red-400`])},null,2),d(` `+h(z.value?e(C).isVehicleOnline(z.value)?`在线`:`离线`:`未选择车辆`),1)],2)]),l(`button`,{class:`shrink-0 text-xs bg-red-50 text-red-600 rounded-lg px-3 py-2 hover:bg-red-100 min-h-[44px]`,onClick:o[5]||=e=>T.value=!T.value},` ⚠️ 报故障 `)]),E.value?(i(),a(`div`,xe,[o[20]||=l(`p`,{class:`text-xs text-gray-400 mb-2`},`选择需要操作的车辆:`,-1),B.value.length===0?(i(),a(`div`,Se,` 暂无可选车辆,请先在车辆档案中绑定 TBox `)):r(``,!0),l(`div`,Ce,[(i(!0),a(t,null,s(B.value,t=>(i(),a(`button`,{key:t.vin,class:p([`w-full flex items-center gap-2 px-3 py-2 rounded-lg text-sm transition-colors`,t.vin===R.value?`bg-blue-50 text-blue-700`:`hover:bg-gray-50 text-gray-600`]),onClick:e=>ut(t.vin)},[l(`span`,{class:p([`w-1.5 h-1.5 rounded-full`,e(C).isVehicleOnline(t)?`bg-green-500`:`bg-gray-400`])},null,2),l(`span`,Te,h(t.plate_number),1),l(`span`,Ee,h(t.tbox_id?`已绑定`:`未绑定`),1)],10,we))),128))])])):r(``,!0)]),V.value.length>0?(i(),a(`div`,De,[l(`h3`,Oe,`📋 待接单 (`+h(V.value.length)+`)`,1),(i(!0),a(t,null,s(V.value,e=>(i(),a(`div`,{key:e.order_id,class:`bg-orange-50 border border-orange-200 rounded-xl p-4`},[l(`div`,ke,[l(`span`,Ae,h(e.destination_name||`未指定工地`),1),l(`span`,{class:p([`inline-flex items-center rounded-full px-1.5 py-0.5 text-xs font-medium`,G[e.status]||`bg-gray-100 text-gray-600`])},h(W[e.status]||e.status),3)]),l(`div`,je,[d(h(e.concrete_grade)+` · `+h(e.volume_m3)+` m³ `,1),e.required_arrival_by?(i(),a(`span`,Me,` 需 `+h(new Date(e.required_arrival_by).toLocaleTimeString(`zh-CN`,{hour:`2-digit`,minute:`2-digit`}))+` 前到达 `,1)):r(``,!0)]),l(`div`,Ne,[e.status===`pending`?(i(),a(`button`,{key:0,class:`flex-1 bg-green-600 text-white rounded-lg py-3 text-sm font-medium hover:bg-green-700 min-h-[44px] disabled:opacity-50`,disabled:j.value===e.order_id,onClick:t=>K(e.order_id)},h(j.value===e.order_id?`处理中...`:`✅ 确认接单`),9,Pe)):r(``,!0),e.status===`pending`?(i(),a(`button`,{key:1,class:`px-3 bg-red-50 text-red-600 rounded-lg py-3 text-sm hover:bg-red-100 min-h-[44px]`,disabled:j.value===e.order_id,onClick:t=>q(e.order_id)},` ✕ `,8,_)):r(``,!0),e.status===`accepted`?(i(),a(`button`,{key:2,class:`flex-1 bg-blue-600 text-white rounded-lg py-3 text-sm font-medium hover:bg-blue-700 min-h-[44px]`,disabled:j.value===e.order_id,onClick:t=>dt(e.order_id)},h(j.value===e.order_id?`处理中...`:`🚛 开始装料`),9,v)):r(``,!0)])]))),128))])):r(``,!0),H.value.length>0?(i(),a(`div`,y,[l(`h3`,Fe,`🔵 进行中 (`+h(H.value.length)+`)`,1),(i(!0),a(t,null,s(H.value,t=>(i(),a(`div`,{key:t.order_id,class:p([`rounded-xl p-4 border`,{"bg-blue-50 border-blue-200":![`discharging`].includes(t.status),"bg-green-50 border-green-200":t.status===`discharging`}])},[l(`div`,Ie,[l(`span`,Le,h(t.destination_name||`未指定工地`),1),l(`span`,{class:p([`inline-flex items-center rounded-full px-1.5 py-0.5 text-xs font-medium`,G[t.status]||`bg-gray-100 text-gray-600`])},h(W[t.status]||t.status),3)]),l(`div`,Re,[d(h(t.concrete_grade)+` · `+h(t.volume_m3)+` m³ `,1),t.required_arrival_by?(i(),a(`span`,ze,` 需 `+h(new Date(t.required_arrival_by).toLocaleTimeString(`zh-CN`,{hour:`2-digit`,minute:`2-digit`}))+` 前到达 `,1)):r(``,!0)]),l(`div`,Be,[l(`div`,{class:p([`rounded-full h-1.5 transition-all duration-500`,{"bg-blue-500":[`loading`,`transporting`].includes(t.status),"bg-teal-500":t.status===`arrived`,"bg-green-500":t.status===`discharging`}]),style:g({width:({loading:15,transporting:35,arrived:60,discharging:80,pending:5,accepted:10,returning:90,paused:35}[t.status]||50)+`%`})},null,6)]),l(`div`,Ve,[t.status===`discharging`?(i(),a(`button`,{key:0,class:`flex-1 bg-green-600 text-white rounded-lg py-2.5 text-sm font-medium hover:bg-green-700 min-h-[44px] disabled:opacity-50`,disabled:j.value===t.order_id,onClick:e=>ft(t.order_id)},h(j.value===t.order_id?`处理中...`:`✅ 卸料完成`),9,He)):r(``,!0),[`loading`,`transporting`,`arrived`,`discharging`].includes(t.status)?(i(),a(`button`,{key:1,class:`px-3 bg-yellow-50 text-yellow-600 rounded-lg py-2.5 text-sm hover:bg-yellow-100 min-h-[44px]`,disabled:j.value===t.order_id,onClick:e=>pt(t.order_id)},` ⏸ `,8,Ue)):r(``,!0),t.status===`paused`?(i(),a(`button`,{key:2,class:`flex-1 bg-blue-600 text-white rounded-lg py-2.5 text-sm font-medium hover:bg-blue-700 min-h-[44px] disabled:opacity-50`,disabled:j.value===t.order_id,onClick:e=>mt(t.order_id)},` ▶️ 恢复运输 `,8,We)):r(``,!0),l(`button`,{class:`px-3 bg-white border rounded-lg py-2.5 text-xs text-gray-500 hover:bg-gray-50 min-h-[44px]`,onClick:o[6]||=t=>e(b).push(`/monitor`)},` 🗺️ `)])],2))),128))])):r(``,!0),R.value&&V.value.length===0&&H.value.length===0?(i(),a(`div`,Ge,[...o[21]||=[l(`div`,{class:`text-3xl mb-2`},`☕`,-1),l(`div`,{class:`text-sm mb-1`},`暂无任务`,-1),l(`div`,{class:`text-xs`},`请等待调度分配或使用扫码接单`,-1)]])):r(``,!0),R.value?r(``,!0):(i(),a(`div`,Ke,[...o[22]||=[l(`div`,{class:`text-3xl mb-2`},`🚛`,-1),l(`div`,{class:`text-sm font-medium text-amber-700 mb-1`},`请先选择车辆`,-1),l(`div`,{class:`text-xs text-amber-500`},`点击上方车辆名称选择您当前操作的车辆`,-1)]])),U.value.length>0?(i(),a(`div`,qe,[l(`h3`,Je,`✅ 今日完成 (`+h(U.value.length)+`)`,1),(i(!0),a(t,null,s(U.value,e=>(i(),a(`div`,{key:e.order_id,class:`bg-gray-50 border border-gray-200 rounded-lg p-3`},[l(`div`,Ye,[l(`span`,Xe,h(e.destination_name),1),l(`span`,Ze,h(e.concrete_grade)+` · `+h(e.volume_m3)+`m³`,1)])]))),128))])):r(``,!0),l(`div`,Qe,[l(`button`,{class:`bg-white border rounded-xl p-4 text-center hover:bg-gray-50 min-h-[60px]`,onClick:o[7]||=t=>e(b).push(`/monitor`)},[...o[23]||=[l(`div`,{class:`text-xl`},`🗺️`,-1),l(`div`,{class:`text-xs mt-1`},`实时地图`,-1)]]),l(`button`,{class:`bg-white border rounded-xl p-4 text-center hover:bg-gray-50 min-h-[60px]`,onClick:o[8]||=e=>w.value=!w.value},[...o[24]||=[l(`div`,{class:`text-xl`},`📷`,-1),l(`div`,{class:`text-xs mt-1`},`扫码接单`,-1)]]),l(`button`,{class:`bg-white border rounded-xl p-4 text-center hover:bg-gray-50 min-h-[60px]`,onClick:o[9]||=t=>e(b).push(`/alarms`)},[...o[25]||=[l(`div`,{class:`text-xl`},`🔔`,-1),l(`div`,{class:`text-xs mt-1`},`告警中心`,-1)]]),l(`button`,{class:`bg-white border rounded-xl p-4 text-center hover:bg-gray-50 min-h-[60px]`,onClick:o[10]||=t=>e(b).push(`/orders`)},[...o[26]||=[l(`div`,{class:`text-xl`},`📦`,-1),l(`div`,{class:`text-xs mt-1`},`订单历史`,-1)]])]),w.value?(i(),a(`div`,$e,[l(`div`,et,[o[27]||=l(`h3`,{class:`font-semibold text-sm`},`📷 扫码接单`,-1),l(`button`,{class:`text-xs text-gray-400 hover:text-gray-600`,onClick:o[11]||=e=>w.value=!1},`✕`)]),o[28]||=l(`p`,{class:`text-xs text-gray-500`},`手动输入订单编号或 QR 编码`,-1),f(l(`input`,{"onUpdate:modelValue":o[12]||=e=>k.value=e,type:`text`,placeholder:`输入订单编码...`,class:`w-full border rounded-lg px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500`,onKeyup:te(J,[`enter`])},null,544),[[n,k.value]]),A.value?(i(),a(`div`,tt,h(A.value),1)):r(``,!0),l(`button`,{class:`w-full bg-blue-600 text-white rounded-lg py-2.5 text-sm font-medium hover:bg-blue-700 disabled:opacity-50`,disabled:!k.value.trim(),onClick:J},` 🔍 查找并接单 `,8,nt)])):r(``,!0),T.value?(i(),a(`div`,rt,[l(`div`,it,[o[29]||=l(`h3`,{class:`font-semibold text-sm`},`⚠️ 故障上报`,-1),l(`button`,{class:`text-xs text-gray-400 hover:text-gray-600`,onClick:o[13]||=e=>T.value=!1},`✕`)]),l(`div`,at,[(i(),a(t,null,s([`mechanical`,`pump`,`drum`,`engine`,`other`],e=>l(`button`,{key:e,class:p([`px-3 py-1.5 rounded-full text-xs transition-colors`,P.value===e?`bg-red-100 text-red-700 font-medium`:`bg-gray-100 text-gray-500 hover:bg-gray-200`]),onClick:t=>P.value=e},h({mechanical:`机械`,pump:`泵送`,drum:`搅拌筒`,engine:`发动机`,other:`其他`}[e]),11,ot)),64))]),f(l(`textarea`,{"onUpdate:modelValue":o[14]||=e=>N.value=e,rows:`3`,placeholder:`描述故障现象...`,class:`w-full border rounded-lg px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-red-400 resize-none`},null,512),[[n,N.value]]),l(`div`,st,[l(`button`,{class:`flex-1 border rounded-lg py-2.5 text-sm text-gray-500 hover:bg-gray-50`,onClick:o[15]||=e=>T.value=!1},` 取消 `),l(`button`,{class:`flex-1 bg-red-600 text-white rounded-lg py-2.5 text-sm font-medium hover:bg-red-700 disabled:opacity-50`,disabled:!N.value.trim()||F.value,onClick:ht},h(F.value?`提交中...`:`🚨 提交故障`),9,ct)])])):r(``,!0)],32))}});export{b as default};
@@ -0,0 +1 @@
1
+ import{$ as e,A as t,B as n,C as r,E as i,F as a,G as o,H as s,I as c,J as l,K as u,M as d,N as f,P as ee,Q as p,R as m,S as te,U as h,W as ne,X as g,Y as re,et as _,j as ie,k as ae,l as v,nt as y,s as b,tt as x,z as S}from"./index-CTrnN2TM.js";import{t as C}from"./_plugin-vue_export-helper-S3RvzygF.js";var w={class:`bg-white rounded-lg border shadow-sm overflow-hidden`},T={class:`overflow-x-auto`},E={class:`w-full text-sm`},D={class:`divide-y`},O={class:`px-3 py-2.5`},k={class:`flex items-center gap-2`},A={class:`font-medium text-gray-800`},j={class:`px-3 py-2.5 text-xs`},M={class:`px-3 py-2.5 text-xs`},N={class:`px-3 py-2.5 text-xs text-gray-500`},P={class:`px-3 py-2.5`},F={class:`px-3 py-2.5`},I=[`onClick`],L={class:`px-3 py-2.5`},R={class:`flex gap-1`},z=[`onClick`],B=[`disabled`,`title`,`onClick`],V={key:0},H=n({__name:`FenceList`,props:{fences:{}},emits:[`edit`,`delete`,`toggle`],setup(e,{emit:n}){let r=n,i=v(),s={plant:`🏭 搅拌站`,construction_site:`🏗️ 工地`,parking:`🅿️ 停车场`,custom:`📍 自定义`},l={circle:`⭕ 圆形`,polygon:`🔷 多边形`};function d(e){return i.orders.filter(t=>t.destination_fence_id===e&&![`completed`,`cancelled`].includes(t.status)).length}return(n,i)=>(o(),c(`div`,w,[f(`div`,T,[f(`table`,E,[i[1]||=f(`thead`,{class:`bg-gray-50 text-xs text-gray-500 uppercase`},[f(`tr`,null,[f(`th`,{class:`px-3 py-2 text-left`},`名称`),f(`th`,{class:`px-3 py-2 text-left`},`类型`),f(`th`,{class:`px-3 py-2 text-left`},`形状`),f(`th`,{class:`px-3 py-2 text-left`},`分组`),f(`th`,{class:`px-3 py-2 text-left`},`进行中订单`),f(`th`,{class:`px-3 py-2 text-left`},`状态`),f(`th`,{class:`px-3 py-2 text-left`},`操作`)])],-1),f(`tbody`,D,[(o(!0),c(t,null,u(e.fences,e=>(o(),c(`tr`,{key:e.fence_id,class:`hover:bg-gray-50`},[f(`td`,O,[f(`div`,k,[f(`span`,{class:`w-3 h-3 rounded-full`,style:x({backgroundColor:e.color})},null,4),f(`span`,A,y(e.name),1)])]),f(`td`,j,y(s[e.type]??e.type),1),f(`td`,M,y(l[e.shape]??e.shape),1),f(`td`,N,y(e.group||`-`),1),f(`td`,P,[f(`span`,{class:_(d(e.fence_id)>0?`text-blue-600 font-medium`:`text-gray-400`)},y(d(e.fence_id)),3)]),f(`td`,F,[f(`button`,{class:_([`text-xs px-2 py-0.5 rounded-full transition-colors`,e.active?`bg-green-100 text-green-700`:`bg-gray-100 text-gray-400`]),onClick:t=>r(`toggle`,e.fence_id,!e.active)},y(e.active?`启用`:`禁用`),11,I)]),f(`td`,L,[f(`div`,R,[f(`button`,{class:`px-2 py-0.5 text-xs rounded bg-blue-50 text-blue-600 hover:bg-blue-100`,onClick:t=>r(`edit`,e.fence_id)},` 编辑 `,8,z),f(`button`,{class:`px-2 py-0.5 text-xs rounded bg-red-50 text-red-500 hover:bg-red-100`,disabled:d(e.fence_id)>0,title:d(e.fence_id)>0?`有进行中订单,无法删除`:``,onClick:t=>r(`delete`,e.fence_id)},` 删除 `,8,B)])])]))),128)),e.fences.length===0?(o(),c(`tr`,V,[...i[0]||=[f(`td`,{colspan:`7`,class:`px-4 py-8 text-center text-gray-400`},`暂无围栏`,-1)]])):a(``,!0)])])])]))}}),oe={key:0,class:`fixed inset-0 z-50 flex items-center justify-center`},se={class:`relative bg-white rounded-xl shadow-2xl max-w-2xl w-full mx-4 max-h-[95vh] overflow-y-auto`},ce={class:`flex items-center justify-between px-6 pt-5 pb-2`},le={class:`text-lg font-semibold text-gray-800`},ue={class:`px-6 pb-6 space-y-4`},U={class:`relative`},de={class:`relative`},fe={key:0,class:`absolute right-3 top-1/2 -translate-y-1/2`},pe={key:0,class:`absolute left-0 right-0 mt-1 bg-white border border-gray-200 rounded-lg shadow-lg z-[60] max-h-48 overflow-y-auto`},me=[`onClick`],he={class:`min-w-0`},ge={class:`text-gray-800 truncate`},_e={class:`text-xs text-gray-400`},ve={key:0,class:`absolute inset-0 flex items-center justify-center text-gray-400 text-sm z-10`},ye={key:1,class:`absolute bottom-2 left-2 bg-black/60 text-white text-xs px-2 py-1 rounded z-20 pointer-events-none`},be={class:`grid grid-cols-1 sm:grid-cols-2 gap-3`},xe={class:`flex gap-2 flex-wrap`},Se=[`onClick`],Ce={class:`grid grid-cols-1 sm:grid-cols-2 gap-3`},we={class:`text-xs font-medium text-gray-600 block mb-1.5`},Te={class:`flex justify-between text-xs text-gray-400 mt-1`},Ee=[`onClick`],De={class:`flex items-center gap-2`},W={class:`text-xs text-gray-400`},Oe={class:`border border-gray-200 rounded-lg p-3 bg-gray-50/50`},ke={class:`grid grid-cols-2 gap-2`},Ae={class:`text-xs text-gray-400 mt-1.5`},je={key:0,class:`block mt-0.5 text-blue-600`},Me={class:`flex items-center gap-2`},Ne={class:`relative inline-flex items-center cursor-pointer`},Pe={class:`flex justify-end gap-3 px-6 pb-5 pt-2 border-t border-gray-100`},Fe=[`disabled`],G=C(n({__name:`FenceCreator`,props:{fence:{},visible:{type:Boolean}},emits:[`close`,`saved`],setup(e,{emit:n}){let h=e,v=n,x=b(),C=d(()=>!!h.fence),w=p(``),T=p(``),E=p(`construction_site`),D=p(`circle`),O=p(`#e74c3c`),k=p(116.4074),A=p(39.9042),j=p(200),M=p(!0),N=p(!1),P=p(``),F=p([]),I=p(!1),L=p(!1),R=p(``),z=null,B=p(null),V=p(null),H=p(null),G=p(null),K=p(!1),q=null;function J(){w.value=``,T.value=``,E.value=`construction_site`,D.value=`circle`,O.value=`#e74c3c`,k.value=116.4074,A.value=39.9042,j.value=200,M.value=!0,P.value=``,R.value=``,F.value=[],L.value=!1}l(()=>h.visible,async e=>{e?(h.fence?(w.value=h.fence.name,T.value=h.fence.group,E.value=h.fence.type,D.value=h.fence.shape,O.value=h.fence.color,h.fence.geometry.center&&(k.value=h.fence.geometry.center.lng,A.value=h.fence.geometry.center.lat),j.value=h.fence.geometry.radius??200,M.value=h.fence.active,R.value=h.fence.address??``,P.value=h.fence.address??``):J(),await s(),setTimeout(()=>Ie(),150)):X()}),ne(()=>{X()});function Y(){return window.AMap??null}function X(){H.value&&=(H.value.setMap(null),null),G.value&&=(G.value.setMap(null),null),V.value&&=(V.value.destroy(),null),K.value=!1,q=null}function Ie(){if(!B.value)return;let e=Y();e&&(X(),V.value=new e.Map(B.value,{zoom:15,center:[k.value,A.value],resizeEnable:!1}),q=new e.Geocoder({city:`全国`}),V.value.on(`click`,e=>{let t=e;k.value=t.lnglat.getLng(),A.value=t.lnglat.getLat(),Q(),Re()}),B.value.addEventListener(`wheel`,Le),Z(),K.value=!0,R.value&&$(R.value))}function Z(){let e=V.value,t=Y();if(!e||!t)return;H.value&&H.value.setMap(null),G.value&&G.value.setMap(null),H.value=new t.Circle({center:[k.value,A.value],radius:j.value,fillOpacity:.18,fillColor:O.value,strokeColor:O.value,strokeWeight:2,zIndex:10}),H.value.setMap(e),e.add(H.value),G.value=new t.Marker({position:[k.value,A.value],content:`<div style="width:16px;height:16px;background:${O.value};border:2px solid #fff;border-radius:50%;box-shadow:0 0 4px rgba(0,0,0,0.4);cursor:pointer;transform:translate(-50%,-50%)"></div>`,offset:new t.Pixel(-8,-8),zIndex:20}),G.value.setMap(e),e.add(G.value),e.setCenter([k.value,A.value]);let n=j.value>1e3?13:j.value>500?14:15;e.setZoom(n)}function Q(){let e=V.value;if(e){if(H.value)H.value.setOptions({center:[k.value,A.value],radius:j.value,fillColor:O.value,strokeColor:O.value});else{Z();return}G.value&&(G.value.setPosition([k.value,A.value]),G.value.setContent(`<div style="width:16px;height:16px;background:${O.value};border:2px solid #fff;border-radius:50%;box-shadow:0 0 4px rgba(0,0,0,0.4);cursor:pointer;transform:translate(-50%,-50%)"></div>`)),e.setCenter([k.value,A.value])}}function Le(e){e.preventDefault();let t=e.deltaY>0?-50:50;j.value=Math.max(50,Math.min(5e3,j.value+t)),Q()}function Re(){q&&q.getAddress([k.value,A.value],(e,t)=>{e===`complete`&&t.regeocode&&(R.value=t.regeocode.formattedAddress,P.value=t.regeocode.formattedAddress)})}function ze(){if(z&&clearTimeout(z),!P.value.trim()){F.value=[],L.value=!1;return}z=setTimeout(()=>$(P.value),400)}function $(e){if(!q){let e=Y();if(!e)return;q=new e.Geocoder({city:`全国`})}I.value=!0,q.getLocation(e,(t,n)=>{I.value=!1,t===`complete`&&n.geocodes?.length>0?(F.value=n.geocodes.map(t=>({name:t.formattedAddress||t.addressComponent?`${t.addressComponent?.district??``}${t.addressComponent?.township??``}`:e,address:t.formattedAddress||e,lng:t.location.lng,lat:t.location.lat})),L.value=F.value.length>0):(F.value=[],L.value=!1)})}function Be(e){k.value=e.lng,A.value=e.lat,R.value=e.address,P.value=e.address,L.value=!1,Q(),V.value&&V.value.setCenter([e.lng,e.lat])}function Ve(){return(E.value===`plant`?`FENCE_PLANT_`:`FENCE_SITE_`)+Date.now().toString(36).toUpperCase()}async function He(){if(!w.value.trim())return;N.value=!0;let e=Date.now(),t={fence_id:h.fence?.fence_id??Ve(),station_id:h.fence?.station_id??`station_a`,name:w.value,group:T.value,type:E.value,shape:D.value,geometry:D.value===`circle`?{center:{lng:k.value,lat:A.value},radius:j.value}:{polygon:[]},color:O.value,address:R.value||void 0,active:M.value,created_at:h.fence?.created_at??e,updated_at:e};await x.upsert(t),J(),N.value=!1,v(`saved`),v(`close`)}let Ue=[{key:`construction_site`,label:`工地`,icon:`🏗️`,color:`#e74c3c`},{key:`plant`,label:`搅拌站`,icon:`🏭`,color:`#3498db`},{key:`parking`,label:`停车场`,icon:`🅿️`,color:`#2ecc71`},{key:`custom`,label:`自定义`,icon:`📍`,color:`#9b59b6`}];function We(e){E.value=e.key,O.value=e.color,Q()}let Ge=[100,200,500,1e3,2e3];return(n,s)=>(o(),ee(ie,{to:`body`},[S(te,{name:`fade`},{default:re(()=>[e.visible?(o(),c(`div`,oe,[f(`div`,{class:`absolute inset-0 bg-black/40`,onClick:[s[0]||=e=>v(`close`),s[1]||=ae(()=>{},[`stop`])]}),f(`div`,se,[f(`div`,ce,[f(`h3`,le,y(C.value?`编辑围栏`:`新建围栏`),1),f(`button`,{class:`w-7 h-7 flex items-center justify-center rounded-full text-gray-400 hover:text-gray-600 hover:bg-gray-100 transition-colors`,onClick:s[2]||=e=>v(`close`)},`✕`)]),f(`div`,ue,[f(`div`,U,[s[17]||=f(`label`,{class:`text-xs font-medium text-gray-600 block mb-1.5`},` 🔍 搜索地址 (输入地名自动定位) `,-1),f(`div`,de,[g(f(`input`,{"onUpdate:modelValue":s[3]||=e=>P.value=e,type:`text`,placeholder:`输入地址或地名,如:北京大兴搅拌站、XX大桥工地...`,class:`w-full border border-gray-300 rounded-lg pl-9 pr-8 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-shadow`,onInput:ze,onFocus:s[4]||=e=>P.value&&F.value.length>0&&(L.value=!0)},null,544),[[i,P.value]]),s[15]||=f(`span`,{class:`absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 text-sm`},`🔍`,-1),I.value?(o(),c(`span`,fe,[...s[14]||=[f(`span`,{class:`inline-block w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin`},null,-1)]])):a(``,!0),P.value&&!I.value?(o(),c(`button`,{key:1,class:`absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 text-xs`,onClick:s[5]||=e=>{P.value=``,L.value=!1}},`✕`)):a(``,!0)]),L.value&&F.value.length>0?(o(),c(`div`,pe,[(o(!0),c(t,null,u(F.value,(e,t)=>(o(),c(`div`,{key:t,class:`px-3 py-2.5 text-sm hover:bg-blue-50 cursor-pointer border-b border-gray-50 last:border-b-0 flex items-start gap-2`,onClick:t=>Be(e)},[s[16]||=f(`span`,{class:`text-blue-500 mt-0.5 shrink-0`},`📍`,-1),f(`div`,he,[f(`div`,ge,y(e.address),1),f(`div`,_e,y(e.lng.toFixed(4))+`, `+y(e.lat.toFixed(4)),1)])],8,me))),128))])):a(``,!0)]),f(`div`,null,[s[18]||=f(`label`,{class:`text-xs font-medium text-gray-600 block mb-1.5`},` 🗺️ 点击地图设置圆心 (滚轮调整半径) `,-1),f(`div`,{ref_key:`miniMapContainer`,ref:B,class:`w-full h-64 rounded-lg border border-gray-200 overflow-hidden bg-gray-100 relative`},[K.value?a(``,!0):(o(),c(`div`,ve,` ⏳ 加载地图中... `)),K.value?(o(),c(`div`,ye,` 点击地图 = 设圆心 · 滚轮 = 调半径 `)):a(``,!0)],512)]),f(`div`,be,[f(`div`,null,[s[19]||=f(`label`,{class:`text-xs font-medium text-gray-600 block mb-1.5`},`名称 *`,-1),g(f(`input`,{"onUpdate:modelValue":s[6]||=e=>w.value=e,placeholder:`例如:XX大桥工地`,class:`w-full border border-gray-300 rounded-lg px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent`},null,512),[[i,w.value]])]),f(`div`,null,[s[20]||=f(`label`,{class:`text-xs font-medium text-gray-600 block mb-1.5`},`分组`,-1),g(f(`input`,{"onUpdate:modelValue":s[7]||=e=>T.value=e,placeholder:`例如:XX大桥项目`,class:`w-full border border-gray-300 rounded-lg px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent`},null,512),[[i,T.value]])])]),f(`div`,null,[s[21]||=f(`label`,{class:`text-xs font-medium text-gray-600 block mb-1.5`},`类型`,-1),f(`div`,xe,[(o(),c(t,null,u(Ue,e=>f(`button`,{key:e.key,class:_([`px-3 py-1.5 text-xs rounded-full border transition-all`,E.value===e.key?`border-blue-500 bg-blue-50 text-blue-700 font-medium`:`border-gray-200 text-gray-600 hover:border-gray-300`]),onClick:t=>We(e)},y(e.icon)+` `+y(e.label),11,Se)),64))])]),f(`div`,Ce,[f(`div`,null,[f(`label`,we,` 半径 `+y(j.value)+` 米 `,1),g(f(`input`,{"onUpdate:modelValue":s[8]||=e=>j.value=e,type:`range`,min:`50`,max:`5000`,step:`10`,class:`w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer accent-blue-600`,onInput:Q},null,544),[[i,j.value,void 0,{number:!0}]]),f(`div`,Te,[(o(),c(t,null,u(Ge,e=>f(`button`,{key:e,class:_([`hover:text-blue-600 transition-colors`,{"text-blue-600 font-medium":j.value===e}]),onClick:t=>{j.value=e,Q()}},y(e>=1e3?e/1e3+`km`:e+`m`),11,Ee)),64))])]),f(`div`,null,[s[22]||=f(`label`,{class:`text-xs font-medium text-gray-600 block mb-1.5`},`颜色标记`,-1),f(`div`,De,[g(f(`input`,{type:`color`,"onUpdate:modelValue":s[9]||=e=>O.value=e,class:`w-9 h-9 rounded-lg cursor-pointer border border-gray-300 p-0.5`,onInput:Q},null,544),[[i,O.value]]),f(`span`,W,y(O.value),1)])])]),f(`div`,Oe,[s[25]||=f(`div`,{class:`flex items-center gap-2 mb-2`},[f(`span`,{class:`text-xs font-medium text-gray-600`},`📐 手动输入经纬度`),f(`span`,{class:`text-[10px] text-gray-400`},`(无需地图可直接输入)`)],-1),f(`div`,ke,[f(`div`,null,[s[23]||=f(`label`,{class:`text-xs text-gray-500`},`经度 (Longitude)`,-1),g(f(`input`,{"onUpdate:modelValue":s[10]||=e=>k.value=e,type:`number`,step:`0.000001`,placeholder:`116.4074`,class:`w-full border rounded px-2 py-1.5 text-sm font-mono`,onInput:Q},null,544),[[i,k.value,void 0,{number:!0}]])]),f(`div`,null,[s[24]||=f(`label`,{class:`text-xs text-gray-500`},`纬度 (Latitude)`,-1),g(f(`input`,{"onUpdate:modelValue":s[11]||=e=>A.value=e,type:`number`,step:`0.000001`,placeholder:`39.9042`,class:`w-full border rounded px-2 py-1.5 text-sm font-mono`,onInput:Q},null,544),[[i,A.value,void 0,{number:!0}]])])]),f(`div`,Ae,[m(` 当前坐标:`+y(k.value.toFixed(6))+`, `+y(A.value.toFixed(6))+` `,1),R.value?(o(),c(`span`,je,`📍 `+y(R.value),1)):a(``,!0)])]),f(`div`,Me,[f(`label`,Ne,[g(f(`input`,{type:`checkbox`,"onUpdate:modelValue":s[12]||=e=>M.value=e,class:`sr-only peer`},null,512),[[r,M.value]]),s[26]||=f(`div`,{class:`w-9 h-5 bg-gray-200 peer-focus:ring-2 peer-focus:ring-blue-300 rounded-full peer peer-checked:after:translate-x-full peer-checked:bg-blue-600 after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:rounded-full after:h-4 after:w-4 after:transition-all`},null,-1)]),s[27]||=f(`span`,{class:`text-sm text-gray-600`},`启用围栏`,-1)])]),f(`div`,Pe,[f(`button`,{class:`px-4 py-2 text-sm text-gray-600 bg-gray-100 rounded-lg hover:bg-gray-200 transition-colors`,onClick:s[13]||=e=>v(`close`)},`取消`),f(`button`,{class:`px-5 py-2 text-sm text-white bg-blue-600 rounded-lg hover:bg-blue-700 disabled:opacity-50 transition-colors`,disabled:N.value||!w.value.trim(),onClick:He},y(N.value?`保存中...`:`保存围栏`),9,Fe)])])])):a(``,!0)]),_:1})]))}}),[[`__scopeId`,`data-v-05e388cc`]]),K={class:`space-y-4`},q={class:`flex gap-6 text-sm text-gray-500`},J={class:`text-green-600`},Y=n({__name:`GeoFenceManager`,setup(t){let n=b(),r=v(),i=p(!1),a=p(null);h(async()=>{await n.load(),await r.load()});function s(){a.value=null,i.value=!0}function l(e){a.value=n.getById(e)??null,i.value=!0}async function u(e){let t=n.getById(e);if(!t)return;let i=r.getByFence(e).filter(e=>![`completed`,`cancelled`].includes(e.status));if(i.length>0){window.alert(`无法删除围栏 "${t.name}",有 ${i.length} 个进行中订单`);return}confirm(`确认删除围栏 "${t.name}"?`)&&await n.remove(e)}async function d(e,t){await n.toggleActive(e,t)}return(t,r)=>(o(),c(`div`,K,[f(`div`,{class:`flex items-center justify-between`},[r[2]||=f(`h1`,{class:`text-2xl font-bold`},`📍 围栏管理`,-1),f(`button`,{class:`px-4 py-2 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700`,onClick:s},` + 新建围栏 `)]),f(`div`,q,[f(`span`,null,[r[3]||=m(`总共 `,-1),f(`strong`,null,y(e(n).fenceCount),1),r[4]||=m(` 个`,-1)]),f(`span`,null,[r[5]||=m(`启用 `,-1),f(`strong`,J,y(e(n).activeCount),1),r[6]||=m(` 个`,-1)]),f(`span`,null,[r[7]||=m(`工地 `,-1),f(`strong`,null,y(e(n).sites.length),1),r[8]||=m(` 个`,-1)]),f(`span`,null,[r[9]||=m(`搅拌站 `,-1),f(`strong`,null,y(e(n).plants.length),1),r[10]||=m(` 个`,-1)])]),S(H,{fences:e(n).fences,onEdit:l,onDelete:u,onToggle:d},null,8,[`fences`]),S(G,{fence:a.value,visible:i.value,onClose:r[0]||=e=>i.value=!1,onSaved:r[1]||=e=>i.value=!1},null,8,[`fence`,`visible`])]))}});export{Y as default};
@@ -0,0 +1 @@
1
+ .fade-enter-active[data-v-05e388cc],.fade-leave-active[data-v-05e388cc]{transition:opacity .2s}.fade-enter-from[data-v-05e388cc],.fade-leave-to[data-v-05e388cc]{opacity:0}@keyframes spin-05e388cc{to{transform:rotate(360deg)}}.animate-spin[data-v-05e388cc]{animation:.8s linear infinite spin-05e388cc}
@@ -0,0 +1 @@
1
+ .fade-enter-active[data-v-0fd82d41],.fade-leave-active[data-v-0fd82d41]{transition:opacity .25s}.fade-enter-from[data-v-0fd82d41],.fade-leave-to[data-v-0fd82d41]{opacity:0}
@@ -0,0 +1 @@
1
+ import{B as e,C as t,E as n,F as r,G as i,I as a,N as o,Q as s,R as c,S as l,U as u,X as d,Y as f,_ as p,et as m,nt as h,x as g,z as _}from"./index-CTrnN2TM.js";import{t as v}from"./_plugin-vue_export-helper-S3RvzygF.js";var y={class:`min-h-screen flex items-center justify-center bg-gray-100 px-4`},b={class:`w-full max-w-sm`},x={class:`bg-white rounded-2xl shadow-lg p-8`},S={class:`flex items-center gap-2 text-sm text-gray-500 cursor-pointer select-none`},C={key:0,role:`alert`,"aria-live":`assertive`,class:`text-sm text-red-600 bg-red-50 border border-red-200 rounded-lg px-3 py-2 text-center flex items-center justify-center gap-1.5`},w=[`disabled`],T={key:0,class:`inline-flex items-center gap-2`},E={key:1},D=v(e({__name:`LoginView`,setup(e){let v=g(),D=p(),O=s(``),k=s(``),A=s(!1),j=s(``),M=s(!1),N=s(!1);u(()=>{let e=localStorage.getItem(`__mf_remembered_user`);e&&(O.value=e,A.value=!0)});function P(){N.value=O.value.trim().length>0&&k.value.length>0}async function F(){if(!(!N.value||M.value)){M.value=!0,j.value=``;try{if(await D.login(O.value.trim(),k.value)){A.value?localStorage.setItem(`__mf_remembered_user`,O.value.trim()):localStorage.removeItem(`__mf_remembered_user`);let e=D.currentUser?.role===`driver`?`/driver`:`/`;v.replace(e)}else j.value=`用户名或密码错误`,setTimeout(()=>{j.value=``},3e3)}catch(e){j.value=`登录异常: `+e.message}finally{M.value=!1}}}function I(e){e.key===`Enter`&&F()}return(e,s)=>(i(),a(`div`,y,[o(`div`,b,[o(`div`,x,[s[8]||=o(`div`,{class:`text-center mb-6`},[o(`div`,{class:`text-4xl mb-2`},`🚛`),o(`h1`,{class:`text-xl font-bold text-gray-800`},`车队管理系统`),o(`p`,{class:`text-xs text-gray-400 mt-1`},`混凝土搅拌车 AI SaaS`)],-1),o(`div`,{class:`space-y-4`,onKeydown:I},[o(`div`,null,[s[3]||=o(`label`,{class:`block text-xs text-gray-500 mb-1`},`用户名`,-1),d(o(`input`,{"onUpdate:modelValue":s[0]||=e=>O.value=e,type:`text`,autocomplete:`username`,class:`w-full border rounded-lg px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-shadow`,placeholder:`请输入用户名`,onInput:P},null,544),[[n,O.value]])]),o(`div`,null,[s[4]||=o(`label`,{class:`block text-xs text-gray-500 mb-1`},`密码`,-1),d(o(`input`,{"onUpdate:modelValue":s[1]||=e=>k.value=e,type:`password`,autocomplete:`current-password`,class:`w-full border rounded-lg px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-shadow`,placeholder:`请输入密码`,onInput:P},null,544),[[n,k.value]])]),o(`label`,S,[d(o(`input`,{"onUpdate:modelValue":s[2]||=e=>A.value=e,type:`checkbox`,class:`rounded`},null,512),[[t,A.value]]),s[5]||=o(`span`,null,`记住我`,-1)]),_(l,{name:`fade`},{default:f(()=>[j.value?(i(),a(`div`,C,[s[6]||=o(`span`,{class:`text-base`},`⚠️`,-1),o(`span`,null,h(j.value),1)])):r(``,!0)]),_:1}),o(`button`,{class:m([`w-full py-2.5 rounded-lg text-sm font-medium transition-all`,N.value&&!M.value?`bg-blue-600 text-white hover:bg-blue-700 active:scale-[0.98] shadow-sm`:`bg-gray-200 text-gray-400 cursor-not-allowed`]),disabled:!N.value||M.value,onClick:F},[M.value?(i(),a(`span`,T,[...s[7]||=[o(`span`,{class:`animate-spin w-4 h-4 border-2 border-white/30 border-t-white rounded-full`},null,-1),c(` 验证中... `,-1)]])):(i(),a(`span`,E,`登 录`))],10,w)],32)]),s[9]||=o(`p`,{class:`text-center text-xs text-gray-400 mt-4`},` 默认账号: admin / admin123 `,-1),s[10]||=o(`p`,{class:`text-center text-[11px] text-gray-300 mt-1`},` 司机用户请在管理员处注册后登录,将自动跳转至司机面板 `,-1)])]))}}),[[`__scopeId`,`data-v-0fd82d41`]]);export{D as default};
@@ -0,0 +1 @@
1
+ import{A as e,B as t,F as n,G as r,I as i,K as a,M as o,N as s,d as c,l,nt as u}from"./index-CTrnN2TM.js";var d={class:`space-y-4`},f={class:`grid grid-cols-1 lg:grid-cols-2 gap-4`},p={class:`bg-white rounded-lg border shadow-sm p-4`},m={key:0,class:`space-y-2`},h={class:`flex-1 min-w-0`},g={class:`font-medium text-sm truncate`},_={class:`text-xs text-gray-500`},v={class:`text-right text-xs`},y={key:0,class:`text-gray-400`},b={key:1,class:`text-center py-8 text-gray-400 text-sm`},x={class:`bg-white rounded-lg border shadow-sm p-4`},S={key:0,class:`space-y-2`},C={class:`flex-1 min-w-0`},w={class:`font-medium text-sm truncate`},T={class:`text-xs text-gray-500`},E={class:`text-right text-xs`},D={class:`text-purple-600 font-medium`},O={class:`text-gray-400`},k={key:1,class:`text-center py-8 text-gray-400 text-sm`},A={class:`bg-white rounded-lg border shadow-sm p-4`},j={class:`grid grid-cols-2 gap-4 text-center text-sm`},M={class:`bg-green-50 rounded-lg p-4`},N={class:`text-2xl font-bold text-green-700`},P={class:`bg-purple-50 rounded-lg p-4`},F={class:`text-2xl font-bold text-purple-700`},I=t({__name:`MixerPumpBoard`,setup(t){let I=l(),L=c(),R=o(()=>I.orders.filter(e=>e.status===`discharging`).map(e=>({order:e,vehicle:e.vin?L.getByVin(e.vin):null})).filter(e=>e.vehicle?.vehicle_type===`搅拌车`)),z=o(()=>L.archiveVehicles.filter(e=>[`拖泵`,`车载泵`,`臂架泵车`].includes(e.vehicle_type))),B=o(()=>I.orders.filter(e=>e.status===`arrived`||e.status===`discharging`).map(e=>({order:e,vehicle:e.vin?L.getByVin(e.vin):null})).filter(e=>e.vehicle&&z.value.some(t=>t.vin===e.vehicle.vin)));function V(e){let t=Math.round((Date.now()-e)/6e4);return t<1?`刚刚`:t<60?`${t} 分钟前`:`${Math.floor(t/60)} 小时前`}return(t,o)=>(r(),i(`div`,d,[o[11]||=s(`h1`,{class:`text-2xl font-bold`},`🔄 协同看板`,-1),s(`div`,f,[s(`div`,p,[o[2]||=s(`h3`,{class:`font-semibold text-sm text-gray-700 mb-3`},`🚛 搅拌车卸料中`,-1),R.value.length>0?(r(),i(`div`,m,[(r(!0),i(e,null,a(R.value,e=>(r(),i(`div`,{key:e.order.order_id,class:`flex items-center gap-3 bg-blue-50 rounded-lg p-3`},[o[1]||=s(`span`,{class:`text-lg`},`🚛`,-1),s(`div`,h,[s(`div`,g,u(e.vehicle?.plate_number||`-`),1),s(`div`,_,u(e.order.concrete_grade)+` · `+u(e.order.volume_m3)+` m³ `,1)]),s(`div`,v,[o[0]||=s(`div`,{class:`text-blue-600 font-medium`},`卸料中`,-1),e.order.discharging_at?(r(),i(`div`,y,u(V(e.order.discharging_at)),1)):n(``,!0)])]))),128))])):(r(),i(`div`,b,`暂无搅拌车在卸料`))]),s(`div`,x,[o[4]||=s(`h3`,{class:`font-semibold text-sm text-gray-700 mb-3`},`⚡ 泵车泵送中`,-1),B.value.length>0?(r(),i(`div`,S,[(r(!0),i(e,null,a(B.value,e=>(r(),i(`div`,{key:e.order.order_id,class:`flex items-center gap-3 bg-purple-50 rounded-lg p-3`},[o[3]||=s(`span`,{class:`text-lg`},`⚡`,-1),s(`div`,C,[s(`div`,w,u(e.vehicle?.plate_number||`-`),1),s(`div`,T,u(e.vehicle?.vehicle_type||`-`),1)]),s(`div`,E,[s(`div`,D,u(e.order.status===`discharging`?`泵送中`:`待泵送`),1),s(`div`,O,`订单 `+u(e.order.order_id.slice(-6)),1)])]))),128))])):(r(),i(`div`,k,`暂无泵车在作业`))])]),s(`div`,A,[o[9]||=s(`h3`,{class:`font-semibold text-sm text-gray-700 mb-3`},`⏱ 协同时序`,-1),s(`div`,j,[s(`div`,M,[o[5]||=s(`div`,{class:`text-xs text-green-600 mb-1`},`卸料进行中`,-1),s(`div`,N,u(R.value.length),1),o[6]||=s(`div`,{class:`text-xs text-gray-400 mt-1`},`台搅拌车`,-1)]),s(`div`,P,[o[7]||=s(`div`,{class:`text-xs text-purple-600 mb-1`},`泵送进行中`,-1),s(`div`,F,u(B.value.length),1),o[8]||=s(`div`,{class:`text-xs text-gray-400 mt-1`},`台泵车`,-1)])]),o[10]||=s(`div`,{class:`mt-4 text-xs text-gray-400 text-center`},` ⚠️ 精确卸料-泵送时序需 CAN 数据(搅拌筒反转 + 泵送排量 >0 同时判定) `,-1)])]))}});export{I as default};
@@ -0,0 +1 @@
1
+ import{$ as e,A as t,B as n,F as r,G as i,I as a,K as o,L as s,M as c,N as l,Q as u,R as d,U as f,et as p,k as m,nt as h,tt as g,u as _,x as v}from"./index-CTrnN2TM.js";var y={class:`space-y-4`},b={key:0,class:`bg-white rounded-lg border p-4`},x={class:`flex items-center justify-between mb-3`},S={class:`flex items-center justify-between`},C={class:`flex gap-2`},w={class:`flex gap-1 bg-gray-100 rounded-lg p-1 w-fit`},T=[`onClick`],E={key:0,class:`ml-1 text-xs text-red-500 font-bold`},D={key:1,class:`bg-white rounded-lg border shadow-sm p-12 text-center text-gray-400`},O={key:2,class:`bg-white rounded-lg border shadow-sm divide-y`},k=[`onClick`,`onTouchstartPassive`,`onTouchend`],A={key:0,class:`mt-1.5 w-2 h-2 rounded-full bg-red-500 shrink-0`},j={key:1,class:`mt-1.5 w-2 h-2 rounded-full bg-gray-300 shrink-0`},M={class:`flex-1 min-w-0`},N={class:`flex items-center gap-2`},P={class:`text-xs rounded-full px-2 py-0.5 bg-gray-100 text-gray-500`},F={class:`text-sm font-medium text-gray-700 truncate`},I={class:`text-xs text-gray-400 mt-1 line-clamp-2`},L={class:`flex items-center gap-2 shrink-0`},ee={class:`text-xs text-gray-400`},R=[`onClick`],z={key:3,class:`text-center`},B=n({__name:`NotificationCenter`,setup(n){let B=v(),V=_(),H=u(`all`),U=u(!1),W=u(null),G=u(0),K=0,q=null;function J(e,t){q=t,K=e.touches[0].clientX,W.value=t}function Y(e){if(q===null)return;let t=e.touches[0].clientX-K;G.value=Math.min(0,t)}function X(e){G.value<-80&&V.removeNotification(e),G.value=0,W.value=null,q=null}let Z=[{key:`all`,label:`全部`,icon:`📋`},{key:`alarm`,label:`告警`,icon:`🔔`},{key:`order`,label:`订单`,icon:`📦`},{key:`system`,label:`系统`,icon:`⚙️`}],Q=c(()=>H.value===`all`?V.notifications:V.notifications.filter(e=>e.type===H.value)),$=c(()=>V.unreadCount>0);function te(e,t){V.markAsRead(e),t&&B.push(t)}function ne(e){return{alarm:`🔴 告警`,order:`🟡 订单`,system:`🔵 系统`}[e]||e}function re(e){let t=new Date(e),n=new Date;return t.toDateString()===n.toDateString()?t.toLocaleTimeString(`zh-CN`,{hour:`2-digit`,minute:`2-digit`}):t.toLocaleDateString(`zh-CN`,{month:`2-digit`,day:`2-digit`})+` `+t.toLocaleTimeString(`zh-CN`,{hour:`2-digit`,minute:`2-digit`})}return f(async()=>{V.notifications.length===0&&await V.loadNotifications()}),(n,c)=>(i(),a(`div`,y,[U.value?(i(),a(`div`,b,[l(`div`,x,[c[5]||=l(`h3`,{class:`font-semibold text-sm`},`通知偏好`,-1),l(`button`,{class:`text-xs text-gray-400 hover:text-gray-600`,onClick:c[0]||=e=>U.value=!1},`✕`)]),c[6]||=s(`<div class="grid grid-cols-2 md:grid-cols-4 gap-3"><label class="flex items-center gap-2 text-sm cursor-pointer"><input type="checkbox" checked class="rounded"> 告警通知 </label><label class="flex items-center gap-2 text-sm cursor-pointer"><input type="checkbox" checked class="rounded"> 订单通知 </label><label class="flex items-center gap-2 text-sm cursor-pointer"><input type="checkbox" class="rounded"> 系统通知 </label><label class="flex items-center gap-2 text-sm cursor-pointer"><input type="checkbox" checked class="rounded"> 桌面推送 </label></div>`,1)])):r(``,!0),l(`div`,S,[c[7]||=l(`h1`,{class:`text-2xl font-bold`},`💬 通知中心`,-1),l(`div`,C,[U.value?r(``,!0):(i(),a(`button`,{key:0,class:`px-2 py-1 text-xs text-gray-500 hover:text-blue-600`,onClick:c[1]||=e=>U.value=!0},`⚙️`)),$.value?(i(),a(`button`,{key:1,class:`px-3 py-1.5 text-xs bg-blue-50 text-blue-700 rounded-lg hover:bg-blue-100 transition-colors`,onClick:c[2]||=t=>e(V).markAllAsRead()},` ✅ 全部标为已读 `)):r(``,!0)])]),l(`div`,w,[(i(),a(t,null,o(Z,t=>l(`button`,{key:t.key,class:p([`px-4 py-1.5 text-sm rounded-md transition-colors`,H.value===t.key?`bg-white text-blue-600 shadow-sm font-medium`:`text-gray-500`]),onClick:e=>H.value=t.key},[d(h(t.icon)+` `+h(t.label)+` `,1),(t.key===`all`?e(V).unreadCount:e(V).notifications.filter(e=>e.type===t.key&&!e.read).length)?(i(),a(`span`,E,` (`+h(t.key===`all`?e(V).unreadCount:e(V).notifications.filter(e=>e.type===t.key&&!e.read).length)+`) `,1)):r(``,!0)],10,T)),64))]),Q.value.length===0?(i(),a(`div`,D,[...c[8]||=[l(`div`,{class:`text-4xl mb-3`},`📭`,-1),l(`p`,{class:`text-sm`},`暂无通知`,-1)]])):(i(),a(`div`,O,[(i(!0),a(t,null,o(Q.value,t=>(i(),a(`div`,{key:t.id,class:p([`px-4 py-3 flex items-start gap-3 cursor-pointer hover:bg-gray-50 transition-colors relative overflow-hidden`,t.read?``:`bg-blue-50/50`]),style:g(W.value===t.id?{transform:`translateX(${G.value}px)`,transition:`none`}:{transform:`translateX(0)`,transition:`transform 0.2s ease`}),onClick:e=>te(t.id,t.link),onTouchstartPassive:e=>J(e,t.id),onTouchmovePassive:c[3]||=e=>Y(e),onTouchend:e=>X(t.id)},[t.read?(i(),a(`span`,j)):(i(),a(`span`,A)),l(`div`,M,[l(`div`,N,[l(`span`,P,h(ne(t.type)),1),l(`span`,F,h(t.title),1)]),l(`p`,I,h(t.message),1)]),l(`div`,L,[l(`span`,ee,h(re(t.createdAt)),1),l(`button`,{class:`text-gray-300 hover:text-red-500 transition-colors`,title:`删除`,onClick:m(n=>e(V).removeNotification(t.id),[`stop`])},` ✕ `,8,R)])],46,k))),128))])),Q.value.length>0?(i(),a(`div`,z,[l(`button`,{class:`text-xs text-gray-400 hover:text-red-500 transition-colors`,onClick:c[4]||=t=>e(V).clearAll()},` 🗑️ 清空全部通知 `)])):r(``,!0)]))}});export{B as default};
@@ -0,0 +1 @@
1
+ import{$ as e,A as t,B as n,F as r,G as i,I as a,K as o,M as s,N as c,P as l,Q as u,R as d,S as f,U as p,V as m,Y as h,d as g,et as _,j as v,k as y,l as b,n as x,nt as S,q as C,s as w,z as T}from"./index-CTrnN2TM.js";import{t as E}from"./_plugin-vue_export-helper-S3RvzygF.js";import{t as D}from"./StatusBadge-kISgaxfW.js";var O={class:`bg-white rounded-lg border shadow-sm overflow-hidden`},ee={key:0,class:`px-4 py-2 bg-gray-50 border-b flex gap-2 flex-wrap`},k=[`onClick`],A={class:`overflow-x-auto`},j={class:`w-full text-sm`},M={class:`divide-y`},N=[`onClick`],P={class:`px-3 py-2.5 font-mono text-xs text-blue-600`},F={class:`px-3 py-2.5 font-medium`},I={class:`px-3 py-2.5`},L={class:`px-3 py-2.5 text-gray-600`},R={class:`px-3 py-2.5 text-gray-600`},z={class:`px-3 py-2.5 text-xs text-gray-400`},B={class:`px-3 py-2.5`},V=[`onClick`],H={key:1,class:`text-xs text-gray-300`},U={key:0},W=n({__name:`OrderList`,props:m({orders:{},showStatusFilter:{type:Boolean}},{statusFilter:{default:``},statusFilterModifiers:{}}),emits:m([`select`,`cancel`],[`update:statusFilter`]),setup(e,{emit:n}){let l=e,u=n,d=g(),f=w(),p=C(e,`statusFilter`),m=[{value:``,label:`全部`},{value:`pending`,label:`待接单`},{value:`loading`,label:`装料中`},{value:`transporting`,label:`运输中`},{value:`arrived`,label:`已到达`},{value:`discharging`,label:`卸料中`},{value:`completed`,label:`已完成`},{value:`returning`,label:`返回中`},{value:`paused`,label:`已暂停`},{value:`cancelled`,label:`已取消`}],h=s(()=>p.value?l.orders.filter(e=>e.status===p.value):l.orders);function v(e){return e?d.getByVin(e)?.plate_number??e.slice(-6):`-`}function b(e){return f.getById(e)?.name??e}function E(e){let t=x.getRemainingTime(e);if(t===1/0)return`-`;let n=Math.round(t/6e4);return n<0?`⚠ 超时`:`${n} min`}function W(e){return e?new Date(e).toLocaleString(`zh-CN`,{month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`}):`-`}return(n,s)=>(i(),a(`div`,O,[e.showStatusFilter===!1?r(``,!0):(i(),a(`div`,ee,[(i(),a(t,null,o(m,e=>c(`button`,{key:e.value,class:_([`px-2 py-1 text-xs rounded-full transition-colors`,p.value===e.value?`bg-blue-600 text-white`:`bg-white text-gray-500 border hover:border-blue-300`]),onClick:t=>p.value=e.value},S(e.label),11,k)),64))])),c(`div`,A,[c(`table`,j,[s[1]||=c(`thead`,{class:`bg-gray-50 text-xs text-gray-500 uppercase`},[c(`tr`,null,[c(`th`,{class:`px-3 py-2 text-left`},`订单ID`),c(`th`,{class:`px-3 py-2 text-left`},`车辆`),c(`th`,{class:`px-3 py-2 text-left`},`状态`),c(`th`,{class:`px-3 py-2 text-left`},`目的地`),c(`th`,{class:`px-3 py-2 text-left`},`标号/方量`),c(`th`,{class:`px-3 py-2 text-left`},`倒计时`),c(`th`,{class:`px-3 py-2 text-left`},`创建时间`),c(`th`,{class:`px-3 py-2 text-left`},`操作`)])],-1),c(`tbody`,M,[(i(!0),a(t,null,o(h.value,e=>(i(),a(`tr`,{key:e.order_id,class:`hover:bg-gray-50 cursor-pointer`,onClick:t=>u(`select`,e.order_id)},[c(`td`,P,S(e.order_id.slice(-12)),1),c(`td`,F,S(v(e.vin)),1),c(`td`,I,[T(D,{status:e.status,size:`sm`},null,8,[`status`])]),c(`td`,L,S(b(e.destination_fence_id)),1),c(`td`,R,S(e.concrete_grade)+` / `+S(e.volume_m3)+`m³`,1),c(`td`,{class:_([`px-3 py-2.5 font-mono text-xs`,E(e).startsWith(`⚠`)?`text-red-500`:``])},S(E(e)),3),c(`td`,z,S(W(e.created_at)),1),c(`td`,B,[[`completed`,`cancelled`].includes(e.status)?(i(),a(`span`,H,`-`)):(i(),a(`button`,{key:0,class:`px-2 py-0.5 text-xs rounded bg-red-50 text-red-600 hover:bg-red-100`,onClick:y(t=>u(`cancel`,e.order_id),[`stop`])},` 撤单 `,8,V))])],8,N))),128)),h.value.length===0?(i(),a(`tr`,U,[...s[0]||=[c(`td`,{colspan:`8`,class:`px-4 py-8 text-center text-gray-400`},`暂无订单`,-1)]])):r(``,!0)])])])]))}}),G={key:0,class:`fixed inset-0 z-40 flex justify-end`},K={class:`relative w-96 bg-white shadow-2xl overflow-y-auto`},q={class:`sticky top-0 bg-white border-b px-4 py-3 flex items-center justify-between`},J={key:0,class:`p-4 space-y-4`},Y={class:`font-mono text-sm font-medium`},X={class:`flex items-center gap-2`},Z={class:`bg-gray-50 rounded-lg p-3 space-y-1 text-sm`},Q={class:`flex justify-between`},te={class:`font-medium`},ne={class:`flex justify-between`},re={class:`font-mono text-xs`},ie={class:`flex justify-between`},ae={class:`bg-gray-50 rounded-lg p-3 space-y-1 text-sm`},oe={class:`flex justify-between`},se={class:`font-medium`},ce={class:`flex justify-between`},le={class:`flex justify-between`},ue={class:`bg-gray-50 rounded-lg p-3 space-y-1 text-sm`},de={class:`flex justify-between`},fe={class:`font-medium`},pe={class:`flex justify-between`},me={class:`font-mono text-xs`},he={class:`space-y-0`},ge={class:`flex flex-col items-center`},_e={key:0,class:`w-0.5 h-5 bg-gray-200`},ve={class:`pb-3`},ye={class:`text-xs font-medium`},be={class:`text-xs text-gray-400`},$={key:1,class:`p-8 text-center text-gray-400`},xe=E(n({__name:`OrderDetail`,props:{order:{},visible:{type:Boolean}},emits:[`close`],setup(e,{emit:n}){let u=e,d=n,p=g(),m=w(),y=s(()=>u.order?.vin?p.getByVin(u.order.vin):null);s(()=>u.order?m.getById(u.order.destination_fence_id):null);let b=s(()=>u.order?Math.round(x.getRemainingTime(u.order)/6e4):null);function C(e){return e?new Date(e).toLocaleString(`zh-CN`):`-`}let E=s(()=>{if(!u.order)return[];let e=u.order;return[{label:`创建`,time:e.created_at,active:!0},{label:`接单`,time:e.accepted_at,active:!!e.accepted_at},{label:`装料完成`,time:e.loaded_at,active:!!e.loaded_at},{label:`离场`,time:e.departed_at,active:!!e.departed_at},{label:`到达工地`,time:e.arrived_at,active:!!e.arrived_at},{label:`开始卸料`,time:e.discharging_at,active:!!e.discharging_at},{label:`完成`,time:e.completed_at,active:!!e.completed_at},{label:`取消`,time:e.cancelled_at,active:!!e.cancelled_at}]});return(n,s)=>(i(),l(v,{to:`body`},[T(f,{name:`slide`},{default:h(()=>[e.visible?(i(),a(`div`,G,[c(`div`,{class:`absolute inset-0 bg-black/30`,onClick:s[0]||=e=>d(`close`)}),c(`div`,K,[c(`div`,q,[s[2]||=c(`h3`,{class:`font-semibold text-gray-800`},`订单详情`,-1),c(`button`,{class:`text-gray-400 hover:text-gray-600 text-lg`,onClick:s[1]||=e=>d(`close`)},`✕`)]),e.order?(i(),a(`div`,J,[c(`div`,null,[s[3]||=c(`div`,{class:`text-xs text-gray-400 mb-1`},`订单ID`,-1),c(`div`,Y,S(e.order.order_id),1)]),c(`div`,X,[T(D,{status:e.order.status},null,8,[`status`]),b.value===null?r(``,!0):(i(),a(`span`,{key:0,class:_([`text-xs`,b.value<30?`text-red-500`:`text-gray-400`])},` 剩余 `+S(b.value)+` 分钟 `,3))]),c(`div`,Z,[c(`div`,Q,[s[4]||=c(`span`,{class:`text-gray-400`},`车辆`,-1),c(`span`,te,S(y.value?.plate_number||(e.order.vin?e.order.vin.slice(-6):`未接单`)),1)]),c(`div`,ne,[s[5]||=c(`span`,{class:`text-gray-400`},`VIN`,-1),c(`span`,re,S(e.order.vin??`-`),1)]),c(`div`,ie,[s[6]||=c(`span`,{class:`text-gray-400`},`司机`,-1),c(`span`,null,S(e.order.driver_name??`-`),1)])]),c(`div`,ae,[c(`div`,oe,[s[7]||=c(`span`,{class:`text-gray-400`},`标号`,-1),c(`span`,se,S(e.order.concrete_grade),1)]),c(`div`,ce,[s[8]||=c(`span`,{class:`text-gray-400`},`方量`,-1),c(`span`,null,S(e.order.volume_m3)+` m³`,1)]),c(`div`,le,[s[9]||=c(`span`,{class:`text-gray-400`},`坍落度`,-1),c(`span`,null,S(e.order.slump)+` mm`,1)])]),c(`div`,ue,[c(`div`,de,[s[10]||=c(`span`,{class:`text-gray-400`},`目的地`,-1),c(`span`,fe,S(e.order.destination_name),1)]),c(`div`,pe,[s[11]||=c(`span`,{class:`text-gray-400`},`围栏ID`,-1),c(`span`,me,S(e.order.destination_fence_id),1)])]),c(`div`,null,[s[12]||=c(`div`,{class:`text-xs text-gray-400 mb-2`},`状态流转`,-1),c(`div`,he,[(i(!0),a(t,null,o(E.value,(e,t)=>(i(),a(`div`,{key:e.label,class:_([`flex items-start gap-3`,{"opacity-30":!e.active}])},[c(`div`,ge,[c(`div`,{class:_([`w-2 h-2 rounded-full`,e.active?`bg-blue-500`:`bg-gray-300`])},null,2),t<E.value.length-1?(i(),a(`div`,_e)):r(``,!0)]),c(`div`,ve,[c(`div`,ye,S(e.label),1),c(`div`,be,S(C(e.time)),1)])],2))),128))])])])):(i(),a(`div`,$,`未选择订单`))])])):r(``,!0)]),_:1})]))}}),[[`__scopeId`,`data-v-3ad8d538`]]),Se={class:`space-y-4`},Ce={class:`flex gap-6 text-sm`},we={class:`text-gray-500`},Te={class:`text-gray-500`},Ee={class:`text-gray-500`},De={class:`flex gap-1 bg-gray-100 rounded-lg p-1 w-fit`},Oe=n({__name:`OrderManager`,setup(t){let n=b(),r=u(`active`),o=u(``),l=u(null),f=u(!1);p(async()=>{n.loaded||await n.load()});let m=s(()=>n.orders.filter(e=>![`completed`,`cancelled`].includes(e.status))),h=s(()=>n.orders.filter(e=>[`completed`,`cancelled`].includes(e.status))),g=s(()=>r.value===`active`?m.value:h.value),v=s(()=>l.value?n.getById(l.value)??null:null);function y(e){l.value=e,f.value=!0}async function C(e){await x.cancelOrder(e,`手动撤单`)}return(t,s)=>(i(),a(`div`,Se,[s[7]||=c(`h1`,{class:`text-2xl font-bold`},`📝 订单管理`,-1),c(`div`,Ce,[c(`span`,we,[s[4]||=d(`进行中: `,-1),c(`strong`,null,S(m.value.length),1)]),c(`span`,Te,[s[5]||=d(`已完成: `,-1),c(`strong`,null,S(h.value.length),1)]),c(`span`,Ee,[s[6]||=d(`总计: `,-1),c(`strong`,null,S(e(n).orderCount),1)])]),c(`div`,De,[c(`button`,{class:_([`px-4 py-1.5 text-sm rounded-md transition-colors`,r.value===`active`?`bg-white text-blue-600 shadow-sm font-medium`:`text-gray-500`]),onClick:s[0]||=e=>r.value=`active`},` 进行中 (`+S(m.value.length)+`) `,3),c(`button`,{class:_([`px-4 py-1.5 text-sm rounded-md transition-colors`,r.value===`history`?`bg-white text-blue-600 shadow-sm font-medium`:`text-gray-500`]),onClick:s[1]||=e=>r.value=`history`},` 历史订单 (`+S(h.value.length)+`) `,3)]),T(W,{orders:g.value,"show-status-filter":!0,statusFilter:o.value,"onUpdate:statusFilter":s[2]||=e=>o.value=e,onSelect:y,onCancel:C},null,8,[`orders`,`statusFilter`]),T(xe,{order:v.value,visible:f.value,onClose:s[3]||=e=>f.value=!1},null,8,[`order`,`visible`])]))}});export{Oe as default};
@@ -0,0 +1 @@
1
+ .slide-enter-active[data-v-3ad8d538],.slide-leave-active[data-v-3ad8d538]{transition:all .25s}.slide-enter-from[data-v-3ad8d538],.slide-leave-to[data-v-3ad8d538]{transform:translate(100%)}
@@ -0,0 +1 @@
1
+ import{$ as e,A as t,B as n,E as r,F as i,G as a,I as o,K as s,M as c,N as l,Q as u,R as d,X as f,d as p,et as m,l as h,nt as g,tt as _,z as v}from"./index-CTrnN2TM.js";var y={class:`grid grid-cols-2 lg:grid-cols-4 gap-3 md:gap-4`},b={class:`text-xs text-gray-500`},x=n({__name:`PumpStatsBar`,setup(e){let n=p(),r=c(()=>n.archiveVehicles.filter(e=>[`拖泵`,`车载泵`,`臂架泵车`].includes(e.vehicle_type))),i=c(()=>r.value.filter(e=>n.isVehicleOnline(e)).length),u=c(()=>r.value.filter(e=>e.status===`discharging`).length),d=c(()=>r.value.filter(e=>e.outrigger_status===2).length),f=c(()=>r.value.length),h=[{label:`在线设备`,value:i,color:`text-green-600`,bg:`bg-green-50`},{label:`泵送中`,value:u,color:`text-blue-600`,bg:`bg-blue-50`},{label:`支腿就绪`,value:d,color:`text-purple-600`,bg:`bg-purple-50`},{label:`总设备`,value:f,color:`text-gray-600`,bg:`bg-gray-50`}];return(e,n)=>(a(),o(`div`,y,[(a(),o(t,null,s(h,e=>l(`div`,{key:e.label,class:m([`rounded-lg border p-3 md:p-4`,e.bg])},[l(`div`,b,g(e.label),1),l(`div`,{class:m([`text-2xl font-bold mt-1`,e.color])},g(e.value),3)],2)),64))]))}}),S={class:`flex flex-col`},C={class:`divide-y overflow-y-auto max-h-[60vh]`},ee=[`onClick`],w={class:`flex-1 min-w-0`},T={class:`font-medium text-sm text-gray-700 truncate`},E={key:0,class:`px-3 py-8 text-center text-sm text-gray-400`},D=n({__name:`PumpDeviceList`,props:{pumps:{},selectedVin:{}},emits:[`select`],setup(n,{emit:h}){let _=n,v=h,y=p(),b=u(``),x=c(()=>{let e=b.value.trim().toLowerCase();return e?_.pumps.filter(t=>(t.plate_number||``).toLowerCase().includes(e)||t.vehicle_type.toLowerCase().includes(e)||t.vin.toLowerCase().includes(e)):_.pumps});function D(e){return e.tbox_id?y.isVehicleOnline(e)?`在线`:`离线`:`未绑定`}function O(e){return e.tbox_id&&y.isVehicleOnline(e)?`text-green-600`:`text-gray-400`}return(c,u)=>(a(),o(`div`,S,[f(l(`input`,{"onUpdate:modelValue":u[0]||=e=>b.value=e,type:`text`,placeholder:`搜索设备名称/类型...`,class:`w-full border rounded-lg px-3 py-2 text-sm mb-3 focus:outline-none focus:ring-2 focus:ring-blue-500`},null,512),[[r,b.value]]),l(`div`,C,[(a(!0),o(t,null,s(x.value,t=>(a(),o(`div`,{key:t.vin,class:m([`px-4 py-3 cursor-pointer hover:bg-blue-50 transition-colors flex items-center gap-3`,n.selectedVin===t.vin?`bg-blue-50 border-l-2 border-blue-500`:``]),onClick:e=>v(`select`,t.vin)},[l(`span`,{class:m([`w-2.5 h-2.5 rounded-full shrink-0`,e(y).isVehicleOnline(t)?`bg-green-500`:`bg-gray-400`])},null,2),l(`div`,w,[l(`div`,T,g(t.plate_number||t.vin.slice(-8)),1),l(`div`,{class:m([`text-xs mt-0.5`,O(t)])},g(t.vehicle_type)+` · `+g(D(t)),3)]),l(`span`,{class:m([`inline-flex items-center rounded-full font-medium px-1.5 py-0.5 text-xs shrink-0`,e(y).isVehicleOnline(t)?`bg-green-100 text-green-700`:`bg-gray-300 text-gray-500`])},[l(`span`,{class:m([`w-1.5 h-1.5 rounded-full mr-1.5`,e(y).isVehicleOnline(t)?`bg-green-500`:`bg-gray-400`])},null,2),d(` `+g(D(t)),1)],2)],10,ee))),128)),x.value.length===0?(a(),o(`div`,E,` 暂无泵送设备 `)):i(``,!0)])]))}}),O={class:`space-y-4`},k={class:`flex items-center gap-2`},A={class:`font-semibold text-lg`},j={class:`text-xs text-gray-400 font-mono`},M={class:`grid grid-cols-2 gap-3`},N={class:`bg-white border rounded-lg p-3`},P={class:`bg-white border rounded-lg p-3`},F={class:`text-sm font-semibold`},I={key:0},L={class:`bg-white border rounded-lg p-3`},R={class:`text-sm font-semibold`},z={key:0},B={key:0,class:`mt-1.5 h-1.5 bg-gray-100 rounded-full overflow-hidden`},V={class:`bg-white border rounded-lg p-3`},H={class:`text-sm font-semibold`},U={key:0},te={key:0,class:`mt-1.5 h-1.5 bg-gray-100 rounded-full overflow-hidden`},W={class:`bg-white border rounded-lg p-3`},G={class:`text-sm font-semibold`},K={key:0},q={class:`bg-white border rounded-lg p-3`},J={class:`text-sm font-semibold`},Y={key:0},X={key:1},Z={class:`grid grid-cols-3 gap-3`},Q={class:`bg-blue-50 border border-blue-200 rounded-lg p-3 text-center`},ne={class:`text-xl font-bold text-blue-600`},re={class:`bg-blue-50 border border-blue-200 rounded-lg p-3 text-center`},ie={class:`text-xl font-bold text-blue-600`},ae={class:`bg-blue-50 border border-blue-200 rounded-lg p-3 text-center`},oe={class:`text-xl font-bold text-blue-600`},$={key:0,class:`text-xs text-gray-400 text-center mt-1`},se=n({__name:`PumpDetailCard`,props:{vehicle:{}},setup(e){let t=e,n=h(),r=c(()=>{let e=new Date;e.setHours(0,0,0,0);let r=new Date().getDay(),i=new Date;i.setDate(i.getDate()-(r===0?6:r-1)),i.setHours(0,0,0,0);let a=t.vehicle.vin,o=n.orders.filter(e=>e.vin===a&&e.status===`completed`&&e.completed_at);return{todayVolume:o.filter(t=>(t.completed_at??0)>=e.getTime()).reduce((e,t)=>e+t.volume_m3,0),weekVolume:o.filter(e=>(e.completed_at??0)>=i.getTime()).reduce((e,t)=>e+t.volume_m3,0),totalVolume:o.reduce((e,t)=>e+t.volume_m3,0),completedTrips:o.length}}),s={0:`未展开`,1:`展开中`,2:`已展开`,3:`收拢中`},u={0:`text-gray-400`,1:`text-yellow-500`,2:`text-green-600`,3:`text-yellow-500`},f=c(()=>t.vehicle.outrigger_status??0);return(t,n)=>(a(),o(`div`,O,[l(`div`,k,[l(`h3`,A,` ⚡ `+g(e.vehicle.plate_number||e.vehicle.vin.slice(-8)),1),l(`span`,j,g(e.vehicle.vin.slice(-6)),1)]),l(`div`,M,[l(`div`,N,[n[0]||=l(`div`,{class:`text-xs text-gray-500 mb-1`},`● 支腿状态`,-1),l(`div`,{class:m([`text-sm font-semibold`,u[f.value]])},g(s[f.value]??`-`)+` (`+g(f.value)+`) `,3)]),l(`div`,P,[n[1]||=l(`div`,{class:`text-xs text-gray-500 mb-1`},`🌡 液压油温上限`,-1),l(`div`,F,[d(g(e.vehicle.hydraulic_oil_temp_max??`-`),1),e.vehicle.hydraulic_oil_temp_max?(a(),o(`span`,I,`°C`)):i(``,!0)])]),l(`div`,L,[n[2]||=l(`div`,{class:`text-xs text-gray-500 mb-1`},`⚡ 最大泵送压力`,-1),l(`div`,R,[d(g(e.vehicle.pump_max_pressure_mpa??`-`),1),e.vehicle.pump_max_pressure_mpa?(a(),o(`span`,z,` MPa`)):i(``,!0)]),e.vehicle.pump_max_pressure_mpa?(a(),o(`div`,B,[l(`div`,{class:`h-full bg-blue-500 rounded-full transition-all`,style:_({width:`${Math.min(100,e.vehicle.pump_max_pressure_mpa/25*100)}%`})},null,4)])):i(``,!0)]),l(`div`,V,[n[3]||=l(`div`,{class:`text-xs text-gray-500 mb-1`},`🚰 理论最大排量`,-1),l(`div`,H,[d(g(e.vehicle.pump_displacement_m3h??`-`),1),e.vehicle.pump_displacement_m3h?(a(),o(`span`,U,` m³/h`)):i(``,!0)]),e.vehicle.pump_displacement_m3h?(a(),o(`div`,te,[l(`div`,{class:`h-full bg-blue-500 rounded-full transition-all`,style:_({width:`${Math.min(100,e.vehicle.pump_displacement_m3h/200*100)}%`})},null,4)])):i(``,!0)]),l(`div`,W,[n[4]||=l(`div`,{class:`text-xs text-gray-500 mb-1`},`🦾 臂架`,-1),l(`div`,G,[d(g(e.vehicle.boom_sections??`-`),1),e.vehicle.boom_sections?(a(),o(`span`,K,` 节`)):i(``,!0)])]),l(`div`,q,[n[5]||=l(`div`,{class:`text-xs text-gray-500 mb-1`},`📏 臂架尺寸 (高×长)`,-1),l(`div`,J,[d(g(e.vehicle.boom_max_height_m??`-`),1),e.vehicle.boom_max_height_m?(a(),o(`span`,Y,`m`)):i(``,!0),d(` × `+g(e.vehicle.boom_max_length_m??`-`),1),e.vehicle.boom_max_length_m?(a(),o(`span`,X,`m`)):i(``,!0)])])]),l(`div`,Z,[l(`div`,Q,[n[7]||=l(`div`,{class:`text-xs text-blue-500 mb-1`},`今日泵送`,-1),l(`div`,ne,[d(g(r.value.todayVolume.toFixed(1))+` `,1),n[6]||=l(`span`,{class:`text-xs font-normal`},`m³`,-1)])]),l(`div`,re,[n[9]||=l(`div`,{class:`text-xs text-blue-500 mb-1`},`本周泵送`,-1),l(`div`,ie,[d(g(r.value.weekVolume.toFixed(1))+` `,1),n[8]||=l(`span`,{class:`text-xs font-normal`},`m³`,-1)])]),l(`div`,ae,[n[11]||=l(`div`,{class:`text-xs text-blue-500 mb-1`},`累计泵送`,-1),l(`div`,oe,[d(g((r.value.totalVolume||(e.vehicle.pump_total_volume_m3??0)).toLocaleString())+` `,1),n[10]||=l(`span`,{class:`text-xs font-normal`},`m³`,-1)])])]),r.value.completedTrips>0?(a(),o(`div`,$,` 共完成 `+g(r.value.completedTrips)+` 趟泵送任务 `,1)):i(``,!0)]))}}),ce={class:`space-y-4`},le={class:`flex items-center justify-between`},ue={class:`text-sm text-gray-400`},de={class:`flex flex-col lg:flex-row gap-4`},fe={class:`w-full lg:w-80 shrink-0 bg-white rounded-lg border p-3`},pe={class:`flex-1 min-w-0`},me={key:0,class:`bg-white rounded-lg border shadow-sm p-4`},he={key:1,class:`bg-white rounded-lg border shadow-sm p-12 text-center text-gray-400`},ge=n({__name:`PumpMonitor`,setup(e){let t=p(),n=u(null),r=c(()=>t.archiveVehicles.filter(e=>[`拖泵`,`车载泵`,`臂架泵车`].includes(e.vehicle_type))),i=c(()=>n.value?t.getByVin(n.value)??null:null);return(e,t)=>(a(),o(`div`,ce,[l(`div`,le,[t[1]||=l(`h1`,{class:`text-2xl font-bold`},`⚡ 泵送监控`,-1),l(`span`,ue,g(r.value.length)+` 台设备`,1)]),v(x),l(`div`,de,[l(`div`,fe,[v(D,{pumps:r.value,"selected-vin":n.value,onSelect:t[0]||=e=>n.value=e},null,8,[`pumps`,`selected-vin`])]),l(`div`,pe,[i.value?(a(),o(`div`,me,[v(se,{vehicle:i.value},null,8,[`vehicle`])])):(a(),o(`div`,he,[...t[2]||=[l(`div`,{class:`text-4xl mb-3`},`⚡`,-1),l(`p`,{class:`text-sm`},`选择左侧设备查看泵送详情`,-1)]]))])])]))}});export{ge as default};
@@ -0,0 +1,6 @@
1
+ import{$ as e,A as t,B as n,D as r,E as i,F as a,G as o,I as s,J as c,K as l,M as u,N as d,P as f,Q as p,R as m,T as h,U as g,W as _,X as v,d as y,et as b,f as x,l as S,m as C,n as w,nt as T,s as E,tt as D,z as O}from"./index-CTrnN2TM.js";import{i as k,r as A}from"./export-LCWayDfi.js";import{t as j}from"./StatsBar-dmdFex0_.js";var M={class:`flex items-center justify-between mb-2`},N={class:`flex items-center gap-1.5`},P=[`title`],F={class:`font-semibold text-sm text-gray-800`},I={class:`space-y-1 text-xs text-gray-500`},L={class:`flex justify-between`},R={class:`flex justify-between`},z={key:0,class:`mt-2 h-1 bg-gray-100 rounded-full overflow-hidden`},B=n({__name:`VehicleCard`,props:{vehicle:{}},emits:[`select`],setup(t,{emit:n}){let r=t,i=n,c=S(),l=y(),f=u(()=>c.getActiveByVin(r.vehicle.vin)),p=u(()=>l.isVehicleOnline(r.vehicle)),h=u(()=>r.vehicle.tbox_id?p.value?`在线`:`离线`:`未绑定`),g=u(()=>r.vehicle.tbox_id&&p.value?`bg-green-100 text-green-700`:`bg-gray-300 text-gray-500`),_=u(()=>{if(!f.value)return null;let e=w.getRemainingTime(f.value);return Math.round(e/6e4)}),v=u(()=>r.vehicle.last_gps?f.value?.status===`discharging`?`🔄 反转`:f.value?.status===`loading`||f.value?.status===`transporting`?`🔄 正转`:`⏸ 停止`:null),x=u(()=>f.value?.destination_name??`-`);return(n,r)=>(o(),s(`div`,{class:`flex-shrink-0 w-56 bg-white rounded-lg border shadow-sm p-3 cursor-pointer hover:shadow-md hover:border-blue-300 transition-all`,onClick:r[0]||=e=>i(`select`,t.vehicle.vin)},[d(`div`,M,[d(`div`,N,[d(`span`,{class:b([`w-2 h-2 rounded-full flex-shrink-0`,p.value?`bg-green-500`:`bg-gray-300`]),title:p.value?`TBox在线`:t.vehicle.tbox_id?`TBox离线`:`未绑定TBox`},null,10,P),d(`span`,F,` 🚛 `+T(t.vehicle.plate_number||t.vehicle.vin.slice(-6)),1)]),d(`span`,{class:b([`inline-flex items-center rounded-full font-medium px-1.5 py-0.5 text-xs`,g.value])},[d(`span`,{class:b([`w-1.5 h-1.5 rounded-full mr-1.5`,p.value?`bg-green-500`:`bg-gray-400`])},null,2),m(` `+T(h.value),1)],2)]),d(`div`,I,[d(`div`,L,[d(`span`,null,T(v.value),1),_.value===null?a(``,!0):(o(),s(`span`,{key:0,class:b(_.value<30?`text-red-500 font-bold`:`text-gray-600`)},` ⏱ `+T(_.value)+`min `,3))]),d(`div`,R,[d(`span`,null,`📍 `+T(x.value),1)])]),f.value?(o(),s(`div`,z,[d(`div`,{class:b([`h-full rounded-full transition-all`,{"bg-green-500":(e(w).getTimeoutRatio(f.value)??0)<.5,"bg-yellow-500":(e(w).getTimeoutRatio(f.value)??0)>=.5&&(e(w).getTimeoutRatio(f.value)??0)<.7,"bg-red-500":(e(w).getTimeoutRatio(f.value)??0)>=.7}]),style:D({width:Math.min((e(w).getTimeoutRatio(f.value)??0)*100,100)+`%`})},null,6)])):a(``,!0)]))}}),V=50,ee=n({__name:`VehicleMarker`,props:{mapInstance:{}},emits:[`select`],setup(e,{expose:t,emit:n}){let r=e,i=n,a=y(),l={transporting:`#22c55e`,loading:`#eab308`,arrived:`#3b82f6`,discharging:`#a855f7`,returning:`#6366f1`,idle:`#9ca3af`,offline:`#6b7280`},d=new Map;function f(e){return`<div style="
2
+ width:24px;height:24px;border-radius:50%;background:${l[e]??`#9ca3af`};
3
+ border:2px solid #fff;box-shadow:0 1px 4px rgba(0,0,0,0.3);
4
+ display:flex;align-items:center;justify-content:center;
5
+ font-size:10px;color:#fff;font-weight:bold;
6
+ ">🚛</div>`}function p(e,t,n,a){let o=d.get(e);o||(o=new AMap.Marker({position:t,offset:new AMap.Pixel(-12,-12),zIndex:100}),o.on(`click`,()=>i(`select`,e)),d.set(e,o),r.mapInstance.add(o)),o.setPosition(t),o.setContent(f(n)),o.setLabel({content:`<span style="background:rgba(0,0,0,0.7);color:#fff;padding:1px 4px;border-radius:2px;font-size:10px;white-space:nowrap;">${a}</span>`,offset:new AMap.Pixel(0,-30)})}function m(e){let t=d.get(e);t&&(r.mapInstance?.remove(t),d.delete(e))}function h(){for(let[e]of d)m(e)}let g=null;function v(){if(!r.mapInstance||g)return;let e=window.AMap?.MarkerClusterer;if(!e){console.warn(`[VehicleMarker] MarkerClusterer plugin not loaded, using individual markers`);return}g=new e(r.mapInstance,[],{gridSize:60,maxZoom:14,averageCenter:!0,zoomOnClick:!0,styles:[{url:``,size:new AMap.Size(36,36),textSize:14,textColor:`#fff`}]}),g.setStyles?.([{url:``,size:new AMap.Size(36,36),textSize:14,textColor:`#fff`},{url:``,size:new AMap.Size(44,44),textSize:16,textColor:`#fff`},{url:``,size:new AMap.Size(52,52),textSize:18,textColor:`#fff`}])}function b(){g&&=(g.setMap?.(null),null)}let x=u(()=>a.vehicles.filter(e=>e.last_gps?.lng&&e.last_gps?.lat)),S=u(()=>x.value.length>V);return c(()=>a.vehicles.map(e=>({vin:e.vin,lng:e.last_gps?.lng??null,lat:e.last_gps?.lat??null,status:e.status,plate:e.plate_number})),e=>{if(r.mapInstance)if(S.value){if(h(),v(),!g){for(let t of e)!t.lng||!t.lat||p(t.vin,[t.lng,t.lat],t.status,t.plate||t.vin.slice(-6));return}let t=g.getMarkers?.()??[];for(let e of t)e.remove?.();let n=[];for(let t of e){if(!t.lng||!t.lat)continue;let e=new AMap.Marker({position:[t.lng,t.lat],content:f(t.status),offset:new AMap.Pixel(-12,-12),extData:{vin:t.vin}});e.on(`click`,()=>i(`select`,t.vin)),n.push(e)}g.setMarkers?.(n)}else{b();for(let t of e){if(!t.lng||!t.lat){m(t.vin);continue}p(t.vin,[t.lng,t.lat],t.status,t.plate||t.vin.slice(-6))}let t=new Set(e.filter(e=>e.lng).map(e=>e.vin));for(let e of d.keys())t.has(e)||m(e)}},{deep:!0,immediate:!0}),_(()=>{h(),b()}),t({refresh(){h(),b()}}),(e,t)=>(o(),s(`div`))}}),H=n({__name:`FenceOverlay`,props:{mapInstance:{}},setup(e){let t=e,n=E(),r=new Map;return c(()=>n.activeFences,e=>{if(!t.mapInstance)return;let n=new Set(e.map(e=>e.fence_id));for(let[e,i]of r)n.has(e)||(t.mapInstance.remove(i),r.delete(e));for(let n of e){if(n.shape!==`circle`||!n.geometry.center)continue;let e=r.get(n.fence_id);e?e.setOptions({center:[n.geometry.center.lng,n.geometry.center.lat],radius:n.geometry.radius??200,fillColor:n.color,strokeColor:n.color}):(e=new AMap.Circle({center:[n.geometry.center.lng,n.geometry.center.lat],radius:n.geometry.radius??200,fillOpacity:.15,fillColor:n.color,strokeColor:n.color,strokeWeight:2,zIndex:10}),t.mapInstance.add(e),r.set(n.fence_id,e))}},{deep:!0,immediate:!0}),_(()=>{for(let[,e]of r)t.mapInstance?.remove(e);r.clear()}),(e,t)=>(o(),s(`div`))}}),U={key:0,class:`bg-white rounded-lg border shadow-sm p-4 space-y-3`},W={class:`flex items-center justify-between`},G={class:`grid grid-cols-3 gap-3`},K=[`value`],q={class:`flex gap-2`},J=[`disabled`],Y={key:0,class:`flex gap-4 text-xs text-gray-500`},X={key:1,class:`text-xs text-gray-400`},Z=n({__name:`HistoryTrack`,props:{mapInstance:{},visible:{type:Boolean}},emits:[`close`],setup(n,{emit:r}){let c=n,f=r,g=y(),b=p(``),x=p(O()),S=p(Date.now()),w=p(!1),E=p([]),D=p(null);function O(){let e=new Date;return e.setHours(0,0,0,0),e.getTime()}let j=u(()=>g.vehicles.filter(e=>e.last_gps!=null&&!e.vin.startsWith(`TEMP_`))),M=u(()=>{if(E.value.length===0)return null;let e=E.value.map(e=>e.speed).filter(e=>e>0);return{points:E.value.length,maxSpeed:e.length>0?Math.max(...e).toFixed(1):`0`,avgSpeed:e.length>0?(e.reduce((e,t)=>e+t,0)/e.length).toFixed(1):`0`,duration:E.value.length>=2?Math.round((E.value[E.value.length-1].timestamp-E.value[0].timestamp)/6e4):0}});async function N(){if(!(!b.value||!c.mapInstance)){w.value=!0;try{let e=await C.getByVin(b.value,x.value);if(E.value=e.filter(e=>e.timestamp<=S.value),D.value&&=(c.mapInstance.remove(D.value),null),e.length>=2){let t=e.filter(e=>e.lng!==0&&e.lat!==0).map(e=>[e.lng,e.lat]);t.length>=2&&(D.value=new AMap.Polyline({path:t,strokeColor:`#1a73e8`,strokeWeight:4,strokeOpacity:.8,zIndex:50}),c.mapInstance.add(D.value),c.mapInstance.setFitView([D.value]))}}finally{w.value=!1}}}function P(){D.value&&c.mapInstance&&(c.mapInstance.remove(D.value),D.value=null),E.value=[]}return _(()=>{P()}),(r,c)=>n.visible?(o(),s(`div`,U,[d(`div`,W,[c[6]||=d(`h3`,{class:`font-semibold text-sm text-gray-700`},`📜 历史轨迹回放`,-1),d(`button`,{class:`text-gray-400 hover:text-gray-600`,onClick:c[0]||=e=>f(`close`)},`✕`)]),d(`div`,G,[d(`div`,null,[c[8]||=d(`label`,{class:`text-xs text-gray-500 block mb-1`},`车辆`,-1),v(d(`select`,{"onUpdate:modelValue":c[1]||=e=>b.value=e,class:`w-full border rounded-lg px-2 py-1.5 text-sm`},[c[7]||=d(`option`,{value:``},`选择车辆`,-1),(o(!0),s(t,null,l(j.value,e=>(o(),s(`option`,{key:e.vin,value:e.vin},T(e.plate_number||e.vin.slice(-6)),9,K))),128))],512),[[h,b.value]])]),d(`div`,null,[c[9]||=d(`label`,{class:`text-xs text-gray-500 block mb-1`},`开始日期`,-1),v(d(`input`,{"onUpdate:modelValue":c[2]||=e=>x.value=e,type:`date`,class:`w-full border rounded-lg px-2 py-1.5 text-sm`},null,512),[[i,x.value,void 0,{number:!0}]])]),d(`div`,null,[c[10]||=d(`label`,{class:`text-xs text-gray-500 block mb-1`},`结束日期`,-1),v(d(`input`,{"onUpdate:modelValue":c[3]||=e=>S.value=e,type:`date`,class:`w-full border rounded-lg px-2 py-1.5 text-sm`},null,512),[[i,S.value,void 0,{number:!0}]])])]),d(`div`,q,[d(`button`,{class:`px-4 py-1.5 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50`,disabled:!b.value||w.value,onClick:N},T(w.value?`加载中...`:`🔍 查询轨迹`),9,J),d(`button`,{class:`px-4 py-1.5 text-sm bg-gray-200 text-gray-600 rounded-lg hover:bg-gray-300`,onClick:P},` 清除 `),E.value.length>0?(o(),s(`button`,{key:0,class:`px-3 py-1.5 text-xs text-blue-600 border border-blue-200 rounded-lg hover:bg-blue-50`,onClick:c[4]||=t=>e(k)(b.value)},` JSON `)):a(``,!0),E.value.length>0?(o(),s(`button`,{key:1,class:`px-3 py-1.5 text-xs text-green-600 border border-green-200 rounded-lg hover:bg-green-50`,onClick:c[5]||=t=>e(A)(b.value)},` CSV `)):a(``,!0)]),M.value?(o(),s(`div`,Y,[d(`span`,null,[c[11]||=m(`轨迹点: `,-1),d(`strong`,null,T(M.value.points),1)]),d(`span`,null,[c[12]||=m(`最高速: `,-1),d(`strong`,null,T(M.value.maxSpeed)+` km/h`,1)]),d(`span`,null,[c[13]||=m(`平均速: `,-1),d(`strong`,null,T(M.value.avgSpeed)+` km/h`,1)]),d(`span`,null,[c[14]||=m(`时长: `,-1),d(`strong`,null,T(M.value.duration)+` min`,1)])])):E.value.length===0&&b.value?(o(),s(`div`,X,` 该时间段无轨迹数据 `)):a(``,!0)])):a(``,!0)}}),Q={class:`space-y-4`},te={class:`flex items-center gap-2 flex-wrap`},ne=[`onClick`],re={class:`ml-1 opacity-70`},ie={class:`grid grid-cols-1 lg:grid-cols-3 gap-4`},ae={class:`lg:col-span-2 bg-white rounded-lg border shadow-sm overflow-hidden`},oe={class:`h-96 flex items-center justify-center bg-gray-50 text-gray-400 text-sm`},se={key:0,class:`lg:col-span-3`},ce={class:`bg-white rounded-lg border shadow-sm p-4`},le={key:0,class:`space-y-3`},ue={class:`flex items-center justify-between`},de={class:`flex items-center gap-2`},fe=[`title`],pe={class:`text-lg font-bold`},$={class:`text-xs text-gray-500 space-y-1`},me={key:0},he={key:1,class:`text-sm text-gray-400 text-center py-8`},ge={class:`bg-white rounded-lg border shadow-sm p-4`},_e={class:`font-semibold text-sm text-gray-700 mb-3`},ve={key:0,class:`flex gap-3 overflow-x-auto pb-2`},ye={key:1,class:`text-center text-gray-400 py-6 text-sm`},be=n({__name:`RealtimeMonitor`,setup(n){let i=y(),c=E(),h=x(),S=p(`all`),C=p(null),w=p(null),D=p(!1),k=p(null),A=p(!1),M=null,N=null,P=u(()=>i.archiveVehicles),F=u(()=>{let e=P.value;return S.value===`all`?e:S.value===`offline`?e.filter(e=>!i.isVehicleOnline(e)):e.filter(e=>e.status===S.value)});function I(e){return e===`offline`?i.offlineCount:i.getByStatus(e).length}let L=u(()=>C.value?i.getByVin(C.value)??null:null),R=[{key:`all`,label:`全部`},{key:`transporting`,label:`运输中`},{key:`loading`,label:`装料中`},{key:`arrived`,label:`已到达`},{key:`discharging`,label:`卸料中`},{key:`idle`,label:`待命`},{key:`offline`,label:`离线`}];g(async()=>{await Promise.all([i.load(),c.load(),h.ready?Promise.resolve():h.load()]),await z(),V()}),_(()=>{M&&=(clearInterval(M),null),N&&=(clearTimeout(N),null),k.value&&=(k.value.destroy(),null)});function z(){return new Promise(e=>{if(typeof window<`u`&&window.AMap){e();return}M=setInterval(()=>{window.AMap&&(clearInterval(M),M=null,e())},100),N=setTimeout(()=>{M&&=(clearInterval(M),null),N=null,e()},1e4)})}function V(){if(!w.value)return;if(!window.AMap){console.warn(`[RealtimeMonitor] AMap SDK not loaded, skipping map init`);return}let e=h.ui.mapCenterLng,t=h.ui.mapCenterLat;k.value=new AMap.Map(w.value,{zoom:h.ui.mapZoomLevel??13,center:[e,t],resizeEnable:!0}),D.value=!0;for(let e of c.activeFences)if(e.shape===`circle`&&e.geometry.center){let t=new AMap.Circle({center:[e.geometry.center.lng,e.geometry.center.lat],radius:e.geometry.radius??200,fillOpacity:.15,fillColor:e.color,strokeColor:e.color,strokeWeight:2});k.value.add(t)}}function U(e){C.value=e}return(n,c)=>(o(),s(`div`,Q,[O(j),d(`div`,te,[(o(),s(t,null,l(R,e=>d(`button`,{key:e.key,class:b([`px-3 py-1.5 text-xs rounded-full border transition-colors`,S.value===e.key?`bg-blue-600 text-white border-blue-600`:`bg-white text-gray-600 border-gray-200 hover:border-blue-300`]),onClick:t=>S.value=e.key},[m(T(e.label)+` `,1),d(`span`,re,` (`+T(e.key===`all`?P.value.length:I(e.key))+`) `,1)],10,ne)),64)),d(`button`,{class:b([`ml-auto px-3 py-1.5 text-xs rounded-full border transition-colors`,A.value?`bg-blue-600 text-white border-blue-600`:`bg-white text-gray-500 border-gray-200 hover:border-blue-300`]),onClick:c[0]||=e=>A.value=!A.value},`📜 轨迹回放`,2)]),d(`div`,ie,[d(`div`,ae,[v(d(`div`,oe,` ⏳ 加载地图中... `,512),[[r,!D.value]]),d(`div`,{ref_key:`mapContainer`,ref:w,class:`h-96 w-full`},null,512),k.value?(o(),f(H,{key:0,mapInstance:k.value},null,8,[`mapInstance`])):a(``,!0),k.value?(o(),f(ee,{key:1,mapInstance:k.value,onSelect:U},null,8,[`mapInstance`])):a(``,!0)]),A.value?(o(),s(`div`,se,[O(Z,{mapInstance:k.value,visible:A.value,onClose:c[1]||=e=>A.value=!1},null,8,[`mapInstance`,`visible`])])):a(``,!0),d(`div`,ce,[c[2]||=d(`h3`,{class:`font-semibold text-sm text-gray-700 mb-3`},`车辆详情`,-1),L.value?(o(),s(`div`,le,[d(`div`,ue,[d(`div`,de,[d(`span`,{class:b([`w-2.5 h-2.5 rounded-full`,e(i).isVehicleOnline(L.value)?`bg-green-500`:`bg-gray-300`]),title:e(i).isVehicleOnline(L.value)?`TBox在线`:L.value.tbox_id?`TBox离线`:`未绑定TBox`},null,10,fe),d(`span`,pe,T(L.value.plate_number||L.value.vin.slice(-6)),1)]),d(`span`,{class:b([`inline-flex items-center rounded-full font-medium px-2 py-0.5 text-xs`,e(i).isVehicleOnline(L.value)?`bg-green-100 text-green-700`:`bg-gray-300 text-gray-500`])},[d(`span`,{class:b([`w-1.5 h-1.5 rounded-full mr-1.5`,e(i).isVehicleOnline(L.value)?`bg-green-500`:`bg-gray-400`])},null,2),m(` `+T(L.value.tbox_id?e(i).isVehicleOnline(L.value)?`在线`:`离线`:`未绑定`),1)],2)]),d(`div`,$,[d(`div`,null,`VIN: `+T(L.value.vin),1),d(`div`,null,`TBox: `+T(L.value.tbox_id||`未绑定`),1),L.value.last_gps?(o(),s(`div`,me,` 位置: `+T(L.value.last_gps.lng.toFixed(4))+`, `+T(L.value.last_gps.lat.toFixed(4)),1)):a(``,!0)])])):(o(),s(`div`,he,`点击车辆卡片查看详情`))])]),d(`div`,ge,[d(`h3`,_e,`车辆列表 (`+T(F.value.length)+`)`,1),F.value.length>0?(o(),s(`div`,ve,[(o(!0),s(t,null,l(F.value,e=>(o(),f(B,{key:e.vin,vehicle:e,onSelect:U},null,8,[`vehicle`]))),128))])):(o(),s(`div`,ye,`暂无车辆数据`))])]))}});export{be as default};
@@ -0,0 +1 @@
1
+ import{$ as e,A as t,B as n,F as r,G as i,I as a,K as o,M as s,N as c,P as l,Q as u,R as d,U as f,c as p,d as m,et as h,l as g,m as _,nt as v,z as y}from"./index-CTrnN2TM.js";import{a as b,o as x,s as S}from"./export-LCWayDfi.js";var C={class:`flex items-center gap-3 flex-wrap`},w={class:`flex gap-1`},T=[`onClick`],E={class:`text-xs text-gray-400`},D=n({__name:`DateRangePicker`,props:{start:{},end:{}},emits:[`update:start`,`update:end`,`change`],setup(e,{emit:n}){let r=e,l=n,u=[{label:`今日`,days:0},{label:`昨日`,days:1},{label:`近7天`,days:7},{label:`近30天`,days:30}];function d(e){let t=new Date;t.setHours(23,59,59,999),l(`update:end`,t.getTime());let n=new Date(t);if(e===0)n.setHours(0,0,0,0);else if(e===1){n.setDate(n.getDate()-1),n.setHours(0,0,0,0);let e=new Date(n);e.setHours(23,59,59,999),l(`update:end`,e.getTime())}else n.setDate(n.getDate()-e),n.setHours(0,0,0,0);l(`update:start`,n.getTime()),l(`change`)}function f(e){return new Date(e).toLocaleDateString(`zh-CN`)}let p=s(()=>{let e=Math.round((r.end-r.start)/864e5);return e===0?`今日`:e===1?`昨日`:null});return(n,r)=>(i(),a(`div`,C,[r[0]||=c(`span`,{class:`text-xs text-gray-500`},`时间范围:`,-1),c(`div`,w,[(i(),a(t,null,o(u,e=>c(`button`,{key:e.label,class:h([`px-3 py-1 text-xs rounded-full border transition-colors`,p.value===e.label?`bg-blue-600 text-white border-blue-600`:`bg-white text-gray-500 border-gray-200 hover:border-blue-300`]),onClick:t=>d(e.days)},v(e.label),11,T)),64))]),c(`span`,E,v(f(e.start))+` ~ `+v(f(e.end)),1)]))}}),ee={class:`space-y-4`},te={class:`bg-white rounded-lg border shadow-sm p-4`},ne={class:`grid grid-cols-6 gap-4 mb-4`},re={class:`text-center p-3 bg-blue-50 rounded-lg`},ie={class:`text-2xl font-bold text-blue-600`},ae={class:`text-center p-3 bg-green-50 rounded-lg`},O={class:`text-2xl font-bold text-green-600`},k={class:`text-center p-3 bg-purple-50 rounded-lg`},A={class:`text-2xl font-bold text-purple-600`},j={class:`text-center p-3 bg-amber-50 rounded-lg`},M={class:`text-2xl font-bold text-amber-600`},N={class:`text-center p-3 bg-indigo-50 rounded-lg`},P={class:`text-2xl font-bold text-indigo-600`},F={class:`text-center p-3 bg-teal-50 rounded-lg`},I={class:`text-2xl font-bold text-teal-600`},L={class:`overflow-x-auto`},R={class:`w-full text-xs`},z={class:`divide-y`},B={class:`py-1 font-mono`},V={class:`py-1`},H={class:`py-1`},U={class:`py-1`},W={class:`py-1 text-right`},G={class:`py-1 text-right`},K={class:`py-1 text-right`},q={class:`bg-white rounded-lg border shadow-sm p-4`},J={class:`overflow-x-auto`},oe={class:`w-full text-xs`},se={class:`divide-y`},ce={class:`py-1.5 font-medium`},le={class:`py-1.5 text-right`},ue={class:`py-1.5 text-right`},de={class:`py-1.5 text-right font-bold`},fe={key:0,class:`text-center py-6 text-gray-400 text-sm`},pe=n({__name:`EfficiencyReport`,props:{start:{},end:{}},setup(n){let l=n,u=g(),d=m(),f=p(),_=s(()=>u.orders.filter(e=>e.completed_at&&e.completed_at>=l.start&&e.completed_at<=l.end)),y=s(()=>{let e=_.value,t=e.reduce((e,t)=>e+t.volume_m3,0),n=e.length>0?e.reduce((e,t)=>e+((t.completed_at??0)-(t.departed_at??t.created_at)),0)/e.length/6e4:0,r=e.filter(e=>e.arrived_at&&e.discharging_at),i=r.length>0?r.reduce((e,t)=>e+((t.discharging_at??0)-(t.arrived_at??0)),0)/r.length/6e4:0,a=e.filter(e=>e.completed_at&&e.completed_at<=e.required_arrival_by).length,o=e.length>0?(a/e.length*100).toFixed(1):`0`,s=new Set;e.forEach(e=>{e.station_id&&s.add(e.station_id)});let c=s.size;return{totalTrips:e.length,totalVolume:t.toFixed(1),avgDuration:Math.round(n),avgWaitMin:Math.round(i),onTimeCount:a,onTimeRate:o,stationCount:c}}),b=s(()=>{let e=new Map;for(let t of _.value){let n=t.vin??``;if(!n)continue;let r=e.get(n)||{trips:0,totalVolume:0,onTimeCount:0};r.trips++,r.totalVolume+=t.volume_m3,t.completed_at&&t.completed_at<=t.required_arrival_by&&r.onTimeCount++,e.set(n,r)}let t=new Map;for(let e of f.alarms)e.vin&&e.timestamp>=l.start&&e.timestamp<=l.end&&t.set(e.vin,(t.get(e.vin)||0)+1);return Array.from(e.entries()).map(([e,n])=>({vin:e,plate:d.getByVin(e)?.plate_number||e.slice(-6),...n,onTimeRate:n.trips>0?(n.onTimeCount/n.trips*100).toFixed(0):`0`,alarmCount:t.get(e)||0})).sort((e,t)=>t.trips-e.trips)});return(n,s)=>(i(),a(`div`,ee,[c(`div`,te,[s[7]||=c(`h3`,{class:`font-semibold text-sm text-gray-700 mb-4`},`🚛 运载效率`,-1),c(`div`,ne,[c(`div`,re,[c(`div`,ie,v(y.value.totalTrips),1),s[0]||=c(`div`,{class:`text-xs text-gray-500 mt-1`},`总趟数`,-1)]),c(`div`,ae,[c(`div`,O,v(y.value.totalVolume),1),s[1]||=c(`div`,{class:`text-xs text-gray-500 mt-1`},`总方量 (m³)`,-1)]),c(`div`,k,[c(`div`,A,v(y.value.avgDuration),1),s[2]||=c(`div`,{class:`text-xs text-gray-500 mt-1`},`平均耗时 (min)`,-1)]),c(`div`,j,[c(`div`,M,v(y.value.avgWaitMin),1),s[3]||=c(`div`,{class:`text-xs text-gray-500 mt-1`},`平均等待 (min)`,-1)]),c(`div`,N,[c(`div`,P,v(y.value.onTimeRate)+`%`,1),s[4]||=c(`div`,{class:`text-xs text-gray-500 mt-1`},`准时率`,-1)]),c(`div`,F,[c(`div`,I,v(y.value.stationCount),1),s[5]||=c(`div`,{class:`text-xs text-gray-500 mt-1`},`搅拌站数`,-1)])]),c(`div`,L,[c(`table`,R,[s[6]||=c(`thead`,{class:`text-gray-400 border-b`},[c(`tr`,null,[c(`th`,{class:`text-left py-1`},`订单ID`),c(`th`,{class:`text-left py-1`},`车辆`),c(`th`,{class:`text-left py-1`},`目的地`),c(`th`,{class:`text-left py-1`},`标号`),c(`th`,{class:`text-right py-1`},`方量`),c(`th`,{class:`text-right py-1`},`耗时`),c(`th`,{class:`text-right py-1`},`准时`)])],-1),c(`tbody`,z,[(i(!0),a(t,null,o(_.value.slice(0,20),t=>(i(),a(`tr`,{key:t.order_id,class:`text-gray-600`},[c(`td`,B,v(t.order_id.slice(-8)),1),c(`td`,V,v(e(d).getByVin(t.vin??``)?.plate_number??t.vin?.slice(-6)??`-`),1),c(`td`,H,v(t.destination_name),1),c(`td`,U,v(t.concrete_grade),1),c(`td`,W,v(t.volume_m3),1),c(`td`,G,v(t.completed_at&&t.departed_at?Math.round((t.completed_at-t.departed_at)/6e4)+`min`:`-`),1),c(`td`,K,v(t.completed_at&&t.completed_at<=t.required_arrival_by?`✅`:`⚠️`),1)]))),128))])])])]),c(`div`,q,[s[9]||=c(`h3`,{class:`font-semibold text-sm text-gray-700 mb-4`},`👨‍✈️ 驾驶员绩效`,-1),c(`div`,J,[c(`table`,oe,[s[8]||=c(`thead`,{class:`text-gray-400 border-b`},[c(`tr`,null,[c(`th`,{class:`text-left py-1.5`},`车辆`),c(`th`,{class:`text-right py-1.5`},`趟数`),c(`th`,{class:`text-right py-1.5`},`方量 (m³)`),c(`th`,{class:`text-right py-1.5`},`准时率`),c(`th`,{class:`text-right py-1.5`},`总告警`),c(`th`,{class:`text-right py-1.5`},`评分`)])],-1),c(`tbody`,se,[(i(!0),a(t,null,o(b.value.slice(0,20),e=>(i(),a(`tr`,{key:e.vin,class:`text-gray-600 hover:bg-gray-50`},[c(`td`,ce,v(e.plate),1),c(`td`,le,v(e.trips),1),c(`td`,ue,v(e.totalVolume.toFixed(1)),1),c(`td`,{class:h([`py-1.5 text-right`,Number(e.onTimeRate)>=80?`text-green-600`:Number(e.onTimeRate)>=60?`text-yellow-600`:`text-red-500`])},v(e.onTimeRate)+`% `,3),c(`td`,{class:h([`py-1.5 text-right`,e.alarmCount>2?`text-red-500`:``])},v(e.alarmCount||`-`),3),c(`td`,de,v(e.trips>0?Math.max(0,Math.min(100,Math.round(Number(e.onTimeRate)*1.2-e.alarmCount*5))):`-`),1)]))),128))])])]),b.value.length===0?(i(),a(`div`,fe,` 暂无绩效数据 `)):r(``,!0)])]))}}),me={class:`bg-white rounded-lg border shadow-sm p-4`},he={class:`grid grid-cols-3 gap-4`},ge={class:`text-center p-3 bg-blue-50 rounded-lg`},_e={class:`text-2xl font-bold text-blue-600`},ve={class:`text-center p-3 bg-green-50 rounded-lg`},ye={class:`text-2xl font-bold text-green-600`},be={class:`text-center p-3 bg-purple-50 rounded-lg`},xe={class:`text-2xl font-bold text-purple-600`},Se={class:`mt-3 text-sm text-gray-500 text-center`},Ce={class:`ml-2 text-xs`},we=n({__name:`DrumUsageReport`,props:{start:{},end:{}},setup(e){let t=e,n=g(),r=s(()=>n.orders.filter(e=>e.completed_at&&e.completed_at>=t.start&&e.completed_at<=t.end)),o=s(()=>{let e=0,t=0,n=0,i=0;for(let a of r.value)a.loaded_at&&a.departed_at&&(e+=(a.departed_at-a.loaded_at)/6e4),a.departed_at&&a.arrived_at&&(t+=((a.arrived_at||a.completed_at||a.departed_at)-a.departed_at)/6e4),a.discharging_at&&a.completed_at&&(n+=(a.completed_at-a.discharging_at)/6e4),a.created_at&&a.completed_at&&(i+=(a.completed_at-a.created_at)/6e4);let a=e+t+n;return{totalTrips:r.value.length,loadingPct:i>0?(e/i*100).toFixed(1):`0`,transportingPct:i>0?(t/i*100).toFixed(1):`0`,dischargingPct:i>0?(n/i*100).toFixed(1):`0`,activePct:i>0?(a/i*100).toFixed(1):`0`,activeMin:Math.round(a),totalMin:Math.round(i)}});return(e,t)=>(i(),a(`div`,me,[t[3]||=c(`h3`,{class:`font-semibold text-sm text-gray-700 mb-4`},`🔄 搅拌筒利用率`,-1),c(`div`,he,[c(`div`,ge,[c(`div`,_e,v(o.value.loadingPct)+`%`,1),t[0]||=c(`div`,{class:`text-xs text-gray-500 mt-1`},`装料占比`,-1)]),c(`div`,ve,[c(`div`,ye,v(o.value.transportingPct)+`%`,1),t[1]||=c(`div`,{class:`text-xs text-gray-500 mt-1`},`运输占比`,-1)]),c(`div`,be,[c(`div`,xe,v(o.value.dischargingPct)+`%`,1),t[2]||=c(`div`,{class:`text-xs text-gray-500 mt-1`},`卸料占比`,-1)])]),c(`div`,Se,[d(` 搅拌筒活动时长 `+v(o.value.activeMin)+`min / 总时长 `+v(o.value.totalMin)+`min `,1),c(`span`,Ce,`(活动率 `+v(o.value.activePct)+`%)`,1)])]))}}),Te={class:`bg-white rounded-lg border shadow-sm p-4`},Ee={class:`grid grid-cols-4 gap-4`},De={class:`text-center p-3 bg-red-50 rounded-lg`},Oe={class:`text-2xl font-bold text-red-600`},ke={class:`text-center p-3 bg-orange-50 rounded-lg`},Ae={class:`text-2xl font-bold text-orange-600`},je={class:`text-center p-3 bg-yellow-50 rounded-lg`},Me={class:`text-2xl font-bold text-yellow-600`},Ne={class:`text-center p-3 bg-gray-50 rounded-lg`},Pe={class:`text-2xl font-bold text-gray-600`},Fe={key:0,class:`mt-4`},Ie={class:`space-y-1`},Le={class:`font-mono`},Re={class:`text-red-500`},ze={key:1,class:`text-sm text-gray-400 text-center py-6`},Be=n({__name:`SafetyReport`,props:{start:{},end:{}},setup(e){let n=e,r=g(),l=p(),u=s(()=>r.orders.filter(e=>e.completed_at&&e.required_arrival_by>0&&(e.arrived_at||e.completed_at)>e.required_arrival_by&&e.created_at>=n.start&&e.created_at<=n.end)),d=s(()=>l.alarms.filter(e=>(e.alarm_type===`concrete_timeout`||e.alarm_type===`fence_timeout`)&&e.occurred_at>=n.start&&e.occurred_at<=n.end)),f=s(()=>({timeoutCount:u.value.length,lossVolume:u.value.reduce((e,t)=>e+t.volume_m3,0).toFixed(1),alarmCount:d.value.length,avgDelay:u.value.length>0?Math.round(u.value.reduce((e,t)=>e+((t.arrived_at||t.completed_at)-t.required_arrival_by)/6e4,0)/u.value.length):0}));return(e,n)=>(i(),a(`div`,Te,[n[5]||=c(`h3`,{class:`font-semibold text-sm text-gray-700 mb-4`},`🛡️ 安全超时统计`,-1),c(`div`,Ee,[c(`div`,De,[c(`div`,Oe,v(f.value.timeoutCount),1),n[0]||=c(`div`,{class:`text-xs text-gray-500 mt-1`},`超时次数`,-1)]),c(`div`,ke,[c(`div`,Ae,v(f.value.lossVolume),1),n[1]||=c(`div`,{class:`text-xs text-gray-500 mt-1`},`损失方量(m³)`,-1)]),c(`div`,je,[c(`div`,Me,v(f.value.alarmCount),1),n[2]||=c(`div`,{class:`text-xs text-gray-500 mt-1`},`告警次数`,-1)]),c(`div`,Ne,[c(`div`,Pe,v(f.value.avgDelay),1),n[3]||=c(`div`,{class:`text-xs text-gray-500 mt-1`},`平均延迟(min)`,-1)])]),u.value.length>0?(i(),a(`div`,Fe,[n[4]||=c(`div`,{class:`text-xs text-gray-400 mb-2`},`超时订单明细`,-1),c(`div`,Ie,[(i(!0),a(t,null,o(u.value.slice(0,10),e=>(i(),a(`div`,{key:e.order_id,class:`flex justify-between text-xs text-gray-600 py-1 border-b border-gray-50`},[c(`span`,Le,v(e.order_id.slice(-8)),1),c(`span`,null,v(e.destination_name),1),c(`span`,Re,`延迟 `+v(Math.round(((e.arrived_at||e.completed_at)-e.required_arrival_by)/6e4))+`min`,1)]))),128))])])):(i(),a(`div`,ze,`🎉 该时间段无超时订单`))]))}}),Ve={class:`bg-white rounded-lg border shadow-sm p-4`},He={class:`font-semibold text-sm text-gray-700 mb-4`},Ue={key:0,class:`ml-2 text-xs text-blue-500 animate-pulse`},We={class:`grid grid-cols-2 md:grid-cols-4 gap-3 md:gap-4 mb-4`},Ge={class:`text-center p-3 bg-blue-50 rounded-lg`},Ke={class:`text-2xl font-bold text-blue-600`},qe={class:`text-center p-3 bg-orange-50 rounded-lg`},Je={class:`text-2xl font-bold text-orange-600`},Ye={class:`text-center p-3 bg-green-50 rounded-lg`},Xe={class:`text-2xl font-bold text-green-600`},Ze={class:`text-center p-3 bg-purple-50 rounded-lg`},Qe={class:`text-2xl font-bold text-purple-600`},$e={class:`grid grid-cols-2 md:grid-cols-3 gap-3`},et={class:`bg-gray-50 rounded p-2 text-sm`},tt={class:`bg-gray-50 rounded p-2 text-sm`},nt={class:`bg-gray-50 rounded p-2 text-sm`},Y=32,X=22,Z=28,Q=n({__name:`FuelReport`,props:{start:{},end:{}},setup(e){let t=e,n=g(),o=m(),l=u(0),p=u(0),h=u(0),y=u(!1),b=s(()=>{let e=l.value/100*Y,r=p.value/100*X,i=h.value/100*Z,a=e+r+i,o=l.value+p.value+h.value;return{trips:n.orders.filter(e=>e.completed_at&&e.completed_at>=t.start&&e.completed_at<=t.end).length,totalKm:o.toFixed(0),loadedKm:l.value.toFixed(0),emptyKm:p.value.toFixed(0),otherKm:h.value.toFixed(0),totalL:a.toFixed(1),loadedL:e.toFixed(1),emptyL:r.toFixed(1),otherL:i.toFixed(1),avgPer100km:o>0?(a/o*100).toFixed(1):`0`}});function x(e,t,n,r){let i=(n-e)*Math.PI/180,a=(r-t)*Math.PI/180,o=Math.sin(i/2)**2+Math.cos(e*Math.PI/180)*Math.cos(n*Math.PI/180)*Math.sin(a/2)**2;return 6371e3*2*Math.atan2(Math.sqrt(o),Math.sqrt(1-o))}function S(e){let t=0;for(let n=1;n<e.length;n++)t+=x(e[n-1].lat,e[n-1].lng,e[n].lat,e[n].lng);return t/1e3}return f(async()=>{y.value=!0;try{let e=n.orders.filter(e=>e.completed_at&&e.completed_at>=t.start&&e.completed_at<=t.end);if(e.length===0){y.value=!1;return}let r=new Map;async function i(e){if(r.has(e))return r.get(e);let t=await _.getByVin(e);return r.set(e,t),t}for(let t of e){if(!t.vin)continue;let e=await i(t.vin);if(t.departed_at&&t.arrived_at){let n=e.filter(e=>e.timestamp>=t.departed_at&&e.timestamp<=t.arrived_at);l.value+=S(n)}if(t.arrived_at&&t.completed_at){let n=e.filter(e=>e.timestamp>=t.arrived_at&&e.timestamp<=t.completed_at);p.value+=S(n)}}let a=new Set(e.map(e=>e.vin).filter(Boolean));for(let t of o.archiveVehicles){if(a.has(t.vin))continue;let n=await i(t.vin);if(n.length<2)continue;let r=e.filter(e=>e.vin===t.vin).map(e=>[e.departed_at??e.created_at,e.completed_at??Date.now()]),o=0;for(let e=1;e<n.length;e++){let t=(n[e-1].timestamp+n[e].timestamp)/2;r.some(([e,n])=>t>=e&&t<=n)||(o+=x(n[e-1].lat,n[e-1].lng,n[e].lat,n[e].lng))}h.value+=o/1e3}}catch{}y.value=!1}),(e,t)=>(i(),a(`div`,Ve,[c(`h3`,He,[t[0]||=d(` ⛽ 油耗分析 `,-1),y.value?(i(),a(`span`,Ue,`计算中...`)):r(``,!0)]),c(`div`,We,[c(`div`,Ge,[c(`div`,Ke,v(b.value.totalKm),1),t[1]||=c(`div`,{class:`text-xs text-gray-500 mt-1`},`总里程 (km)`,-1)]),c(`div`,qe,[c(`div`,Je,v(b.value.totalL),1),t[2]||=c(`div`,{class:`text-xs text-gray-500 mt-1`},`总油耗 (L)`,-1)]),c(`div`,Ye,[c(`div`,Xe,v(b.value.avgPer100km),1),t[3]||=c(`div`,{class:`text-xs text-gray-500 mt-1`},`百公里油耗 (L)`,-1)]),c(`div`,Ze,[c(`div`,Qe,v(b.value.trips),1),t[4]||=c(`div`,{class:`text-xs text-gray-500 mt-1`},`总趟数`,-1)])]),c(`div`,$e,[c(`div`,et,[c(`div`,{class:`text-gray-400 text-xs`},`满载运输 (`+v(Y)+`L/100km)`),c(`div`,null,v(b.value.loadedKm)+`km / `+v(b.value.loadedL)+`L`,1)]),c(`div`,tt,[c(`div`,{class:`text-gray-400 text-xs`},`空载返回 (`+v(X)+`L/100km)`),c(`div`,null,v(b.value.emptyKm)+`km / `+v(b.value.emptyL)+`L`,1)]),c(`div`,nt,[c(`div`,{class:`text-gray-400 text-xs`},`其他行驶 (`+v(Z)+`L/100km)`),c(`div`,null,v(b.value.otherKm)+`km / `+v(b.value.otherL)+`L`,1)])]),t[5]||=c(`p`,{class:`text-xs text-gray-400 mt-3`},` ⚠️ 油耗为基于 GPS 轨迹距离 × 固定系数的估算值,对接 CAN 油耗数据后可替换为实际油耗 `,-1)]))}}),rt={class:`text-xs text-gray-500 mb-1`},it={key:0,class:`text-xs font-normal text-gray-400 ml-0.5`},$=n({__name:`MetricCard`,props:{label:{},value:{},unit:{},warn:{type:Boolean}},setup(e){function t(e){return Number.isInteger(e)?String(e):e.toFixed(1)}return(n,o)=>(i(),a(`div`,{class:h([`rounded-lg p-3 text-center`,e.warn?`border border-orange-300 bg-orange-50`:`bg-gray-50`])},[c(`div`,rt,v(e.label),1),c(`div`,{class:h([`text-xl font-bold`,e.warn?`text-orange-600`:`text-gray-800`])},[d(v(typeof e.value==`number`?t(e.value):e.value)+` `,1),e.unit?(i(),a(`span`,it,v(e.unit),1)):r(``,!0)],2)],2))}}),at={class:`bg-white rounded-lg border shadow-sm p-4 md:p-6 space-y-4`},ot={class:`flex items-center gap-3`},st={class:`flex gap-1 bg-gray-100 rounded-lg p-1`},ct={class:`text-xs text-gray-400`},lt={key:0,class:`bg-blue-50 border border-blue-200 rounded-lg p-4 text-sm leading-relaxed text-gray-700`},ut={class:`grid grid-cols-2 md:grid-cols-4 gap-3`},dt={key:1,class:`border-t pt-4`},ft={class:`space-y-1`},pt={key:2,class:`border-t pt-4 text-sm text-green-600`},mt=n({__name:`DailySummary`,setup(e){let n=g(),l=p(),f=u(`daily`),m=u(!1),_=u(``),b=u([]),x=s(()=>{let e=new Date;if(f.value===`daily`)return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,`0`)}-${String(e.getDate()).padStart(2,`0`)}`;let t=e.getDay(),n=new Date(e);n.setDate(e.getDate()-(t===0?6:t-1));let r=new Date(n);r.setDate(n.getDate()+6);let i=e=>`${e.getMonth()+1}/${e.getDate()}`;return n.getMonth()!==r.getMonth()||n.getFullYear()!==r.getFullYear()?`${n.getFullYear()}-${i(n)} 至 ${r.getFullYear()}-${i(r)}`:i(n)+` - `+i(r)}),S=s(()=>{let e=new Date;if(f.value===`daily`)return e.setHours(0,0,0,0),e.getTime();let t=e.getDay(),n=new Date(e);return n.setDate(e.getDate()-(t===0?6:t-1)),n.setHours(0,0,0,0),n.getTime()}),C=s(()=>Date.now()),w=s(()=>n.orders.filter(e=>e.completed_at&&e.completed_at>=S.value&&e.completed_at<=C.value)),T=s(()=>l.alarms.filter(e=>e.timestamp>=S.value&&e.timestamp<=C.value)),E=s(()=>{let e=w.value,t=T.value,n=e.length,r=e.reduce((e,t)=>e+t.volume_m3,0),i=e.filter(e=>e.completed_at&&e.completed_at<=e.required_arrival_by).length,a=n>0?i/n*100:0,o=t.length,s=e.filter(e=>e.completed_at&&e.completed_at>e.required_arrival_by).length,c=e.filter(e=>e.completed_at&&e.completed_at>e.required_arrival_by).reduce((e,t)=>e+t.volume_m3,0),l=new Set(e.map(e=>e.station_id).filter(Boolean)).size,u=l>0?(n/l).toFixed(1):`0`,d=e.filter(e=>e.arrived_at&&e.discharging_at);return{totalTrips:n,totalVolume:r,onTimeRate:a,alarmCount:o,timeoutCount:s,lostVolume:c,stationCount:l,turnoverRate:u,avgWait:d.length>0?Math.round(d.reduce((e,t)=>e+((t.discharging_at??0)-(t.arrived_at??0)),0)/d.length/6e4):0}});function D(){m.value=!0;try{let e=E.value,t=[];t.push(`${x.value}共完成运输 ${e.totalTrips} 趟,运输方量 ${e.totalVolume.toFixed(1)} m³。`),e.onTimeRate>=90?t.push(`准时率达到 ${e.onTimeRate.toFixed(0)}%,表现优秀。`):e.onTimeRate>=70?t.push(`准时率 ${e.onTimeRate.toFixed(0)}%,有待改善。`):t.push(`准时率仅 ${e.onTimeRate.toFixed(0)}%,需重点关注。`),e.timeoutCount>0&&t.push(`发生超时 ${e.timeoutCount} 次,损失方量约 ${e.lostVolume.toFixed(1)} m³。`),e.avgWait>30&&t.push(`平均卸料等待 ${e.avgWait} 分钟,搅拌站效率偏低。`),t.push(`搅拌站 ${e.stationCount} 个,平均周转率 ${e.turnoverRate} 趟/站。`),e.alarmCount>0&&t.push(`触发告警 ${e.alarmCount} 次。`),_.value=t.join(``);let n=[];e.onTimeRate<80&&n.push(`准时率低于 80%(当前 ${e.onTimeRate.toFixed(0)}%)`),e.timeoutCount>0&&n.push(`${e.timeoutCount} 次超时,损失 ${e.lostVolume.toFixed(1)} m³`),e.alarmCount>0&&n.push(`${e.alarmCount} 条告警记录`);let r=new Map;for(let e of w.value)e.station_id&&r.set(e.station_id,(r.get(e.station_id)||0)+1);for(let[e,t]of r)t<3&&n.push(`搅拌站 ${e.slice(-4)} 仅 ${t} 趟,周转不足`);b.value=n}finally{m.value=!1}}return(e,n)=>(i(),a(`div`,at,[c(`div`,ot,[c(`div`,st,[c(`button`,{class:h([`px-4 py-1.5 text-sm rounded-md transition-colors`,f.value===`daily`?`bg-white text-blue-600 shadow-sm font-medium`:`text-gray-500`]),onClick:n[0]||=e=>f.value=`daily`},` 📅 日报 `,2),c(`button`,{class:h([`px-4 py-1.5 text-sm rounded-md transition-colors`,f.value===`weekly`?`bg-white text-blue-600 shadow-sm font-medium`:`text-gray-500`]),onClick:n[1]||=e=>f.value=`weekly`},` 📆 周报 `,2)]),c(`span`,ct,v(x.value),1),c(`button`,{class:`px-4 py-2 text-sm bg-green-600 text-white rounded-lg hover:bg-green-700 ml-auto`,onClick:D},` 📝 生成摘要 `)]),_.value?(i(),a(`div`,lt,v(_.value),1)):r(``,!0),c(`div`,ut,[y($,{label:`总趟数`,value:E.value.totalTrips,unit:`趟`},null,8,[`value`]),y($,{label:`总方量`,value:E.value.totalVolume.toFixed(1),unit:`m³`},null,8,[`value`]),y($,{label:`准时率`,value:E.value.onTimeRate.toFixed(0),unit:`%`,warn:E.value.onTimeRate<80},null,8,[`value`,`warn`]),y($,{label:`告警数`,value:E.value.alarmCount,unit:`次`,warn:E.value.alarmCount>0},null,8,[`value`,`warn`]),y($,{label:`超时次数`,value:E.value.timeoutCount,unit:`次`,warn:E.value.timeoutCount>0},null,8,[`value`,`warn`]),y($,{label:`损失方量`,value:E.value.lostVolume.toFixed(1),unit:`m³`,warn:E.value.lostVolume>0},null,8,[`value`,`warn`]),y($,{label:`搅拌站`,value:E.value.stationCount,unit:`个`},null,8,[`value`]),y($,{label:`平均周转`,value:E.value.turnoverRate,unit:`趟/站`},null,8,[`value`])]),b.value.length?(i(),a(`div`,dt,[n[3]||=c(`h4`,{class:`font-semibold text-sm text-orange-700 mb-2`},`⚠️ 异常事项`,-1),c(`ul`,ft,[(i(!0),a(t,null,o(b.value,e=>(i(),a(`li`,{key:e,class:`text-sm text-orange-600 flex gap-2`},[n[2]||=c(`span`,null,`•`,-1),d(` `+v(e),1)]))),128))])])):_.value?(i(),a(`div`,pt,` ✅ 本期无异常事项 `)):r(``,!0)]))}}),ht={class:`space-y-4`},gt={class:`flex items-center justify-between`},_t={class:`flex gap-2`},vt=n({__name:`ReportStats`,setup(t){let n=[`daily`,`efficiency`,`drum`,`fuel`,`safety`],o=0;function s(e){o=e.touches[0].clientX}function d(e){let t=e.changedTouches[0].clientX-o;if(Math.abs(t)<30)return;let r=n.indexOf(w.value),i=t<0?r+1:r-1;i>=0&&i<n.length&&(w.value=n[i])}let p=g(),m=Date.now(),_=new Date;_.setHours(0,0,0,0);let v=u(_.getTime()),C=u(m),w=u(`daily`);return f(async()=>{p.loaded||await p.load()}),(t,n)=>(i(),a(`div`,ht,[c(`div`,gt,[n[10]||=c(`h1`,{class:`text-2xl font-bold`},`📈 报表统计`,-1),c(`div`,_t,[c(`button`,{class:`px-3 py-1.5 text-xs bg-blue-600 text-white rounded-lg hover:bg-blue-700`,onClick:n[0]||=t=>e(x)(e(p).orders)},` 📥 导出 JSON `),c(`button`,{class:`px-3 py-1.5 text-xs bg-green-600 text-white rounded-lg hover:bg-green-700`,onClick:n[1]||=t=>e(b)(e(p).orders)},` 📊 导出 CSV `),c(`button`,{class:`px-3 py-1.5 text-xs bg-red-600 text-white rounded-lg hover:bg-red-700`,onClick:n[2]||=t=>e(S)(`车队报表`)},` 📄 打印 PDF `)])]),y(D,{start:v.value,"onUpdate:start":n[3]||=e=>v.value=e,end:C.value,"onUpdate:end":n[4]||=e=>C.value=e},null,8,[`start`,`end`]),c(`div`,{class:`flex gap-1 bg-gray-100 rounded-lg p-1 w-fit overflow-x-auto touch-pan-x`,onTouchstart:s,onTouchend:d},[c(`button`,{class:h([`px-4 py-1.5 text-sm rounded-md transition-colors`,w.value===`daily`?`bg-white text-blue-600 shadow-sm font-medium`:`text-gray-500`]),onClick:n[5]||=e=>w.value=`daily`},` 📝 日报/周报 `,2),c(`button`,{class:h([`px-4 py-1.5 text-sm rounded-md transition-colors`,w.value===`efficiency`?`bg-white text-blue-600 shadow-sm font-medium`:`text-gray-500`]),onClick:n[6]||=e=>w.value=`efficiency`},` 🚛 运载效率 `,2),c(`button`,{class:h([`px-4 py-1.5 text-sm rounded-md transition-colors`,w.value===`drum`?`bg-white text-blue-600 shadow-sm font-medium`:`text-gray-500`]),onClick:n[7]||=e=>w.value=`drum`},` 🔄 搅拌筒利用率 `,2),c(`button`,{class:h([`px-4 py-1.5 text-sm rounded-md transition-colors`,w.value===`fuel`?`bg-white text-blue-600 shadow-sm font-medium`:`text-gray-500`]),onClick:n[8]||=e=>w.value=`fuel`},` ⛽ 油耗分析 `,2),c(`button`,{class:h([`px-4 py-1.5 text-sm rounded-md transition-colors`,w.value===`safety`?`bg-white text-blue-600 shadow-sm font-medium`:`text-gray-500`]),onClick:n[9]||=e=>w.value=`safety`},` 🛡️ 安全超时 `,2)],32),w.value===`daily`?(i(),l(mt,{key:0})):r(``,!0),w.value===`efficiency`?(i(),l(pe,{key:1,start:v.value,end:C.value},null,8,[`start`,`end`])):r(``,!0),w.value===`drum`?(i(),l(we,{key:2,start:v.value,end:C.value},null,8,[`start`,`end`])):r(``,!0),w.value===`safety`?(i(),l(Be,{key:3,start:v.value,end:C.value},null,8,[`start`,`end`])):r(``,!0),w.value===`fuel`?(i(),l(Q,{key:4,start:v.value,end:C.value},null,8,[`start`,`end`])):r(``,!0)]))}});export{vt as default};
@@ -0,0 +1,5 @@
1
+ import{$ as e,A as t,B as n,E as r,F as i,G as a,H as o,I as s,K as c,L as l,N as u,O as d,Q as f,R as p,X as m,et as h,l as g,n as _,nt as v,s as y,z as b}from"./index-CTrnN2TM.js";import{t as x}from"./deepseek-kuCyKxoN.js";var S=[{type:`material_enough`,patterns:[/料够了/i,/料已经够了/i,/不需要再送了/i,/停止供货/i]},{type:`stop_supply`,patterns:[/不要再供货/i,/暂停供货/i,/暂停这个工地/i,/暂停.*工地/i,/不要送了/i]},{type:`need_more`,patterns:[/还差(\d+)方/i,/需要(\d+)方/i,/再送(\d+)方/i,/差(\d+)立方/i,/还需要(\d+)立方/i]},{type:`pump_broken`,patterns:[/泵坏了/i,/泵机坏了/i,/混凝土泵坏了/i,/工地泵坏了/i,/打不了料/i]},{type:`pump_fixed`,patterns:[/泵修好了/i,/泵好了/i,/泵机修好了/i,/可以泵送了/i]},{type:`resume_delivery`,patterns:[/可以发车了/i,/继续供货/i,/恢复供货/i,/继续送料/i]},{type:`request_more`,patterns:[/还需要(\d+)方/i,/还需要(\d+)立方/i,/再要(\d+)方/i,/补充(\d+)方/i]}];function C(e){for(let t of S)for(let n of t.patterns)if(n.test(e))return t.type;return`unknown`}function w(e){for(let t of[/(\d+(?:\.\d+)?)\s*方/,/(\d+(?:\.\d+)?)\s*立方/,/(\d+(?:\.\d+)?)\s*m³/]){let n=e.match(t);if(n)return parseFloat(n[1])}return null}function T(e,t){let n=e.match(/([\u4e00-\u9fa5]{2,10}(?:工地|项目|标段))/i);if(n)return n[1];let r=e.replace(/[^\u4e00-\u9fa5]/g,``);for(let e of t)if(r.includes(e)||e.includes(r.slice(0,4)))return e;return null}async function E(e,t,n){let r=g(),i=y(),a=null;t&&(a=i.getByName(t)??null);let o=r.activeOrders;switch(a&&(o=o.filter(e=>e.destination_fence_id===a.fence_id)),e){case`material_enough`:case`stop_supply`:{if(!a&&t)return{success:!1,error:`未找到工地 "${t}"`};if(o.length===0)return{success:!0,message:`工地 "${t}" 当前无进行中的运输任务`};let n=[];for(let t of o)await _.pauseOrder(t.order_id,e),n.push(t.order_id);return{success:!0,message:`✅ 已暂停工地 "${t}" 的 ${n.length} 个运输任务`,orders:n}}case`need_more`:return!a&&t?{success:!1,error:`未找到工地 "${t}"`}:{success:!0,message:`📝 需要为工地 "${t}" 补充 ${n??`?`} 方,请前往调度中心创建订单`,requireConfirm:!1};case`pump_broken`:{if(o.length===0)return{success:!0,message:`${t?`工地 "`+t+`" `:``}当前无进行中的运输任务`};let e=[];for(let t of o)await _.terminateOrder(t.order_id,`泵坏紧急终止`),e.push(t.order_id);return{success:!0,message:`🚨 已紧急终止 ${e.length} 个运输任务!请通知相关司机`,orders:e,requireConfirm:!0}}case`pump_fixed`:case`resume_delivery`:{if(!a&&t)return{success:!1,error:`未找到工地 "${t}"`};let e=r.orders.filter(e=>e.destination_fence_id===a?.fence_id&&e.status===`paused`);if(e.length===0)return{success:!0,message:`工地 "${t}" 无暂停订单,可直接派新任务`};for(let t of e)await _.resumeOrder(t.order_id);return{success:!0,message:`✅ 已恢复工地 "${t}" 的 ${e.length} 个运输任务`,orders:e.map(e=>e.order_id)}}case`request_more`:return!a&&t?{success:!1,error:`未找到工地 "${t}"`}:{success:!0,message:`📝 需要为工地 "${t}" 补充 ${n??`?`} 方,请前往调度中心创建补充订单`,requireConfirm:!1};default:return{success:!1,error:`无法识别该指令,请尝试:"泵坏了,停止XX工地" 或 "还差10方"`}}}async function D(e){let t=y().fences.map(e=>e.name),n=C(e);if(n===`unknown`&&x.enabled)try{let r=await x.recognizeIntent(e,t);r.intent!==`unknown`&&r.confidence>.5&&(n=r.intent,console.log(`[SmartDispatch] LLM fallback: "${e}" → ${n} (confidence: ${r.confidence})`))}catch(e){console.warn(`[SmartDispatch] LLM fallback failed:`,e)}if(n===`unknown`)return{success:!1,intent:`unknown`,siteName:null,volume:null,error:`无法识别该指令。试试:"泵坏了,停止XX工地"、"还差10方"、"可以发车了"`};let r=T(e,t),i=w(e),a=await E(n,r,i);if(a.success&&x.enabled)try{let e=await x.generateReply(n,a);return{...a,intent:n,siteName:r,volume:i,message:e,llmFallback:!0}}catch{}return{...a,intent:n,siteName:r,volume:i}}function O(e){return{material_enough:`料够了`,stop_supply:`暂停供货`,need_more:`需要更多方量`,pump_broken:`泵坏了`,pump_fixed:`泵修好了`,resume_delivery:`恢复供货`,request_more:`请求补充方量`,unknown:`未知意图`}[e]??e}var k={class:`bg-white rounded-lg border shadow-sm flex flex-col h-[600px]`},A={class:`px-4 py-2 border-b flex gap-2 flex-wrap`},j=[`onClick`],M={class:`whitespace-pre-wrap`},N={key:0},P={key:1},F={class:`text-right text-[10px] opacity-50 mt-0.5`},I={key:0,class:`flex items-center gap-2 text-sm text-gray-400`},L={class:`px-4 py-3 border-t flex gap-2`},R=[`disabled`],z=[`disabled`],B=n({__name:`ChatDispatchPanel`,setup(n){let l=f(``),g=f([{role:`system`,content:`👋 你好!我是 AI 调度助手。你可以用自然语言指令来管理运输任务:
2
+ • "泵坏了,停止XX工地" → 紧急终止
3
+ • "料够了" → 暂停供货
4
+ • "还差10方" → 调整方量
5
+ • "可以发车了" → 恢复供货`,time:Date.now()}]),_=f(!1),y=f(null);async function b(){let e=l.value.trim();if(!(!e||_.value)){g.value.push({role:`user`,content:e,time:Date.now()}),l.value=``,_.value=!0,await x();try{let t=await D(e);g.value.push({role:`ai`,content:t.success?t.message??`操作成功`:`⚠️ ${t.error??`未知错误`}`,time:Date.now(),result:t})}catch(e){g.value.push({role:`ai`,content:`❌ 处理失败: ${e.message}`,time:Date.now()})}finally{_.value=!1,await x()}}}async function x(){await o(),y.value&&(y.value.scrollTop=y.value.scrollHeight)}function S(e){return new Date(e).toLocaleTimeString(`zh-CN`,{hour:`2-digit`,minute:`2-digit`})}let C=[{text:`泵坏了`,label:`🚨 泵坏了`},{text:`料够了`,label:`✅ 料够了`},{text:`还差5方`,label:`📏 还差5方`},{text:`泵修好了,可以发车了`,label:`🔄 泵修好了`}];return(n,o)=>(a(),s(`div`,k,[o[2]||=u(`div`,{class:`px-4 py-3 border-b bg-gradient-to-r from-blue-50 to-indigo-50`},[u(`h3`,{class:`font-semibold text-sm text-gray-800`},`💬 AI 智能调度`),u(`p`,{class:`text-xs text-gray-400 mt-0.5`},`用自然语言管理运输任务`)],-1),u(`div`,A,[(a(),s(t,null,c(C,e=>u(`button`,{key:e.text,class:`px-2 py-1 text-xs rounded-full border border-blue-200 text-blue-600 hover:bg-blue-50 transition-colors`,onClick:t=>{l.value=e.text,b()}},v(e.label),9,j)),64))]),u(`div`,{ref_key:`chatContainer`,ref:y,class:`flex-1 overflow-y-auto p-4 space-y-3`},[(a(!0),s(t,null,c(g.value,(t,n)=>(a(),s(`div`,{key:n,class:h([`max-w-[85%] rounded-xl px-3 py-2 text-sm`,t.role===`user`?`ml-auto bg-blue-600 text-white`:t.role===`system`?`mx-auto bg-gray-100 text-gray-600 text-center text-xs`:`bg-gray-100 text-gray-800`])},[u(`div`,M,v(t.content),1),t.result?.intent&&t.result.intent!==`unknown`?(a(),s(`div`,{key:0,class:h([`mt-1 text-xs opacity-70`,t.role===`user`?``:`text-gray-400`])},[p(` 意图: `+v(e(O)(t.result.intent))+` `,1),t.result.siteName?(a(),s(`span`,N,` | 工地: `+v(t.result.siteName),1)):i(``,!0),t.result.volume?(a(),s(`span`,P,` | 方量: `+v(t.result.volume)+`m³`,1)):i(``,!0)],2)):i(``,!0),u(`div`,F,v(S(t.time)),1)],2))),128)),_.value?(a(),s(`div`,I,[...o[1]||=[u(`span`,{class:`animate-spin`},`⏳`,-1),p(` AI 正在分析... `,-1)]])):i(``,!0)],512),u(`div`,L,[m(u(`input`,{"onUpdate:modelValue":o[0]||=e=>l.value=e,class:`flex-1 border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500`,placeholder:`输入指令,如:泵坏了,停止XX工地供货`,disabled:_.value,onKeyup:d(b,[`enter`])},null,40,R),[[r,l.value]]),u(`button`,{class:`px-4 py-2 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50`,disabled:!l.value.trim()||_.value,onClick:b},` 发送 `,8,z)])]))}}),V={class:`space-y-4`},H={class:`grid grid-cols-1 lg:grid-cols-3 gap-4`},U={class:`lg:col-span-2`},W=n({__name:`SmartDispatch`,setup(e){return(e,t)=>(a(),s(`div`,V,[t[1]||=u(`h1`,{class:`text-2xl font-bold`},`💬 AI 智能调度`,-1),u(`div`,H,[u(`div`,U,[b(B)]),t[0]||=l(`<div class="space-y-3"><div class="bg-white rounded-lg border shadow-sm p-4"><h3 class="font-semibold text-sm text-gray-700 mb-3">📖 支持的场景</h3><div class="space-y-3 text-sm"><div class="p-2 bg-green-50 rounded-lg"><div class="font-medium text-green-700">场景1:料够了/暂停供货</div><div class="text-xs text-gray-500 mt-0.5"> &quot;料够了&quot;、&quot;不要再供货了&quot;、&quot;还差10方&quot; </div><div class="text-xs text-gray-400 mt-0.5"> → 暂停/调整该工地运输任务 </div></div><div class="p-2 bg-red-50 rounded-lg"><div class="font-medium text-red-700">场景2:泵坏了(紧急)</div><div class="text-xs text-gray-500 mt-0.5"> &quot;泵坏了&quot;、&quot;工地泵坏了&quot; </div><div class="text-xs text-gray-400 mt-0.5"> → 立即终止该工地所有运输任务 </div></div><div class="p-2 bg-blue-50 rounded-lg"><div class="font-medium text-blue-700">场景3:泵修好了/恢复</div><div class="text-xs text-gray-500 mt-0.5"> &quot;泵修好了&quot;、&quot;可以发车了&quot;、&quot;还需要5方&quot; </div><div class="text-xs text-gray-400 mt-0.5"> → 恢复被暂停订单或创建补充订单 </div></div></div></div><div class="bg-white rounded-lg border shadow-sm p-4"><h3 class="font-semibold text-sm text-gray-700 mb-2">💡 提示</h3><ul class="text-xs text-gray-500 space-y-1"><li>• 指令中请包含<strong>工地名称</strong>(如&quot;XX大桥工地&quot;)</li><li>• 方量数字会自动提取(如&quot;还差5方&quot;→5m³)</li><li>• 高危操作(终止任务)需要确认</li><li>• 模糊表达将降级到 LLM 识别</li></ul></div></div>`,1)])]))}});export{W as default};
@@ -0,0 +1 @@
1
+ import{A as e,B as t,G as n,I as r,K as i,M as a,N as o,c as s,d as c,et as l,l as u,nt as d}from"./index-CTrnN2TM.js";var f={class:`grid grid-cols-5 gap-4 mb-4`},p={class:`flex items-center justify-between`},m={class:`text-lg`},h={class:`text-xs text-gray-500 mt-1`},g=t({__name:`StatsBar`,setup(t){let g=c(),_=u(),v=s(),y=a(()=>[{label:`车辆总数`,value:g.vehicleCount,color:`text-gray-700`,bg:`bg-gray-50`,icon:`🚛`},{label:`在线车辆`,value:g.onlineCount,color:`text-green-600`,bg:`bg-green-50`,icon:`🟢`},{label:`运输中`,value:g.transportingVehicles.length,color:`text-blue-600`,bg:`bg-blue-50`,icon:`🔄`},{label:`今日方量`,value:_.completedOrders.filter(e=>e.completed_at&&e.completed_at>Date.now()-864e5).reduce((e,t)=>e+t.volume_m3,0).toFixed(1)+` m³`,color:`text-purple-600`,bg:`bg-purple-50`,icon:`📊`},{label:`活跃告警`,value:v.activeCount,color:v.activeCount>0?`text-red-600`:`text-gray-400`,bg:v.activeCount>0?`bg-red-50`:`bg-gray-50`,icon:`🔔`}]);return(t,a)=>(n(),r(`div`,f,[(n(!0),r(e,null,i(y.value,e=>(n(),r(`div`,{key:e.label,class:l([`rounded-lg p-3 border shadow-sm`,e.bg])},[o(`div`,p,[o(`span`,m,d(e.icon),1),o(`span`,{class:l([`text-2xl font-bold`,e.color])},d(e.value),3)]),o(`div`,h,d(e.label),1)],2))),128))]))}});export{g as t};
@@ -0,0 +1 @@
1
+ import{B as e,G as t,I as n,M as r,N as i,R as a,et as o,nt as s}from"./index-CTrnN2TM.js";var c=e({__name:`StatusBadge`,props:{status:{},type:{},size:{}},setup(e){let c=e,l={idle:`bg-gray-100 text-gray-700`,loading:`bg-yellow-100 text-yellow-700`,transporting:`bg-green-100 text-green-700`,arrived:`bg-blue-100 text-blue-700`,discharging:`bg-purple-100 text-purple-700`,returning:`bg-indigo-100 text-indigo-700`,offline:`bg-gray-300 text-gray-500`,pending:`bg-gray-100 text-gray-600`,accepted:`bg-blue-100 text-blue-700`,completed:`bg-green-50 text-green-600`,cancelled:`bg-red-50 text-red-500`,paused:`bg-orange-50 text-orange-600`,critical:`bg-red-100 text-red-700`,warning:`bg-orange-100 text-orange-700`,info:`bg-blue-100 text-blue-700`,active:`bg-red-100 text-red-700`,acknowledged:`bg-yellow-100 text-yellow-700`,resolved:`bg-green-100 text-green-600`,ignored:`bg-gray-100 text-gray-500`},u={idle:`待命`,loading:`装料中`,transporting:`运输中`,arrived:`已到达`,discharging:`卸料中`,returning:`返回中`,offline:`离线`,pending:`待接单`,accepted:`已接单`,completed:`已完成`,cancelled:`已取消`,paused:`已暂停`,critical:`紧急`,warning:`警告`,info:`提示`,active:`未处理`,acknowledged:`已知悉`,resolved:`已解决`,ignored:`已忽略`},d=r(()=>{switch(c.size){case`sm`:return`px-1.5 py-0.5 text-xs`;case`lg`:return`px-3 py-1 text-sm`;default:return`px-2 py-0.5 text-xs`}}),f=r(()=>l[c.status]??`bg-gray-100 text-gray-600`),p=r(()=>u[c.status]??c.status);return(r,c)=>(t(),n(`span`,{class:o([`inline-flex items-center rounded-full font-medium`,[f.value,d.value]])},[i(`span`,{class:o([`w-1.5 h-1.5 rounded-full mr-1.5`,{"bg-green-500":e.status===`transporting`||e.status===`completed`||e.status===`resolved`,"bg-yellow-500":e.status===`loading`||e.status===`warning`||e.status===`acknowledged`,"bg-red-500":e.status===`critical`||e.status===`active`||e.status===`cancelled`,"bg-blue-500":e.status===`arrived`||e.status===`discharging`||e.status===`info`,"bg-purple-500":e.status===`returning`,"bg-gray-400":e.status===`idle`||e.status===`pending`||e.status===`offline`||e.status===`ignored`,"bg-orange-500":e.status===`paused`}])},null,2),a(` `+s(p.value),1)],2))}});export{c as t};
@@ -0,0 +1 @@
1
+ import{A as e,B as t,C as n,E as r,F as i,G as a,I as o,J as s,K as c,M as l,N as u,P as d,Q as f,T as p,U as m,X as h,Z as g,et as _,f as ee,nt as v,p as y}from"./index-CTrnN2TM.js";var b={class:`bg-white rounded-lg border shadow-sm p-4`},x={class:`font-semibold text-sm text-gray-700 mb-4`},S={class:`space-y-3`},C={class:`text-xs text-gray-500`},w=[`value`,`type`,`placeholder`,`onInput`],T={key:1,class:`flex items-center gap-2 cursor-pointer`},E=[`checked`,`onChange`],D={class:`text-sm text-gray-700`},O={key:2,class:`text-xs text-gray-400`},k=t({__name:`SettingsForm`,props:{fields:{},title:{}},emits:[`save`],setup(t,{emit:n}){let r=t,l=n,d=g({});s(()=>r.fields,e=>{for(let t of e)d[t.key]===void 0&&(d[t.key]=t.value)},{deep:!0,immediate:!0});function f(e,t){d[e]=t.target.value}function p(e,t){d[e]=t.target.checked}function m(){l(`save`,r.fields.map(e=>{let t=d[e.key]??e.value;return e.type===`number`&&(t=Number(t)),e.type===`toggle`&&(t=!!t),{key:e.key,value:t}}))}return(n,r)=>(a(),o(`div`,b,[u(`h3`,x,v(t.title),1),u(`div`,S,[(a(!0),o(e,null,c(t.fields,e=>(a(),o(`div`,{key:e.key,class:`flex flex-col gap-1`},[u(`label`,C,v(e.label),1),e.type===`toggle`?(a(),o(`label`,T,[u(`input`,{type:`checkbox`,checked:!!(d[e.key]??e.value),class:`w-4 h-4 rounded text-blue-600`,onChange:t=>p(e.key,t)},null,40,E),u(`span`,D,v(d[e.key]??e.value?`已启用`:`已禁用`),1)])):(a(),o(`input`,{key:0,value:d[e.key]??e.value,type:e.type===`password`?`password`:`text`,placeholder:e.placeholder,class:`border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 w-full`,onInput:t=>f(e.key,t)},null,40,w)),e.hint?(a(),o(`span`,O,v(e.hint),1)):i(``,!0)]))),128))]),u(`button`,{class:`mt-4 w-full py-2 bg-blue-600 text-white text-sm font-medium rounded-lg hover:bg-blue-700 transition-colors`,onClick:m},` 保存 `+v(t.title),1)]))}});function A(){let e=y.config.ollama;return{baseUrl:e.baseUrl||`http://localhost:11434`,model:e.model||`nomic-embed-text`}}async function te(e={}){let t=e.baseUrl??A().baseUrl;try{let n=await fetch(`${t}/api/tags`,{signal:e.signal});return n.ok?{ok:!0,models:((await n.json()).models??[]).map(e=>e.name).filter(e=>typeof e==`string`)}:{ok:!1,error:`Ollama 返回 ${n.status}`}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}}var ne={class:`space-y-4`},re={class:`flex gap-1 bg-gray-100 rounded-lg p-1 w-fit`},ie=[`onClick`],ae={key:2,class:`bg-white rounded-lg border shadow-sm p-4 space-y-4`},oe={key:1},se={class:`grid grid-cols-3 gap-3`},ce={key:3,class:`space-y-4`},le={class:`bg-white rounded-lg border shadow-sm p-4`},j={class:`flex gap-1 bg-gray-100 rounded-lg p-1 w-fit`},M={key:0,class:`bg-white rounded-lg border shadow-sm p-4 space-y-4`},N={class:`grid grid-cols-2 gap-4`},P={class:`flex items-center gap-2`},F={class:`bg-gray-50 rounded-lg p-3`},I={class:`flex items-center justify-between mb-2`},L=[`disabled`],R={class:`space-y-1.5 text-xs`},z={class:`flex items-center gap-2`},B={class:`text-gray-500`},V={key:0,class:`flex items-center gap-2`},H={class:`text-gray-500`},U={key:1,class:`text-red-500`},ue={key:1,class:`bg-white rounded-lg border shadow-sm p-4 space-y-4`},de={class:`grid grid-cols-2 gap-4`},fe={class:`flex items-center gap-2`},W=t({__name:`SystemSettings`,setup(t){let y=ee(),b=f(`emqx`),x=[{key:`emqx`,label:`📡 EMQX 连接`},{key:`alarm`,label:`🔔 告警阈值`},{key:`map`,label:`🗺️ 地图配置`},{key:`ai`,label:`🤖 AI 配置`}],S=f(`ollama`),C=f(`http://localhost:11434`),w=f(`nomic-embed-text`),T=f(``),E=f(`https://api.deepseek.com`),D=f(`deepseek-v4-flash`),O=f(!1),A=f(!0),W=f(`idle`),G=f([]),K=f(``),q=f(!1),J=g({provider:`amap`,key:``,securityCode:``,lng:116.3972,lat:39.9075,zoom:13}),Y=f(``),X=f(!0);function Z(){J.provider=y.mapProvider,J.key=y.amap.key,J.securityCode=y.amap.securityCode,J.lng=y.ui.mapCenterLng,J.lat=y.ui.mapCenterLat,J.zoom=y.ui.mapZoomLevel}async function pe(){let e=await y.setBatch([{key:`mapProvider`,value:J.provider},{key:`amap.key`,value:J.key},{key:`amap.securityCode`,value:J.securityCode},{key:`ui.mapCenterLng`,value:Number(J.lng)},{key:`ui.mapCenterLat`,value:Number(J.lat)},{key:`ui.mapZoomLevel`,value:Number(J.zoom)}]);X.value=e,Y.value=e?`✅ 地图配置已保存`:`❌ 保存失败`,setTimeout(()=>{Y.value=``},3e3)}s(b,e=>{e===`map`&&Z()}),m(async()=>{y.ready||await y.load(),Z(),C.value=y.ollama.baseUrl,w.value=y.ollama.model,A.value=y.ollama.enabled,T.value=y.deepseek.apiKey,E.value=y.deepseek.baseUrl,D.value=y.deepseek.model,O.value=y.deepseek.enabled});async function me(){q.value=!0,W.value=`checking`,K.value=``;try{let e=await te({baseUrl:C.value});e.ok?(W.value=`ready`,G.value=e.models):(W.value=`error`,K.value=e.error)}catch(e){W.value=`error`,K.value=e.message}finally{q.value=!1}}async function he(){await y.setBatch([{key:`ollama.baseUrl`,value:C.value},{key:`ollama.model`,value:w.value},{key:`ollama.enabled`,value:A.value}]),window.alert(`✅ Ollama 配置已保存`)}async function ge(){await y.setBatch([{key:`deepseek.apiKey`,value:T.value},{key:`deepseek.baseUrl`,value:E.value},{key:`deepseek.model`,value:D.value},{key:`deepseek.enabled`,value:O.value}]),window.alert(`✅ DeepSeek 配置已保存`)}let _e=l(()=>[{key:`emqx.broker`,label:`MQTT 服务器地址`,value:y.emqx.broker,placeholder:`121.40.192.196`},{key:`emqx.port`,label:`MQTT 端口 (WebSocket)`,value:y.emqx.port,type:`number`,placeholder:`8083`,hint:`浏览器需 WebSocket 端口(EMQX 默认 8083)`},{key:`emqx.username`,label:`用户名`,value:y.emqx.username},{key:`emqx.password`,label:`密码`,value:y.emqx.password,type:`password`},{key:`emqx.clientIdPrefix`,label:`Client ID 前缀`,value:y.emqx.clientIdPrefix,placeholder:`mixer-client`}]),Q=l(()=>[{key:`business.concreteSettingTimeMin`,label:`默认初凝时间 (分钟)`,value:y.business.concreteSettingTimeMin,type:`number`,hint:`C30标号默认135分钟`},{key:`business.drumStopAlarmThresholdSec`,label:`停筒告警阈值 (秒)`,value:y.business.drumStopAlarmThresholdSec,type:`number`,hint:`运输中停筒超过此时间触发告警`},{key:`business.alarmCooldownMinutes`,label:`告警冷却时间 (分钟)`,value:y.business.alarmCooldownMinutes,type:`number`,hint:`同类型告警冷却期内不重复触发`},{key:`business.overspeedThresholdKmh`,label:`超速阈值 (km/h)`,value:y.business.overspeedThresholdKmh,type:`number`},{key:`business.fenceCheckIntervalMs`,label:`围栏检测间隔 (ms)`,value:y.business.fenceCheckIntervalMs,type:`number`,hint:`建议3000ms`}]);l(()=>[{key:`amap.key`,label:`高德地图 API Key`,value:y.amap.key,placeholder:`填入你的 AMap Key`},{key:`ui.mapCenterLng`,label:`默认中心经度`,value:y.ui.mapCenterLng,type:`number`},{key:`ui.mapCenterLat`,label:`默认中心纬度`,value:y.ui.mapCenterLat,type:`number`},{key:`ui.mapZoomLevel`,label:`默认缩放级别`,value:y.ui.mapZoomLevel,type:`number`,hint:`3-18`}]);async function $(e){let t=await y.setBatch(e);window.alert(t?`✅ 配置已保存`:`❌ 保存失败,请检查输入值格式`)}async function ve(){await y.reset(),window.alert(`已重置为默认值`)}return(t,s)=>(a(),o(`div`,ne,[s[41]||=u(`h1`,{class:`text-2xl font-bold`},`⚙️ 系统设置`,-1),u(`div`,re,[(a(),o(e,null,c(x,e=>u(`button`,{key:e.key,class:_([`px-4 py-2 text-sm rounded-md transition-colors`,b.value===e.key?`bg-white text-blue-600 shadow-sm font-medium`:`text-gray-500 hover:text-gray-700`]),onClick:t=>b.value=e.key},v(e.label),11,ie)),64))]),b.value===`emqx`?(a(),d(k,{key:0,title:`EMQX 连接配置`,fields:_e.value,onSave:$},null,8,[`fields`])):i(``,!0),b.value===`alarm`?(a(),d(k,{key:1,title:`告警阈值配置`,fields:Q.value,onSave:$},null,8,[`fields`])):i(``,!0),b.value===`map`?(a(),o(`div`,ae,[s[24]||=u(`h3`,{class:`font-semibold text-sm text-gray-700`},`🗺️ 地图配置`,-1),u(`div`,null,[s[17]||=u(`label`,{class:`text-xs text-gray-500 block mb-1`},`地图供应商`,-1),h(u(`select`,{"onUpdate:modelValue":s[0]||=e=>J.provider=e,class:`w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500`},[...s[16]||=[u(`option`,{value:`amap`},`🗺️ 高德地图 (AMap)`,-1),u(`option`,{value:`bmap`},`📍 百度地图 (BMap)`,-1)]],512),[[p,J.provider]])]),J.provider===`amap`?(a(),o(e,{key:0},[u(`div`,null,[s[18]||=u(`label`,{class:`text-xs text-gray-500 block mb-1`},`API Key (Key)`,-1),h(u(`input`,{"onUpdate:modelValue":s[1]||=e=>J.key=e,class:`w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500`,placeholder:`高德地图 Key`},null,512),[[r,J.key]])]),u(`div`,null,[s[19]||=u(`label`,{class:`text-xs text-gray-500 block mb-1`},`安全密钥 (Security Code)`,-1),h(u(`input`,{"onUpdate:modelValue":s[2]||=e=>J.securityCode=e,type:`password`,class:`w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500`,placeholder:`高德地图安全密钥`},null,512),[[r,J.securityCode]])])],64)):i(``,!0),J.provider===`bmap`?(a(),o(`div`,oe,[s[20]||=u(`label`,{class:`text-xs text-gray-500 block mb-1`},`百度地图 AK`,-1),h(u(`input`,{"onUpdate:modelValue":s[3]||=e=>J.key=e,class:`w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500`,placeholder:`百度地图 AK`},null,512),[[r,J.key]])])):i(``,!0),u(`div`,se,[u(`div`,null,[s[21]||=u(`label`,{class:`text-xs text-gray-500 block mb-1`},`默认经度`,-1),h(u(`input`,{"onUpdate:modelValue":s[4]||=e=>J.lng=e,type:`number`,step:`0.0001`,class:`w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500`},null,512),[[r,J.lng,void 0,{number:!0}]])]),u(`div`,null,[s[22]||=u(`label`,{class:`text-xs text-gray-500 block mb-1`},`默认纬度`,-1),h(u(`input`,{"onUpdate:modelValue":s[5]||=e=>J.lat=e,type:`number`,step:`0.0001`,class:`w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500`},null,512),[[r,J.lat,void 0,{number:!0}]])]),u(`div`,null,[s[23]||=u(`label`,{class:`text-xs text-gray-500 block mb-1`},`默认缩放`,-1),h(u(`input`,{"onUpdate:modelValue":s[6]||=e=>J.zoom=e,type:`number`,min:`3`,max:`18`,class:`w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500`},null,512),[[r,J.zoom,void 0,{number:!0}]])])]),u(`button`,{class:`w-full py-2 bg-blue-600 text-white text-sm rounded-lg hover:bg-blue-700`,onClick:pe},`保存地图配置`),Y.value?(a(),o(`div`,{key:2,class:_([`text-sm`,X.value?`text-green-600`:`text-red-500`])},v(Y.value),3)):i(``,!0)])):i(``,!0),b.value===`ai`?(a(),o(`div`,ce,[u(`div`,le,[s[25]||=u(`h3`,{class:`font-semibold text-sm text-gray-700 mb-3`},`Embedding Provider`,-1),u(`div`,j,[u(`button`,{class:_([`px-4 py-1.5 text-sm rounded-md transition-colors`,S.value===`ollama`?`bg-white text-blue-600 shadow-sm font-medium`:`text-gray-500 hover:text-gray-700`]),onClick:s[7]||=e=>S.value=`ollama`},`🦙 Ollama (本地)`,2),u(`button`,{class:_([`px-4 py-1.5 text-sm rounded-md transition-colors`,S.value===`deepseek`?`bg-white text-blue-600 shadow-sm font-medium`:`text-gray-500 hover:text-gray-700`]),onClick:s[8]||=e=>S.value=`deepseek`},`🧠 DeepSeek (云端)`,2)])]),S.value===`ollama`?(a(),o(`div`,M,[s[33]||=u(`h3`,{class:`font-semibold text-sm text-gray-700`},`Ollama 本地 Embedding`,-1),u(`div`,N,[u(`div`,null,[s[26]||=u(`label`,{class:`text-xs text-gray-500 block mb-1`},`Base URL`,-1),h(u(`input`,{"onUpdate:modelValue":s[9]||=e=>C.value=e,class:`w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500`,placeholder:`http://localhost:11434`},null,512),[[r,C.value]])]),u(`div`,null,[s[28]||=u(`label`,{class:`text-xs text-gray-500 block mb-1`},`Model`,-1),h(u(`select`,{"onUpdate:modelValue":s[10]||=e=>w.value=e,class:`w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500`},[...s[27]||=[u(`option`,{value:`nomic-embed-text`},`nomic-embed-text (通用, 768维)`,-1),u(`option`,{value:`mxbai-embed-large`},`mxbai-embed-large (中文优化, 1024维)`,-1),u(`option`,{value:`bge-m3`},`bge-m3 (多语言, 1024维)`,-1)]],512),[[p,w.value]]),s[29]||=u(`p`,{class:`text-xs text-gray-400 mt-1`},`推荐 nomic-embed-text`,-1)])]),u(`div`,P,[h(u(`input`,{type:`checkbox`,"onUpdate:modelValue":s[11]||=e=>A.value=e,class:`w-4 h-4 rounded text-blue-600`},null,512),[[n,A.value]]),s[30]||=u(`label`,{class:`text-sm text-gray-600`},`启用 Ollama`,-1)]),u(`div`,F,[u(`div`,I,[s[31]||=u(`span`,{class:`text-xs font-medium text-gray-600`},`服务状态`,-1),u(`button`,{class:`px-3 py-1 text-xs bg-blue-600 text-white rounded-md hover:bg-blue-700 disabled:opacity-50`,disabled:q.value,onClick:me},v(q.value?`检测中...`:`🔄 检测连接`),9,L)]),u(`div`,R,[u(`div`,z,[u(`span`,{class:_(W.value===`ready`?`text-green-500`:W.value===`checking`?`text-yellow-500 animate-pulse`:`text-gray-300`)},`●`,2),u(`span`,B,`Daemon: `+v(W.value===`ready`?`运行中`:W.value===`checking`?`检测中...`:W.value===`error`?`不可达`:`未检测`),1)]),W.value===`ready`?(a(),o(`div`,V,[s[32]||=u(`span`,{class:`text-green-500`},`●`,-1),u(`span`,H,`模型已安装: `+v(G.value.join(`, `)),1)])):i(``,!0),W.value===`error`?(a(),o(`div`,U,v(K.value),1)):i(``,!0)])]),u(`button`,{class:`w-full py-2 bg-blue-600 text-white text-sm rounded-lg hover:bg-blue-700`,onClick:he},`保存 Ollama 配置`)])):i(``,!0),S.value===`deepseek`?(a(),o(`div`,ue,[s[40]||=u(`h3`,{class:`font-semibold text-sm text-gray-700`},`DeepSeek API`,-1),u(`div`,null,[s[34]||=u(`label`,{class:`text-xs text-gray-500 block mb-1`},`API Key`,-1),h(u(`input`,{"onUpdate:modelValue":s[12]||=e=>T.value=e,type:`password`,class:`w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500`,placeholder:`sk-...`},null,512),[[r,T.value]])]),u(`div`,de,[u(`div`,null,[s[35]||=u(`label`,{class:`text-xs text-gray-500 block mb-1`},`Base URL`,-1),h(u(`input`,{"onUpdate:modelValue":s[13]||=e=>E.value=e,class:`w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500`,placeholder:`https://api.deepseek.com`},null,512),[[r,E.value]]),s[36]||=u(`p`,{class:`text-xs text-gray-400 mt-1`},`Chat API: /chat/completions`,-1)]),u(`div`,null,[s[38]||=u(`label`,{class:`text-xs text-gray-500 block mb-1`},`Model`,-1),h(u(`select`,{"onUpdate:modelValue":s[14]||=e=>D.value=e,class:`w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500`},[...s[37]||=[u(`option`,{value:`deepseek-v4-flash`},`deepseek-v4-flash`,-1),u(`option`,{value:`deepseek-v4-pro`},`deepseek-v4-pro`,-1)]],512),[[p,D.value]])])]),u(`div`,fe,[h(u(`input`,{type:`checkbox`,"onUpdate:modelValue":s[15]||=e=>O.value=e,class:`w-4 h-4 rounded text-blue-600`},null,512),[[n,O.value]]),s[39]||=u(`label`,{class:`text-sm text-gray-600`},`启用 DeepSeek (LLM 降级 + AI 回复)`,-1)]),u(`button`,{class:`w-full py-2 bg-blue-600 text-white text-sm rounded-lg hover:bg-blue-700`,onClick:ge},`保存 DeepSeek 配置`)])):i(``,!0)])):i(``,!0),u(`div`,{class:`pt-4 border-t`},[u(`button`,{class:`px-4 py-2 text-sm text-red-600 border border-red-200 rounded-lg hover:bg-red-50 transition-colors`,onClick:ve},` 🔄 恢复默认设置 `)])]))}});export{W as default};
@@ -0,0 +1 @@
1
+ .fade-enter-active[data-v-245121c6],.fade-leave-active[data-v-245121c6]{transition:opacity .2s}.fade-enter-from[data-v-245121c6],.fade-leave-to[data-v-245121c6]{opacity:0}.fade-enter-active[data-v-ffaa2236],.fade-leave-active[data-v-ffaa2236]{transition:opacity .2s}.fade-enter-from[data-v-ffaa2236],.fade-leave-to[data-v-ffaa2236]{opacity:0}.fade-enter-active[data-v-fd03c6d7],.fade-leave-active[data-v-fd03c6d7]{transition:opacity .2s}.fade-enter-from[data-v-fd03c6d7],.fade-leave-to[data-v-fd03c6d7]{opacity:0}
@@ -0,0 +1 @@
1
+ import{A as e,B as t,E as n,F as r,G as i,I as a,J as o,K as s,M as c,N as l,P as u,Q as d,R as f,S as p,T as m,U as h,W as g,X as _,Y as v,Z as y,b,d as x,et as S,h as C,i as w,j as T,nt as E,r as D,v as O,y as k,z as A}from"./index-CTrnN2TM.js";import{t as j}from"./_plugin-vue_export-helper-S3RvzygF.js";var M={class:`bg-white rounded-lg border shadow-sm overflow-hidden`},N={class:`overflow-x-auto`},P={class:`w-full text-sm`},F={class:`bg-gray-50 text-xs text-gray-500 uppercase`},I={key:0,class:`px-3 py-2 text-left`},L={class:`divide-y`},ee={class:`px-3 py-2.5 font-mono text-xs text-gray-700`},te={class:`px-3 py-2.5 font-medium`},R={class:`px-3 py-2.5 font-mono text-xs text-gray-400`},z={class:`px-3 py-2.5`},B={class:`inline-flex items-center gap-1 text-xs`},V={class:`px-3 py-2.5 text-xs text-gray-500`},H={class:`px-3 py-2.5`},U={class:`px-3 py-2.5 text-xs text-gray-400`},W={key:0,class:`px-3 py-2.5`},G={class:`flex gap-1`},K=[`onClick`],q=[`onClick`],J=[`onClick`],Y=[`onClick`],X={key:0},Z=[`colspan`],Q=t({__name:`TBoxList`,props:{tboxes:{},showActions:{type:Boolean,default:!0}},emits:[`bind`,`unbind`,`settings`,`calibrate`],setup(t,{emit:n}){let o=t,u=n,d=x(),p=c(()=>{let e={};for(let t of o.tboxes){let n=d.getByTboxId(t.tbox_id);if(!n&&t.vin&&(n=d.getByVin(t.vin)),!n&&t.tbox_id){let e=t.tbox_id.slice(-8);n=d.vehicles.find(n=>n.vin?.includes(e)||n.tbox_id===t.tbox_id)}n?e[t.tbox_id]={plate_number:n.plate_number,vin:n.vin}:t.vin&&console.warn(`[TBoxList] 车辆查找失败: tbox=${t.tbox_id}, tbox.vin="${t.vin}", vehicles count=${d.vehicles.length}`)}return e});function m(e){return p.value[e]?.plate_number??`-`}function h(e){return p.value[e]?.vin||`-`}function g(e){return!e||e<=0?`-`:new Date(e).toLocaleString(`zh-CN`,{month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`})}function _(e){let t=e??-120;return t>-70?{bars:4,color:`text-green-500`}:t>-85?{bars:3,color:`text-green-400`}:t>-100?{bars:2,color:`text-yellow-500`}:{bars:1,color:`text-red-400`}}return(n,o)=>(i(),a(`div`,M,[l(`div`,N,[l(`table`,P,[l(`thead`,F,[l(`tr`,null,[o[0]||=l(`th`,{class:`px-3 py-2 text-left`},`TBox ID`,-1),o[1]||=l(`th`,{class:`px-3 py-2 text-left`},`绑定车辆`,-1),o[2]||=l(`th`,{class:`px-3 py-2 text-left`},`VIN`,-1),o[3]||=l(`th`,{class:`px-3 py-2 text-left`},`在线`,-1),o[4]||=l(`th`,{class:`px-3 py-2 text-left`},`固件版本`,-1),o[5]||=l(`th`,{class:`px-3 py-2 text-left`},`信号`,-1),o[6]||=l(`th`,{class:`px-3 py-2 text-left`},`最后上线`,-1),t.showActions===!1?r(``,!0):(i(),a(`th`,I,`操作`))])]),l(`tbody`,L,[(i(!0),a(e,null,s(t.tboxes,e=>(i(),a(`tr`,{key:e.tbox_id,class:`hover:bg-gray-50`},[l(`td`,ee,E(e.tbox_id),1),l(`td`,te,E(m(e.tbox_id)),1),l(`td`,R,E((h(e.tbox_id)||`-`).slice(-8)),1),l(`td`,z,[l(`span`,B,[l(`span`,{class:S([`w-2 h-2 rounded-full`,e.online?`bg-green-500`:`bg-gray-300`])},null,2),f(` `+E(e.online?`在线`:`离线`),1)])]),l(`td`,V,E(e.fw_version),1),l(`td`,H,[l(`span`,{class:S([`text-xs`,_(e.signal_strength).color])},E(`█`.repeat(_(e.signal_strength).bars))+E(`░`.repeat(4-_(e.signal_strength).bars))+` `+E(e.signal_strength)+` dBm `,3)]),l(`td`,U,E(g(e.last_login)),1),t.showActions===!1?r(``,!0):(i(),a(`td`,W,[l(`div`,G,[e.vin?(i(),a(`button`,{key:1,class:`px-2 py-0.5 text-xs rounded bg-red-50 text-red-500 hover:bg-red-100`,onClick:t=>u(`unbind`,e.tbox_id)},` 解绑 `,8,q)):(i(),a(`button`,{key:0,class:`px-2 py-0.5 text-xs rounded bg-blue-50 text-blue-600 hover:bg-blue-100`,onClick:t=>u(`bind`,e.tbox_id)},` 绑定 `,8,K)),l(`button`,{class:`px-2 py-0.5 text-xs rounded bg-gray-100 text-gray-600 hover:bg-gray-200`,onClick:t=>u(`settings`,e.tbox_id)},` 设置 `,8,J),l(`button`,{class:`px-2 py-0.5 text-xs rounded bg-purple-50 text-purple-600 hover:bg-purple-100`,onClick:t=>u(`calibrate`,e.tbox_id)},` 标定 `,8,Y)])]))]))),128)),t.tboxes.length===0?(i(),a(`tr`,X,[l(`td`,{colspan:t.showActions===!1?7:8,class:`px-4 py-8 text-center text-gray-400`},` 暂无 TBox 设备 `,8,Z)])):r(``,!0)])])])]))}}),ne={key:0,class:`fixed inset-0 z-50 flex items-center justify-center`},re={class:`relative bg-white rounded-xl shadow-2xl max-w-sm w-full mx-4 p-6`},ie={class:`space-y-3`},ae=[`value`],oe={class:`flex gap-1 bg-gray-100 rounded-lg p-1`},se={class:`text-xs text-gray-500 block mb-1`},ce={class:`text-gray-300 ml-1`},le=[`value`],ue={key:0,class:`text-xs text-amber-600 mt-1`},de=[`disabled`],fe={key:2,class:`text-sm text-red-500 bg-red-50 rounded-lg px-3 py-2`},pe={class:`flex justify-end gap-3 mt-6`},me=[`disabled`],he=j(t({__name:`BindDialog`,props:{tboxId:{},visible:{type:Boolean}},emits:[`close`,`bound`],setup(t,{emit:h}){let g=t,y=h,w=x(),D=d(``),O=d(``),j=d(!1),M=d(``),N=d(!1),P=c(()=>w.archiveVehicles.filter(e=>!e.tbox_id||e.tbox_id===``));o(D,e=>{if(!e||N.value)return;let t=w.getByVin(e);t&&(O.value=t.plate_number||``)}),o(()=>g.visible,e=>{e&&(D.value=``,O.value=``,M.value=``,N.value=!1)});async function F(){M.value=``;let e=D.value.trim(),t=O.value.trim();if(!e){M.value=`请选择车辆或输入 VIN`;return}if(!t){M.value=`车牌号不能为空`;return}j.value=!0;try{let n=await C.get(g.tboxId);if(!n){M.value=`TBox 设备不存在`,j.value=!1;return}let r=w.getByVin(e);if(n.vin=e,n.updated_at=Date.now(),await C.set(n),r)r.tbox_id=g.tboxId,r.plate_number=t,r.bind_time=Date.now(),r.updated_at=Date.now(),await w.upsert(r);else{await w.bindTbox(e,g.tboxId);let n=w.getByVin(e);n&&(n.plate_number=t,n.bind_time=Date.now(),n.updated_at=Date.now(),await w.upsert(n))}let i=`TEMP_`+g.tboxId;w.getByVin(i)&&(await w.remove(i),console.log(`[BindDialog] 已清理临时车辆:`,i)),I(g.tboxId,e,t).catch(e=>{console.warn(`[BindDialog] 后端同步失败(本地已保存):`,e)}),y(`bound`),y(`close`)}catch(e){M.value=`绑定失败: ${e.message}`}finally{j.value=!1}}async function I(e,t,n){try{await k.update(e,{vin:t})}catch{await k.create({tbox_id:e,vin:t,online:1,last_login:Date.now(),created_at:Date.now(),updated_at:Date.now()})}try{await b.update(t,{tbox_id:e,plate_number:n})}catch{let r=Date.now();await b.create({vin:t,tbox_id:e,plate_number:n,vehicle_type:`搅拌车`,status:`idle`,created_at:r,updated_at:r})}}return(o,c)=>(i(),u(T,{to:`body`},[A(p,{name:`fade`},{default:v(()=>[t.visible?(i(),a(`div`,ne,[l(`div`,{class:`absolute inset-0 bg-black/40`,onClick:c[0]||=e=>y(`close`)}),l(`div`,re,[c[14]||=l(`h3`,{class:`text-lg font-semibold mb-4`},`绑定 TBox 设备`,-1),l(`div`,ie,[l(`div`,null,[c[8]||=l(`label`,{class:`text-xs text-gray-500 block mb-1`},`TBox ID`,-1),l(`input`,{value:t.tboxId,disabled:``,class:`w-full border rounded-lg px-3 py-2 text-sm bg-gray-50 text-gray-500`},null,8,ae)]),l(`div`,oe,[l(`button`,{class:S([`flex-1 px-3 py-1 text-xs rounded-md transition-colors`,N.value?`text-gray-500`:`bg-white text-blue-600 shadow-sm font-medium`]),onClick:c[1]||=e=>N.value=!1},` 从列表选择 `,2),l(`button`,{class:S([`flex-1 px-3 py-1 text-xs rounded-md transition-colors`,N.value?`bg-white text-blue-600 shadow-sm font-medium`:`text-gray-500`]),onClick:c[2]||=e=>N.value=!0},` 手动输入 `,2)]),N.value?(i(),a(e,{key:1},[l(`div`,null,[c[12]||=l(`label`,{class:`text-xs text-gray-500 block mb-1`},`车辆 VIN (17位)`,-1),_(l(`input`,{"onUpdate:modelValue":c[5]||=e=>D.value=e,placeholder:`LSVXXXXXXXXXXXX`,maxlength:`17`,class:`w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500`},null,512),[[n,D.value]])]),l(`div`,null,[c[13]||=l(`label`,{class:`text-xs text-gray-500 block mb-1`},`车牌号`,-1),_(l(`input`,{"onUpdate:modelValue":c[6]||=e=>O.value=e,placeholder:`沪A·88888`,class:`w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500`},null,512),[[n,O.value]])])],64)):(i(),a(e,{key:0},[l(`div`,null,[l(`label`,se,[c[9]||=f(` 选择车辆 `,-1),l(`span`,ce,`(`+E(P.value.length)+` 台可用)`,1)]),_(l(`select`,{"onUpdate:modelValue":c[3]||=e=>D.value=e,class:`w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500`},[c[10]||=l(`option`,{value:``,disabled:``},`-- 请选择车辆 --`,-1),(i(!0),a(e,null,s(P.value,e=>(i(),a(`option`,{key:e.vin,value:e.vin},E(e.plate_number||`未上牌`)+` — `+E(e.vin.slice(-6))+` (`+E(e.vehicle_type)+`) `,9,le))),128))],512),[[m,D.value]]),P.value.length===0?(i(),a(`p`,ue,` ⚠️ 没有未绑定的车辆,请先在「车辆档案」中创建车辆,或切换到手动输入模式。 `)):r(``,!0)]),l(`div`,null,[c[11]||=l(`label`,{class:`text-xs text-gray-500 block mb-1`},`车牌号`,-1),_(l(`input`,{"onUpdate:modelValue":c[4]||=e=>O.value=e,disabled:!D.value,placeholder:`选择车辆后自动回填`,class:`w-full border rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 disabled:bg-gray-50 disabled:text-gray-400`},null,8,de),[[n,O.value]])])],64)),M.value?(i(),a(`div`,fe,E(M.value),1)):r(``,!0)]),l(`div`,pe,[l(`button`,{class:`px-4 py-2 text-sm text-gray-600 bg-gray-100 rounded-lg hover:bg-gray-200`,onClick:c[7]||=e=>y(`close`)},` 取消 `),l(`button`,{class:`px-4 py-2 text-sm text-white bg-blue-600 rounded-lg hover:bg-blue-700 disabled:opacity-50`,disabled:j.value,onClick:F},E(j.value?`绑定中...`:`确认绑定`),9,me)])])])):r(``,!0)]),_:1})]))}}),[[`__scopeId`,`data-v-245121c6`]]),ge={key:0,class:`fixed inset-0 z-50 flex items-center justify-center`},_e={class:`relative bg-white rounded-xl shadow-2xl max-w-lg w-full mx-4 max-h-[80vh] overflow-hidden flex flex-col`},ve={class:`px-6 pt-4 pb-2 border-b`},ye={class:`flex items-center justify-between mb-2`},be={class:`flex gap-1`},xe=[`onClick`],Se={class:`p-4 space-y-3 overflow-y-auto flex-1`},Ce={class:`grid grid-cols-2 gap-3`},we={class:`space-y-3`},Te={class:`grid grid-cols-2 gap-3`},Ee={class:`space-y-3`},De={key:3,class:`grid grid-cols-2 gap-3`},$=j(t({__name:`SettingsDialog`,props:{tboxId:{},visible:{type:Boolean}},emits:[`close`,`sendCommand`],setup(t,{emit:o}){let c=o,f=d(`device`),m=[{key:`device`,label:`📡 设备参数`},{key:`comm`,label:`📶 通信参数`},{key:`alarm`,label:`🔔 报警阈值`},{key:`control`,label:`🎮 远程控制`}],h=y({gpsInterval:10,distanceInterval:50,drumInterval:5,canEnable:!1}),g=y({mqttServer:`121.40.192.196`,mqttPort:1883,keepalive:60,reconnectInterval:30}),b=y({drumStopThreshold:300,overspeedThreshold:80,fatigueThreshold:14400});function x(e,t){c(`sendCommand`,e,t)}return(o,d)=>(i(),u(T,{to:`body`},[A(p,{name:`fade`},{default:v(()=>[t.visible?(i(),a(`div`,ge,[l(`div`,{class:`absolute inset-0 bg-black/40`,onClick:d[0]||=e=>c(`close`)}),l(`div`,_e,[l(`div`,ve,[l(`div`,ye,[d[19]||=l(`h3`,{class:`font-semibold text-gray-800`},`TBox 设置`,-1),l(`button`,{class:`text-gray-400 hover:text-gray-600`,onClick:d[1]||=e=>c(`close`)},`✕`)]),l(`div`,be,[(i(),a(e,null,s(m,e=>l(`button`,{key:e.key,class:S([`px-3 py-1 text-xs rounded-md transition-colors`,f.value===e.key?`bg-blue-100 text-blue-700 font-medium`:`text-gray-500 hover:bg-gray-100`]),onClick:t=>f.value=e.key},E(e.label),11,xe)),64))])]),l(`div`,Se,[f.value===`device`?(i(),a(e,{key:0},[d[23]||=l(`div`,{class:`text-xs text-gray-400 mb-2`},`GPS 参数`,-1),l(`div`,Ce,[l(`div`,null,[d[20]||=l(`label`,{class:`text-xs text-gray-500`},`上报间隔 (秒)`,-1),_(l(`input`,{"onUpdate:modelValue":d[2]||=e=>h.gpsInterval=e,type:`number`,class:`w-full border rounded px-3 py-1.5 text-sm`},null,512),[[n,h.gpsInterval,void 0,{number:!0}]])]),l(`div`,null,[d[21]||=l(`label`,{class:`text-xs text-gray-500`},`距离触发 (米)`,-1),_(l(`input`,{"onUpdate:modelValue":d[3]||=e=>h.distanceInterval=e,type:`number`,class:`w-full border rounded px-3 py-1.5 text-sm`},null,512),[[n,h.distanceInterval,void 0,{number:!0}]])])]),d[24]||=l(`div`,{class:`text-xs text-gray-400 mt-3 mb-2`},`搅拌筒参数`,-1),l(`div`,null,[d[22]||=l(`label`,{class:`text-xs text-gray-500`},`上报间隔 (秒)`,-1),_(l(`input`,{"onUpdate:modelValue":d[4]||=e=>h.drumInterval=e,type:`number`,class:`w-full border rounded px-3 py-1.5 text-sm`},null,512),[[n,h.drumInterval,void 0,{number:!0}]])]),l(`button`,{class:`mt-3 px-4 py-2 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700`,onClick:d[5]||=e=>x(`update_config`,{...h})},` 下发配置 `)],64)):r(``,!0),f.value===`comm`?(i(),a(e,{key:1},[l(`div`,we,[l(`div`,null,[d[25]||=l(`label`,{class:`text-xs text-gray-500`},`MQTT 服务器`,-1),_(l(`input`,{"onUpdate:modelValue":d[6]||=e=>g.mqttServer=e,class:`w-full border rounded px-3 py-1.5 text-sm`},null,512),[[n,g.mqttServer]])]),l(`div`,null,[d[26]||=l(`label`,{class:`text-xs text-gray-500`},`端口`,-1),_(l(`input`,{"onUpdate:modelValue":d[7]||=e=>g.mqttPort=e,type:`number`,class:`w-full border rounded px-3 py-1.5 text-sm`},null,512),[[n,g.mqttPort,void 0,{number:!0}]])]),l(`div`,Te,[l(`div`,null,[d[27]||=l(`label`,{class:`text-xs text-gray-500`},`心跳间隔 (秒)`,-1),_(l(`input`,{"onUpdate:modelValue":d[8]||=e=>g.keepalive=e,type:`number`,class:`w-full border rounded px-3 py-1.5 text-sm`},null,512),[[n,g.keepalive,void 0,{number:!0}]])]),l(`div`,null,[d[28]||=l(`label`,{class:`text-xs text-gray-500`},`重连间隔 (秒)`,-1),_(l(`input`,{"onUpdate:modelValue":d[9]||=e=>g.reconnectInterval=e,type:`number`,class:`w-full border rounded px-3 py-1.5 text-sm`},null,512),[[n,g.reconnectInterval,void 0,{number:!0}]])])])]),l(`button`,{class:`mt-3 px-4 py-2 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700`,onClick:d[10]||=e=>x(`update_comm_config`,{...g})},` 下发通信配置 `)],64)):r(``,!0),f.value===`alarm`?(i(),a(e,{key:2},[l(`div`,Ee,[l(`div`,null,[d[29]||=l(`label`,{class:`text-xs text-gray-500`},`停筒告警阈值 (秒)`,-1),_(l(`input`,{"onUpdate:modelValue":d[11]||=e=>b.drumStopThreshold=e,type:`number`,class:`w-full border rounded px-3 py-1.5 text-sm`},null,512),[[n,b.drumStopThreshold,void 0,{number:!0}]])]),l(`div`,null,[d[30]||=l(`label`,{class:`text-xs text-gray-500`},`超速阈值 (km/h)`,-1),_(l(`input`,{"onUpdate:modelValue":d[12]||=e=>b.overspeedThreshold=e,type:`number`,class:`w-full border rounded px-3 py-1.5 text-sm`},null,512),[[n,b.overspeedThreshold,void 0,{number:!0}]])]),l(`div`,null,[d[31]||=l(`label`,{class:`text-xs text-gray-500`},`疲劳驾驶阈值 (秒)`,-1),_(l(`input`,{"onUpdate:modelValue":d[13]||=e=>b.fatigueThreshold=e,type:`number`,class:`w-full border rounded px-3 py-1.5 text-sm`},null,512),[[n,b.fatigueThreshold,void 0,{number:!0}]])])]),l(`button`,{class:`mt-3 px-4 py-2 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700`,onClick:d[14]||=e=>x(`update_alarm_config`,{...b})},` 下发报警配置 `)],64)):r(``,!0),f.value===`control`?(i(),a(`div`,De,[l(`button`,{class:`p-3 border rounded-lg text-sm hover:bg-gray-50 text-left`,onClick:d[15]||=e=>x(`reboot`,{delay_seconds:5})},[...d[32]||=[l(`div`,{class:`text-lg mb-1`},`🔄`,-1),l(`div`,{class:`font-medium`},`重启设备`,-1),l(`div`,{class:`text-xs text-gray-400`},`5秒后重启`,-1)]]),l(`button`,{class:`p-3 border rounded-lg text-sm hover:bg-gray-50 text-left`,onClick:d[16]||=e=>x(`reset_factory`,{})},[...d[33]||=[l(`div`,{class:`text-lg mb-1`},`⚠️`,-1),l(`div`,{class:`font-medium`},`恢复出厂`,-1),l(`div`,{class:`text-xs text-gray-400`},`清除所有配置`,-1)]]),l(`button`,{class:`p-3 border rounded-lg text-sm hover:bg-gray-50 text-left`,onClick:d[17]||=e=>x(`clear_data`,{data_type:`all`})},[...d[34]||=[l(`div`,{class:`text-lg mb-1`},`🗑️`,-1),l(`div`,{class:`font-medium`},`清除数据`,-1),l(`div`,{class:`text-xs text-gray-400`},`清除本地数据`,-1)]]),l(`button`,{class:`p-3 border rounded-lg text-sm hover:bg-gray-50 text-left`,onClick:d[18]||=e=>x(`query_status`,{})},[...d[35]||=[l(`div`,{class:`text-lg mb-1`},`📊`,-1),l(`div`,{class:`font-medium`},`查询状态`,-1),l(`div`,{class:`text-xs text-gray-400`},`获取设备详情`,-1)]])])):r(``,!0)])])])):r(``,!0)]),_:1})]))}}),[[`__scopeId`,`data-v-ffaa2236`]]),Oe={key:0,class:`fixed inset-0 z-50 flex items-center justify-center`},ke={class:`relative bg-white rounded-xl shadow-2xl max-w-md w-full mx-4 p-6`},Ae={class:`text-lg font-semibold mb-4`},je={class:`space-y-3`},Me={class:`grid grid-cols-2 gap-3`},Ne={class:`grid grid-cols-2 gap-3`},Pe={class:`grid grid-cols-2 gap-3`},Fe={key:0,class:`mt-3 px-3 py-2 bg-green-50 border border-green-200 rounded-lg text-sm text-green-700 flex items-center gap-2`},Ie=j(t({__name:`CalibrateDialog`,props:{tboxId:{},visible:{type:Boolean}},emits:[`close`,`calibrate`],setup(e,{emit:t}){let o=t,s=d(0),c=d(10),m=d(0),h=d(100),g=d(0),y=d(0),b=d(!1);function x(){o(`calibrate`,{speed_zero:s.value,speed_full:c.value,level_zero:m.value,level_full:h.value,tilt_zero:g.value,temp_offset:y.value}),b.value=!0}function S(){b.value=!1,o(`close`)}return(t,d)=>(i(),u(T,{to:`body`},[A(p,{name:`fade`},{default:v(()=>[e.visible?(i(),a(`div`,Oe,[l(`div`,{class:`absolute inset-0 bg-black/40`,onClick:d[0]||=e=>o(`close`)}),l(`div`,ke,[l(`h3`,Ae,`🔧 传感器标定 — `+E(e.tboxId),1),l(`div`,je,[d[13]||=l(`div`,{class:`text-xs text-gray-400 font-medium`},`搅拌筒转速 (r/min)`,-1),l(`div`,Me,[l(`div`,null,[d[7]||=l(`label`,{class:`text-xs text-gray-500`},`零点 (静止)`,-1),_(l(`input`,{"onUpdate:modelValue":d[1]||=e=>s.value=e,type:`number`,step:`0.1`,class:`w-full border rounded-lg px-3 py-2 text-sm`},null,512),[[n,s.value,void 0,{number:!0}]])]),l(`div`,null,[d[8]||=l(`label`,{class:`text-xs text-gray-500`},`满点 (最高转速)`,-1),_(l(`input`,{"onUpdate:modelValue":d[2]||=e=>c.value=e,type:`number`,step:`0.1`,class:`w-full border rounded-lg px-3 py-2 text-sm`},null,512),[[n,c.value,void 0,{number:!0}]])])]),d[14]||=l(`div`,{class:`text-xs text-gray-400 font-medium mt-2`},`料位 (%)`,-1),l(`div`,Ne,[l(`div`,null,[d[9]||=l(`label`,{class:`text-xs text-gray-500`},`零点 (空筒)`,-1),_(l(`input`,{"onUpdate:modelValue":d[3]||=e=>m.value=e,type:`number`,class:`w-full border rounded-lg px-3 py-2 text-sm`},null,512),[[n,m.value,void 0,{number:!0}]])]),l(`div`,null,[d[10]||=l(`label`,{class:`text-xs text-gray-500`},`满点 (满载)`,-1),_(l(`input`,{"onUpdate:modelValue":d[4]||=e=>h.value=e,type:`number`,class:`w-full border rounded-lg px-3 py-2 text-sm`},null,512),[[n,h.value,void 0,{number:!0}]])])]),d[15]||=l(`div`,{class:`text-xs text-gray-400 font-medium mt-2`},`其他`,-1),l(`div`,Pe,[l(`div`,null,[d[11]||=l(`label`,{class:`text-xs text-gray-500`},`倾角零点 (°)`,-1),_(l(`input`,{"onUpdate:modelValue":d[5]||=e=>g.value=e,type:`number`,step:`0.1`,class:`w-full border rounded-lg px-3 py-2 text-sm`},null,512),[[n,g.value,void 0,{number:!0}]])]),l(`div`,null,[d[12]||=l(`label`,{class:`text-xs text-gray-500`},`温度偏移 (°C)`,-1),_(l(`input`,{"onUpdate:modelValue":d[6]||=e=>y.value=e,type:`number`,step:`0.1`,class:`w-full border rounded-lg px-3 py-2 text-sm`},null,512),[[n,y.value,void 0,{number:!0}]])])]),d[16]||=l(`p`,{class:`text-xs text-gray-400 bg-yellow-50 rounded p-2 mt-2`},` ⚠️ 标定前请确保搅拌筒完全静止,空筒状态下标定料位零点 `,-1)]),l(`div`,{class:`flex justify-end gap-3 mt-6`},[l(`button`,{class:`px-4 py-2 text-sm text-gray-600 bg-gray-100 rounded-lg hover:bg-gray-200`,onClick:S},`取消`),l(`button`,{class:`px-4 py-2 text-sm text-white bg-blue-600 rounded-lg hover:bg-blue-700`,onClick:x},`保存标定`)]),A(p,{name:`fade`},{default:v(()=>[b.value?(i(),a(`div`,Fe,[...d[17]||=[l(`span`,null,`✅`,-1),f(` 标定数据已提交,命令将在设备在线时自动下发 `,-1)]])):r(``,!0)]),_:1})])])):r(``,!0)]),_:1})]))}}),[[`__scopeId`,`data-v-fd03c6d7`]]),Le={class:`space-y-4`},Re={class:`flex gap-1 bg-gray-100 rounded-lg p-1 w-fit`},ze=t({__name:`TBoxManager`,setup(e){let t=x(),n=d([]),r=d(`all`),o=d(``),s=d(!1),u=d(``),f=d(!1),p=d(``),m=d(!1),_=c(()=>r.value===`unbound`?n.value.filter(e=>!e.vin):n.value),v=null;h(async()=>{await t.load(),await y(),v=setInterval(T,3e3)}),g(()=>{v&&clearInterval(v)});async function y(){try{let e=await O(`/tboxes`);if(!e.ok||!Array.isArray(e.data))return;let t=await C.getAll(),r=new Map;for(let e of t)r.set(e.tbox_id,e);n.value=e.data.map(e=>{let t=r.get(e.tbox_id);return{tbox_id:e.tbox_id,vin:e.vin??null,online:t?.online??!1,last_login:t?.last_login??e.last_login??Date.now(),last_gps:t?.last_gps??e.last_gps??null,fw_version:t?.fw_version??e.fw_version??`-`,signal_strength:t?.signal_strength??e.signal_strength??0,created_at:e.created_at??Date.now(),updated_at:e.updated_at??Date.now()}})}catch{n.value=await C.getAll()}}async function T(){try{let e=await C.getAll(),t=new Map;for(let n of e)t.set(n.tbox_id,n);for(let e of n.value){let n=t.get(e.tbox_id);n&&(e.online!==n.online||e.last_gps!==n.last_gps||e.signal_strength!==n.signal_strength||e.fw_version!==n.fw_version)&&(e.online=n.online,e.last_gps=n.last_gps,e.signal_strength=n.signal_strength,e.fw_version=n.fw_version)}for(let[e,r]of t)n.value.find(t=>t.tbox_id===e)||n.value.push({...r})}catch{}}function j(e){o.value=e,s.value=!0}function M(e){u.value=e,f.value=!0}async function N(e){let r=n.value.find(t=>t.tbox_id===e);if(!r||!r.vin||!confirm(`确认解绑 TBox ${e} 与车辆 ${r.vin.slice(-6)}?`))return;let i=r.vin;try{await k.update(e,{vin:null}),await b.update(i,{tbox_id:``})}catch(e){console.warn(`[TBox] unbind API failed:`,e)}r.vin=null,r.updated_at=Date.now();let a=t.getByVin(i);a&&(a.tbox_id=``,await t.upsert(a))}async function P(e,t){try{await w.publish(D.CMD(u.value),{tbox_id:u.value,command:e,params:t,timestamp:Date.now()},1),window.alert(`✅ 命令 "${e}" 已下发`)}catch{window.alert(`❌ 命令下发失败,MQTT 未连接`)}}function F(e){p.value=e,m.value=!0}async function I(e){try{await w.publish(D.CMD(p.value),{tbox_id:p.value,command:`update_config`,params:{drum_sensor_config:e},timestamp:Date.now()},1)}catch{}}async function L(){await y(),await t.load()}return(e,t)=>(i(),a(`div`,Le,[t[5]||=l(`h1`,{class:`text-2xl font-bold`},`📡 TBox 管理`,-1),l(`div`,Re,[l(`button`,{class:S([`px-4 py-1.5 text-sm rounded-md transition-colors`,r.value===`all`?`bg-white text-blue-600 shadow-sm font-medium`:`text-gray-500`]),onClick:t[0]||=e=>r.value=`all`},` 全部设备 (`+E(n.value.length)+`) `,3),l(`button`,{class:S([`px-4 py-1.5 text-sm rounded-md transition-colors`,r.value===`unbound`?`bg-white text-blue-600 shadow-sm font-medium`:`text-gray-500`]),onClick:t[1]||=e=>r.value=`unbound`},` 未绑定 (`+E(n.value.filter(e=>!e.vin).length)+`) `,3)]),A(Q,{tboxes:_.value,onBind:j,onUnbind:N,onSettings:M,onCalibrate:F},null,8,[`tboxes`]),A(he,{tboxId:o.value,visible:s.value,onClose:t[2]||=e=>s.value=!1,onBound:L},null,8,[`tboxId`,`visible`]),A($,{tboxId:u.value,visible:f.value,onClose:t[3]||=e=>f.value=!1,onSendCommand:P},null,8,[`tboxId`,`visible`]),A(Ie,{tboxId:p.value,visible:m.value,onClose:t[4]||=e=>m.value=!1,onCalibrate:I},null,8,[`tboxId`,`visible`])]))}});export{ze as default};
@@ -0,0 +1 @@
1
+ import{$ as e,A as t,B as n,E as r,F as i,G as a,I as o,K as s,M as c,N as l,Q as u,R as d,T as f,U as p,X as m,_ as h,et as ee,g,k as _,nt as v,w as y}from"./index-CTrnN2TM.js";var te={class:`space-y-4`},b={class:`flex gap-3 items-center`},x=[`value`],S={class:`bg-white rounded-lg border shadow-sm overflow-hidden`},C={class:`overflow-x-auto`},w={class:`w-full text-sm`},ne={class:`divide-y`},re={key:0},ie={class:`py-2.5 px-4 text-gray-400`},ae={class:`py-2.5 px-4 font-medium text-gray-700`},oe={class:`py-2.5 px-4`},se={class:`text-xs rounded-full px-2 py-0.5 bg-blue-50 text-blue-700`},ce={class:`py-2.5 px-4 text-gray-500`},T={class:`py-2.5 px-4 text-gray-400 text-xs`},E={class:`py-2.5 px-4 text-center`},D={class:`py-2.5 px-4 text-center`},O={class:`flex justify-center gap-2`},k=[`onClick`],A=[`onClick`],j={class:`bg-white rounded-xl shadow-2xl w-full max-w-md p-6`},M={class:`text-lg font-semibold mb-4`},N=[`disabled`],P={class:`text-xs text-gray-500`},F={key:0,class:`text-red-400`},I={key:1,class:`text-gray-300`},L=[`value`],R={class:`flex gap-4 mt-1`},z={class:`flex items-center gap-1 text-sm`},le={class:`flex items-center gap-1 text-sm`},B=n({__name:`UserManager`,setup(n){let B=h(),V=u([]),H=u(!1),U=u(null),W=u(``),G=u(``),K=u(``),q=u(``),J=u(``),Y=u(`driver`),X=u(`enabled`),Z=c(()=>{let e=V.value;if(W.value&&(e=e.filter(e=>e.role===W.value)),G.value){let t=G.value.toLowerCase();e=e.filter(e=>e.username.toLowerCase().includes(t)||e.phone.includes(t))}return e});async function Q(){V.value=await B.getUsers()}function ue(){U.value=null,K.value=``,q.value=``,J.value=``,Y.value=`driver`,X.value=`enabled`,H.value=!0}function de(e){U.value={...e},K.value=e.username,q.value=``,J.value=e.phone,Y.value=e.role,X.value=e.status,H.value=!0}function $(){H.value=!1,U.value=null}async function fe(){if(K.value.trim()){if(U.value){let e={phone:J.value,role:Y.value,status:X.value};q.value&&(e.password=q.value),await B.updateUser(U.value.id,e)}else await B.register(K.value.trim(),q.value||`123456`,J.value,Y.value);await Q(),$()}}async function pe(e){confirm(`确定删除用户 "${e.username}" 吗?此操作不可撤销。`)&&(await B.deleteUser(e.id),await Q())}function me(e){return new Date(e).toLocaleDateString(`zh-CN`)}return p(Q),(n,c)=>(a(),o(`div`,te,[l(`div`,{class:`flex items-center justify-between`},[c[8]||=l(`h1`,{class:`text-2xl font-bold`},`👥 用户管理`,-1),l(`button`,{class:`px-4 py-2 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors`,onClick:ue},` + 新建用户 `)]),l(`div`,b,[m(l(`input`,{"onUpdate:modelValue":c[0]||=e=>G.value=e,type:`text`,placeholder:`搜索用户名/手机号...`,class:`border rounded-lg px-3 py-1.5 text-sm w-48`},null,512),[[r,G.value]]),m(l(`select`,{"onUpdate:modelValue":c[1]||=e=>W.value=e,class:`border rounded-lg px-3 py-1.5 text-sm`},[c[9]||=l(`option`,{value:``},`全部角色`,-1),(a(!0),o(t,null,s(e(g),(e,t)=>(a(),o(`option`,{key:t,value:t},v(e),9,x))),128))],512),[[f,W.value]])]),l(`div`,S,[l(`div`,C,[l(`table`,w,[c[11]||=l(`thead`,{class:`text-gray-400 border-b bg-gray-50`},[l(`tr`,null,[l(`th`,{class:`text-left py-2.5 px-4`},`序号`),l(`th`,{class:`text-left py-2.5 px-4`},`用户名`),l(`th`,{class:`text-left py-2.5 px-4`},`角色`),l(`th`,{class:`text-left py-2.5 px-4`},`手机号`),l(`th`,{class:`text-left py-2.5 px-4`},`创建时间`),l(`th`,{class:`text-center py-2.5 px-4`},`状态`),l(`th`,{class:`text-center py-2.5 px-4`},`操作`)])],-1),l(`tbody`,ne,[Z.value.length===0?(a(),o(`tr`,re,[...c[10]||=[l(`td`,{colspan:`7`,class:`py-8 text-center text-gray-400`},`暂无用户`,-1)]])):i(``,!0),(a(!0),o(t,null,s(Z.value,(t,n)=>(a(),o(`tr`,{key:t.id,class:`hover:bg-gray-50 transition-colors`},[l(`td`,ie,v(n+1),1),l(`td`,ae,v(t.username),1),l(`td`,oe,[l(`span`,se,v(e(g)[t.role]||t.role),1)]),l(`td`,ce,v(t.phone||`-`),1),l(`td`,T,v(me(t.createdAt)),1),l(`td`,E,[l(`span`,{class:ee([`text-xs rounded-full px-2 py-0.5`,t.status===`enabled`?`bg-green-50 text-green-600`:`bg-red-50 text-red-600`])},v(t.status===`enabled`?`启用`:`禁用`),3)]),l(`td`,D,[l(`div`,O,[l(`button`,{class:`text-xs text-blue-600 hover:underline`,onClick:e=>de(t)},`编辑`,8,k),l(`button`,{class:`text-xs text-red-500 hover:underline`,onClick:e=>pe(t)},`删除`,8,A)])])]))),128))])])])]),H.value?(a(),o(`div`,{key:0,class:`fixed inset-0 bg-black/30 z-50 flex items-center justify-center`,onClick:_($,[`self`])},[l(`div`,j,[l(`h3`,M,v(U.value?`编辑用户`:`新建用户`),1),l(`form`,{class:`space-y-3`,onSubmit:_(fe,[`prevent`])},[l(`div`,null,[c[12]||=l(`label`,{class:`text-xs text-gray-500`},[d(`用户名 `),l(`span`,{class:`text-red-400`},`*`)],-1),m(l(`input`,{"onUpdate:modelValue":c[2]||=e=>K.value=e,disabled:!!U.value,type:`text`,class:`w-full border rounded-lg px-3 py-2 text-sm disabled:bg-gray-50 disabled:text-gray-400`},null,8,N),[[r,K.value]])]),l(`div`,null,[l(`label`,P,[c[13]||=d(` 密码 `,-1),U.value?(a(),o(`span`,I,`(不填=不修改)`)):(a(),o(`span`,F,`*`))]),m(l(`input`,{"onUpdate:modelValue":c[3]||=e=>q.value=e,type:`password`,class:`w-full border rounded-lg px-3 py-2 text-sm`},null,512),[[r,q.value]])]),l(`div`,null,[c[14]||=l(`label`,{class:`text-xs text-gray-500`},`手机号`,-1),m(l(`input`,{"onUpdate:modelValue":c[4]||=e=>J.value=e,type:`text`,class:`w-full border rounded-lg px-3 py-2 text-sm`},null,512),[[r,J.value]])]),l(`div`,null,[c[15]||=l(`label`,{class:`text-xs text-gray-500`},`角色`,-1),m(l(`select`,{"onUpdate:modelValue":c[5]||=e=>Y.value=e,class:`w-full border rounded-lg px-3 py-2 text-sm`},[(a(!0),o(t,null,s(e(g),(e,t)=>(a(),o(`option`,{key:t,value:t},v(e),9,L))),128))],512),[[f,Y.value]])]),l(`div`,null,[c[18]||=l(`label`,{class:`text-xs text-gray-500`},`状态`,-1),l(`div`,R,[l(`label`,z,[m(l(`input`,{"onUpdate:modelValue":c[6]||=e=>X.value=e,type:`radio`,value:`enabled`},null,512),[[y,X.value]]),c[16]||=d(` 启用`,-1)]),l(`label`,le,[m(l(`input`,{"onUpdate:modelValue":c[7]||=e=>X.value=e,type:`radio`,value:`disabled`},null,512),[[y,X.value]]),c[17]||=d(` 禁用`,-1)])])]),l(`div`,{class:`flex justify-end gap-3 pt-3`},[l(`button`,{type:`button`,class:`px-4 py-2 text-sm text-gray-600 bg-white border rounded-lg hover:bg-gray-100`,onClick:$},`取消`),c[19]||=l(`button`,{type:`submit`,class:`px-4 py-2 text-sm text-white bg-blue-600 rounded-lg hover:bg-blue-700`},`保存`,-1)])],32)])])):i(``,!0)]))}});export{B as default};
@@ -0,0 +1 @@
1
+ .ai-field-highlight[data-v-bfbe3e7b]{animation:5s ease-out forwards aiHighlightFade-bfbe3e7b}.ai-field-highlight input[data-v-bfbe3e7b],.ai-field-highlight select[data-v-bfbe3e7b]{transition:border-color .3s,background-color .3s;background-color:#f5f3ff!important;border-color:#a78bfa!important}@keyframes aiHighlightFade-bfbe3e7b{0%{box-shadow:0 0 0 3px #a78bfa59}to{box-shadow:0 0 #a78bfa00}}@keyframes spin-bfbe3e7b{to{transform:rotate(360deg)}}.animate-spin[data-v-bfbe3e7b]{animation:1s linear infinite spin-bfbe3e7b}