|
|
import{n as e,t}from"./axios-CiYFffbI.js";import{I as n,N as r,V as i,Y as a,_ as o,d as s,f as c,i as l,it as u,kt as d,l as f,p,u as m,ut as h,v as g,y as _,z as ee}from"./runtime-core.esm-bundler-CnFWH3R5.js";import{d as v,u as y}from"./index-DDo-CpLK.js";function b(){return(`https://hik.pdc.langye.net:18080/api/people-counting`?.trim()??``).replace(/\/+$/,``)}function x(){let e=b();return e?e.replace(/\/api\/people-counting$/i,``):``}var S=2e4,C=45e3;function w(e,n=S){return t.create({baseURL:e.replace(/\/+$/,``),timeout:n,headers:{Accept:`application/json`,"Content-Type":`application/json`}})}async function T(e){let t=b();if(!t)throw Error(`未配置 VITE_PEOPLE_COUNTING_URL(海康客流 people-counting 完整地址)`);let n=w(t.replace(/\/api\/people-counting$/i,``)),r=(e||``).trim(),i=r&&/^\d{4}-\d{2}-\d{2}$/.test(r)?{date:r}:void 0,{data:a}=await n.get(`/api/people-counting`,{params:i});return a}async function E(){let e=x();if(!e)throw Error(`未配置 VITE_PEOPLE_COUNTING_URL,无法推导 /api/health 基址`);let{data:t}=await w(e).get(`/api/health`);return t}async function D(e,t){let n=x();if(!n)throw Error(`未配置 VITE_PEOPLE_COUNTING_URL,无法请求 /api/venues/hourly`);let{data:r}=await w(n).get(`/api/venues/hourly`,{params:{date:e.trim(),...t&&String(t).trim()?{venueId:String(t).trim()}:{}}});return r}async function O(e){let t=x();if(!t)throw Error(`未配置 VITE_PEOPLE_COUNTING_URL,无法请求 /api/device-links`);let n=w(t,e?.probe||e?.live?C:S),r={};e?.probe&&(r.probe=`true`),e?.live&&(r.live=`1`),e?.tcpTimeoutMs!=null&&Number.isFinite(e.tcpTimeoutMs)&&(r.tcpTimeoutMs=Math.min(3e4,Math.max(300,Math.floor(e.tcpTimeoutMs))));let{data:i}=await n.get(`/api/device-links`,{params:r});return i}async function k(e){let t=x();if(!t)throw Error(`未配置 VITE_PEOPLE_COUNTING_URL,无法请求重试接口`);let{data:n}=await w(t,S*2).post(`/api/device-links/retry`,e);return n}function te(e){return Math.max(0,Number(e.enter??0)-Number(e.exit??0))}function ne(e){return e==null?``:Array.isArray(e)?e.filter(Boolean).join(`、`):String(e).trim()}function re(e){let t=String(e||``).toUpperCase();return t===`UP`?`green`:t===`DEGRADED`?`orangered`:`red`}var ie={key:0,class:`muted`},ae={class:`muted`},oe={class:`muted`},se={class:`muted`},ce={class:`muted`},le={key:0,class:`muted`},ue={class:`sum-value`},de={style:{"margin-top":`8px`,color:`var(--color-text-3)`,"font-size":`12px`}},fe={key:1},pe={key:0,style:{"margin-top":`8px`,color:`var(--color-text-3)`,"font-size":`12px`}},me={key:0,class:`muted`,style:{"margin-bottom":`8px`}},he={key:1,class:`muted`,style:{"margin-bottom":`8px`}},A=y(_({__name:`HikPeopleCounting`,setup(t){let _=u(!1),y=u(!1);function b(){let e=new Date,t=e=>String(e).padStart(2,`0`);return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())}`}let x=u(`realtime`),S=u(b()),C=u(null),w=u(null),A=u(null),j=u(null),M=f(()=>C.value?.venues??[]),N=u(b()),P=u(void 0),F=u(null),I=u(!1),L=u(!1),R=u(null),z=u(!1),B=u(!1),V=u([]),H=u(!1),U=u(null),ge=f(()=>M.value.map(e=>({label:`${e.venueName||e.venueId} (${e.venueId})`,value:String(e.venueId)})));function _e(e,t){let n=(e||``).trim().toLowerCase();if(!n)return!0;let r=String(t?.label??``).toLowerCase(),i=String(t?.value??``).toLowerCase();return r.includes(n)||i.includes(n)}async function W(t=!1){let n=(S.value||``).trim();if(!/^\d{4}-\d{2}-\d{2}$/.test(n)){e.warning(`请选择合法日期 yyyy-MM-dd`);return}_.value=!0;try{C.value=await T(n),j.value=new Date().toLocaleString(`zh-CN`),C.value.code===200?t&&e.success(`客流数据已更新`):e.warning(C.value.message||`请求失败(错误码 ${C.value.code})`)}catch(t){C.value=null;let n=t,r=n.response?.status,i=n.response?.data,a=typeof i==`object`&&i&&`message`in i?String(i.message):``,o=t&&typeof t==`object`&&`message`in t?String(t.message):String(t);r===404?e.warning(a||`暂无该日期的归档数据`):e.error(o||`客流接口请求失败`)}finally{_.value=!1}}async function G(){y.value=!0,A.value=null;try{w.value=await E()}catch(t){w.value=null,A.value=t&&typeof t==`object`&&`message`in t?String(t.message):String(t),e.error(A.value||`健康检查失败`)}finally{y.value=!1}}async function K(){await Promise.all([W(!0),G()])}async function ve(){let t=(N.value||``).trim();if(!/^\d{4}-\d{2}-\d{2}$/.test(t)){e.warning(`请选择合法日期 yyyy-MM-dd`);return}I.value=!0,F.value=null;try{F.value=await D(t,P.value||void 0),e.success(`已加载按小时数据`)}catch(t){let n=t&&typeof t==`object`&&`message`in t?String(t.message):String(t);e.error(n||`按小时查询失败`)}finally{I.value=!1}}async function q(){z.value=!0,R.value=null,V.value=[];try{R.value=await O({probe:L.value,live:L.value}),e.success(L.value?`已加载设备(含探测)`:`已加载设备链路`),V.value=[...new Set((R.value.devices??[]).filter(e=>J(e.status)).map(e=>e.deviceSlot).filter(e=>typeof e==`number`&&Number.isFinite(e)))].sort((e,t)=>e-t)}catch(t){let n=t,r=n.response?.status,i=n.response?.data?.message||(t&&typeof t==`object`&&`message`in t?String(t.message):String(t));e.error(r===403?`探测已被服务端关闭`:i||`设备链路加载失败`)}finally{z.value=!1}}function J(e){return String(e||``).trim().toUpperCase()!==`ONLINE`}function Y(e){let t=(R.value?.devices??[]).find(t=>t.deviceSlot===e),n=(t?.name||``).trim()||`设备槽位 ${e}`,r=(t?.ip||``).trim();return r?`${n} ${r}`:n}function ye(){let e=R.value?.devices??[];return[...new Set(e.map(e=>e.deviceSlot).filter(e=>typeof e==`number`))].sort((e,t)=>e-t).map(e=>({label:Y(e),value:e}))}async function be(){let t=V.value.filter(e=>Number.isFinite(e));if(!t.length){e.warning(`请至少选择一个设备槽位序号`);return}B.value=!0;try{let n=await k({deviceIndices:t});if(n.code===200){e.success(n.message||`重试指令已下发`);let t=(n.results??[]).map(e=>`${Y(e.deviceIndex)}:${e.ok?`成功`:`失败`} ${e.message||``}`.trim());t.length&&v.info({title:`重试结果`,content:t.join(`
|
|
|
`)}),await q(),await G()}else e.warning(n.message||`错误码 ${n.code}`)}catch(t){let n=t,r=t&&typeof t==`object`&&`message`in t?String(t.message):String(t);e.error(n.response?.status===403?`服务端已禁止远程重试登录`:r||`重试请求失败`)}finally{B.value=!1}}function xe(e){U.value=e,H.value=!0}r(()=>{K()});let Se=[{title:`场馆ID`,dataIndex:`venueId`,width:140,ellipsis:!0,tooltip:!0},{title:`场馆名称`,dataIndex:`venueName`,width:180,ellipsis:!0,tooltip:!0},{title:`进入`,dataIndex:`enter`,width:96},{title:`离开`,dataIndex:`exit`,width:96},{title:`经过`,dataIndex:`passing`,width:96},{title:`在馆(推算)`,slotName:`net`,width:110},{title:`更新次数`,dataIndex:`updateCount`,width:110},{title:`最后更新`,slotName:`venueLastUpdate`,width:190,ellipsis:!0,tooltip:!0},{title:`包含组`,slotName:`included`,width:220,ellipsis:!0,tooltip:!0},{title:`馆内子组`,slotName:`nested`,width:100}],Ce=[{title:`小时`,dataIndex:`hourLabel`,width:100},{title:`进入`,dataIndex:`enter`,width:90},{title:`离开`,dataIndex:`exit`,width:90},{title:`经过`,dataIndex:`passing`,width:90}];function X(e){return(e.hourly??[]).map(t=>({key:`${e.venueId}-${t.hour}`,hourLabel:t.hourLabel!=null&&String(t.hourLabel).trim()?t.hourLabel:String(t.hour),enter:t.enter,exit:t.exit,passing:t.passing}))}let we=[{title:`槽位`,dataIndex:`deviceSlot`,width:72},{title:`名称`,dataIndex:`name`,width:120,ellipsis:!0,tooltip:!0},{title:`IP`,dataIndex:`ip`,width:130},{title:`端口`,dataIndex:`port`,width:80},{title:`状态`,slotName:`devStatus`,width:120},{title:`说明`,dataIndex:`statusHint`,ellipsis:!0,tooltip:!0},{title:`探测`,slotName:`probe`,width:200,ellipsis:!0,tooltip:!0}];function Te(e){let t=e.networkProbe;if(!t)return`—`;let n=[t.tcpReachable===void 0?``:t.tcpReachable?`TCP 已连通`:`TCP 未连通`,t.tcpConnectLatencyMs==null?``:`延迟 ${t.tcpConnectLatencyMs} ms`,t.icmpReachable===void 0?``:t.icmpReachable?`ICMP 已通`:`ICMP 不可用`,(t.summaryHint||``).trim()].filter(Boolean);return n.length?n.join(`,`):`—`}function Ee(e){let t=String(e||``).toUpperCase();return t===`UP`?`正常`:t===`DEGRADED`?`降级`:(e||``).trim()||`—`}function De(e){if(e==null||e===``)return`—`;let t;if(typeof e==`number`)t=new Date(e);else{let n=String(e).trim();if(/^\d+$/.test(n)){let e=Number(n),r=e>1e11?e:e*1e3;t=new Date(r)}else t=new Date(n)}if(Number.isNaN(t.getTime()))return String(e);let n=e=>String(e).padStart(2,`0`);return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())} ${n(t.getHours())}:${n(t.getMinutes())}:${n(t.getSeconds())}`}function Z(e){if(e==null||e===``)return``;if(typeof e==`number`){let t=new Date(e);return Number.isNaN(t.getTime())?String(e):t.toLocaleString(`zh-CN`)}let t=String(e).trim();if(/^\d+$/.test(t)){let e=Number(t),n=e>1e11?e:e*1e3,r=new Date(n);return Number.isNaN(r.getTime())?t:r.toLocaleString(`zh-CN`)}let n=new Date(t);return Number.isNaN(n.getTime())?t:n.toLocaleString(`zh-CN`)}function Oe(e){return{ONLINE:`在线`,LOGIN_FAILED:`登录失败`,ARM_FAILED:`布防失败`}[String(e||``).trim().toUpperCase()]||(e||``).trim()||`—`}let ke=[{title:`统计组ID`,dataIndex:`groupId`,ellipsis:!0,tooltip:!0},{title:`名称`,dataIndex:`groupName`,ellipsis:!0,tooltip:!0},{title:`进入`,dataIndex:`enter`,width:80},{title:`离开`,dataIndex:`exit`,width:80},{title:`经过`,dataIndex:`passing`,width:80}];return(e,t)=>{let r=i(`a-date-picker`),u=i(`a-button`),f=i(`a-space`),v=i(`a-tag`),b=i(`a-typography-text`),T=i(`a-card`),E=i(`a-col`),D=i(`a-statistic`),O=i(`a-row`),k=i(`a-empty`),J=i(`a-alert`),Y=i(`a-table`),Q=i(`a-tab-pane`),$=i(`a-select`),Ae=i(`a-switch`),je=i(`a-tabs`),Me=i(`a-modal`);return n(),s(T,{title:`客流监控 / 海康客流接口`},{default:a(()=>[g(je,{"active-key":x.value,"onUpdate:activeKey":t[6]||=e=>x.value=e,type:`rounded`},{default:a(()=>[g(Q,{key:`realtime`,title:`实时汇总`},{default:a(()=>[g(f,{wrap:``,style:{"margin-bottom":`16px`}},{default:a(()=>[t[11]||=m(`span`,{style:{color:`var(--color-text-2)`}},`统计日期`,-1),g(r,{modelValue:S.value,"onUpdate:modelValue":t[0]||=e=>S.value=e,"value-format":`YYYY-MM-DD`,style:{width:`160px`}},null,8,[`modelValue`]),g(u,{type:`primary`,loading:_.value,onClick:t[1]||=e=>W(!0)},{default:a(()=>[...t[8]||=[o(`拉取客流`,-1)]]),_:1},8,[`loading`]),g(u,{loading:y.value,onClick:G},{default:a(()=>[...t[9]||=[o(`健康检查`,-1)]]),_:1},8,[`loading`]),g(u,{onClick:K},{default:a(()=>[...t[10]||=[o(`全部刷新`,-1)]]),_:1}),j.value?(n(),p(`span`,ie,`上次拉取:`+d(j.value),1)):c(``,!0)]),_:1}),w.value||A.value?(n(),s(T,{key:0,title:`服务健康状态`,style:{"margin-bottom":`16px`},size:`small`},{default:a(()=>[w.value?(n(),s(f,{key:0,direction:`vertical`,fill:``},{default:a(()=>[g(f,{wrap:``},{default:a(()=>[g(v,{color:h(re)(w.value.status)},{default:a(()=>[o(d(Ee(w.value.status)),1)]),_:1},8,[`color`]),m(`span`,ae,`配置设备路数:`+d(w.value.nvrConfigured??`—`),1),m(`span`,oe,`已成功登录路数:`+d(w.value.nvrLoggedIn??`—`),1),m(`span`,se,`设备数量:`+d(w.value.deviceCount??`—`),1),m(`span`,ce,`统计组条目数:`+d(w.value.groupCount??`—`),1),w.value.timestamp?(n(),p(`span`,le,d(`返回时间:${Z(w.value.timestamp)}`),1)):c(``,!0)]),_:1}),w.value.hint?(n(),s(b,{key:0,type:`warning`},{default:a(()=>[o(d(w.value.hint),1)]),_:1})):c(``,!0)]),_:1})):(n(),s(b,{key:1,type:`danger`},{default:a(()=>[o(d(A.value),1)]),_:1}))]),_:1})):c(``,!0),C.value&&C.value.code===200?(n(),s(T,{key:1,title:`当日客流汇总`,style:{"margin-bottom":`16px`},size:`small`},{default:a(()=>[g(O,{gutter:16},{default:a(()=>[g(E,{span:6},{default:a(()=>[t[12]||=m(`div`,{class:`sum-label`},`数据日期`,-1),m(`div`,ue,d(C.value.date??`—`),1)]),_:1}),g(E,{span:6},{default:a(()=>[g(D,{title:`进入(合计)`,value:C.value.total.enter},null,8,[`value`])]),_:1}),g(E,{span:6},{default:a(()=>[g(D,{title:`离开(合计)`,value:C.value.total.exit},null,8,[`value`])]),_:1}),g(E,{span:6},{default:a(()=>[g(D,{title:`经过(合计)`,value:C.value.total.passing},null,8,[`value`])]),_:1})]),_:1}),m(`div`,de,` 累计接收数据条数:`+d(C.value.total.dataCount),1)]),_:1})):c(``,!0),C.value===null&&!_.value?(n(),s(k,{key:2,description:`暂无数据,请先拉取客流`})):C.value&&C.value.code!==200?(n(),s(J,{key:3,type:`warning`,style:{"margin-bottom":`16px`}},{default:a(()=>[o(` 接口返回非 200:`+d(C.value.message||C.value.code),1)]),_:1})):c(``,!0),g(T,{title:`各场馆当日人数统计`,style:{"margin-bottom":`16px`},size:`small`},{default:a(()=>[g(Y,{"row-key":`venueId`,columns:Se,data:M.value,pagination:!1,size:`small`,scroll:{x:1300,y:280}},{net:a(({record:e})=>[o(d(h(te)(e)),1)]),venueLastUpdate:a(({record:e})=>[o(d(De(e.lastUpdate)),1)]),included:a(({record:e})=>[o(d(h(ne)(e.includedGroups)),1)]),nested:a(({record:e})=>[(e.groups?.length??0)>0?(n(),s(u,{key:0,type:`text`,size:`mini`,onClick:t=>xe(e)},{default:a(()=>[o(d(e.groups.length)+` 组 `,1)]),_:2},1032,[`onClick`])):(n(),p(`span`,fe,`—`))]),_:1},8,[`data`]),M.value.length===0?(n(),p(`div`,pe,` 暂无场馆数据时,请检查服务端场馆与统计组映射是否已正确配置。 `)):c(``,!0)]),_:1})]),_:1}),g(Q,{key:`hourly`,title:`场馆按小时`},{default:a(()=>[g(f,{wrap:``,style:{"margin-bottom":`12px`}},{default:a(()=>[g(r,{modelValue:N.value,"onUpdate:modelValue":t[2]||=e=>N.value=e,"value-format":`YYYY-MM-DD`,style:{width:`160px`}},null,8,[`modelValue`]),g($,{modelValue:P.value,"onUpdate:modelValue":t[3]||=e=>P.value=e,placeholder:`可选:搜索并筛选单个场馆`,"allow-clear":``,"allow-search":``,"filter-option":_e,style:{width:`280px`},options:ge.value},null,8,[`modelValue`,`options`]),g(u,{type:`primary`,loading:I.value,onClick:ve},{default:a(()=>[...t[13]||=[o(`按小时查询`,-1)]]),_:1},8,[`loading`])]),_:1}),g(b,{type:`secondary`,style:{display:`block`,"margin-bottom":`12px`}},{default:a(()=>[...t[14]||=[o(` 须选择查询日期;可按需指定场馆。数据来自服务内存按小时汇总,过早历史日期可能均为 0。 `,-1)]]),_:1}),F.value?.venues?.length?(n(!0),p(l,{key:0},ee(F.value.venues||[],e=>(n(),p(`div`,{key:e.venueId,style:{"margin-bottom":`16px`}},[g(T,{size:`small`,title:(e.venueName||e.venueId)+`(${e.venueId})`},{default:a(()=>[g(Y,{columns:Ce,data:X(e),"row-key":`key`,pagination:!1,size:`small`},null,8,[`data`])]),_:2},1032,[`title`])]))),128)):I.value?c(``,!0):(n(),s(k,{key:1,description:`请选择日期后查询`}))]),_:1}),g(Q,{key:`devices`,title:`设备链路 / 重试`},{default:a(()=>[g(f,{wrap:``,style:{"margin-bottom":`12px`}},{default:a(()=>[g(Ae,{modelValue:L.value,"onUpdate:modelValue":t[4]||=e=>L.value=e},{checked:a(()=>[...t[15]||=[o(`含网络探测(较慢)`,-1)]]),unchecked:a(()=>[...t[16]||=[o(`仅快照`,-1)]]),_:1},8,[`modelValue`]),g(u,{loading:z.value,onClick:q},{default:a(()=>[...t[17]||=[o(`加载设备链路`,-1)]]),_:1},8,[`loading`])]),_:1}),g(b,{type:`secondary`,style:{display:`block`,"margin-bottom":`12px`}},{default:a(()=>[...t[18]||=[o(` 开启网络探测会向各设备端口发起连通性检测,耗时更长;服务端可关闭此项(将返回无权访问)。 `,-1)]]),_:1}),R.value?(n(),s(T,{key:0,title:`设备列表`,size:`small`,style:{"margin-bottom":`16px`}},{default:a(()=>[R.value.probedAt?(n(),p(`div`,me,` 探测完成时间:`+d(Z(R.value.probedAt)),1)):c(``,!0),R.value.probeDetail?(n(),p(`div`,he,d(R.value.probeDetail),1)):c(``,!0),g(Y,{"row-key":`__k`,columns:we,data:(R.value.devices||[]).map((e,t)=>({...e,__k:`${e.deviceSlot}-${e.ip}-${t}`})),pagination:!1,size:`small`,scroll:{x:1e3,y:220}},{devStatus:a(({record:e})=>[o(d(Oe(e.status)),1)]),probe:a(({record:e})=>[o(d(Te(e)),1)]),_:1},8,[`data`])]),_:1})):c(``,!0),g(T,{title:`设备重试登录`,size:`small`},{default:a(()=>[g(f,{direction:`vertical`,fill:``},{default:a(()=>[g($,{modelValue:V.value,"onUpdate:modelValue":t[5]||=e=>V.value=e,options:ye(),multiple:``,placeholder:`默认为失败设备;可选场馆名称与 IP 对应项`,"allow-clear":``,style:{width:`100%`,"max-width":`720px`}},null,8,[`modelValue`,`options`]),g(f,{wrap:``},{default:a(()=>[g(u,{type:`primary`,status:`danger`,loading:B.value,onClick:be},{default:a(()=>[...t[19]||=[o(` 发起重试登录 `,-1)]]),_:1},8,[`loading`]),t[20]||=m(`span`,{class:`muted`},`向服务下发重试指令,不勾选从磁盘重新加载配置(如有需要可由运维在服务端操作)`,-1)]),_:1})]),_:1})]),_:1})]),_:1})]),_:1},8,[`active-key`]),g(Me,{visible:H.value,"onUpdate:visible":t[7]||=e=>H.value=e,title:`馆内分组明细`,footer:!1,width:`800px`},{default:a(()=>[U.value?(n(),p(l,{key:0},[g(b,{type:`secondary`,style:{"margin-bottom":`8px`,display:`block`}},{default:a(()=>[o(d(U.value.venueName)+` / `+d(U.value.venueId),1)]),_:1}),g(Y,{"row-key":`groupId`,columns:ke,data:U.value.groups||[],pagination:!1,size:`small`},null,8,[`data`])],64)):c(``,!0)]),_:1},8,[`visible`])]),_:1})}}}),[[`__scopeId`,`data-v-2cf8a72b`]]);export{A as default}; |