You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1 line
11 KiB
1 line
11 KiB
import{n as e}from"./axios-CiYFffbI.js";import{I as t,N as n,Ot as r,V as i,Y as a,_ as o,d as s,f as c,i as ee,it as l,kt as u,l as d,nt as f,p,u as m,ut as h,v as g,y as _,z as te}from"./runtime-core.esm-bundler-CnFWH3R5.js";import{n as v,o as y}from"./index-BbRh5og5.js";import{n as b}from"./datetime-3T8f3S0H.js";var ne={class:`dashboard-wrap`},re={class:`stats-grid-5`},ie={class:`hero-stat-card`},ae={class:`hero-value`},oe={class:`hero-stat-card`},se={class:`hero-value`},ce={class:`hero-stat-card`},le={class:`hero-value hero-green`},ue={class:`hero-stat-card`},de={class:`hero-value hero-yellow`},fe={class:`hero-stat-card`},pe={class:`hero-value`},me={class:`stats-grid-4`},he={class:`metric-stat-card`},ge={class:`metric-value`},_e={class:`metric-stat-card`},ve={class:`metric-value`},x={class:`metric-stat-card`},S={class:`metric-value`},C={class:`metric-stat-card`},w={class:`metric-value`},T={key:0,class:`single-trend-card`},E={class:`single-trend-date`},D={class:`single-trend-grid`},O={class:`single-item`},k={class:`single-value`},A={class:`single-item`},j={class:`single-value`},M={class:`single-item`},N={class:`single-value`},P={class:`single-item`},F={class:`single-value`},ye={key:1,class:`trend-wrap`},be={class:`trend-scroll`},xe=[`x1`,`y1`,`x2`,`y2`],Se=[`x1`,`y1`,`x2`,`y2`],Ce=[`points`],we=[`points`],Te=[`x1`,`x2`,`y1`,`y2`],Ee=[`cx`,`cy`],De=[`cx`,`cy`],I=[`x`,`y`],Oe=[`x`,`y`],ke=[`x`,`y`],Ae=[`y`],je={key:2},L=860,R=210,z=y(_({__name:`Dashboard`,setup(_){let y=l(!1),z=l(!1),B=l([]);function V(){let e=new Date;return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,`0`)}-${String(e.getDate()).padStart(2,`0`)}`}let H=f({venue_id:void 0,dateRange:[V(),V()]}),Me=[{label:`今天`,value:()=>{let e=new Date,t=`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,`0`)}-${String(e.getDate()).padStart(2,`0`)}`;return[t,t]}},{label:`本月`,value:()=>{let e=new Date;return[`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,`0`)}-01`,`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,`0`)}-${String(new Date(e.getFullYear(),e.getMonth()+1,0).getDate()).padStart(2,`0`)}`]}},{label:`近三月`,value:()=>{let e=new Date,t=new Date;return t.setMonth(t.getMonth()-3),[`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,`0`)}-${String(t.getDate()).padStart(2,`0`)}`,`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,`0`)}-${String(e.getDate()).padStart(2,`0`)}`]}},{label:`今年`,value:()=>{let e=new Date;return[`${e.getFullYear()}-01-01`,`${e.getFullYear()}-12-31`]}},{label:`去年`,value:()=>{let e=new Date().getFullYear()-1;return[`${e}-01-01`,`${e}-12-31`]}}],U=l({scope:{role:``,venue_id:void 0,start_date:``,end_date:``},summary:{total_count:0,verified_count:0,cancelled_count:0,pending_count:0,effective_count:0,verify_rate:0,blacklisted_unique:0,activity_sessions:0,active_venue_count:0},trends:[],compare_venues:[],realtime:{city_total:0,venues:[]}}),Ne=d(()=>Number((U.value.summary.verify_rate*100).toFixed(2))),Pe=d(()=>{if(!q.value)return{display:`none`};let e=Math.min(L-182,Math.max(8,q.value.x+10)),t=Math.max(8,q.value.y-84);return{position:`absolute`,left:`${e}px`,top:`${t}px`,background:`#fff`,border:`1px solid #e5e6eb`,borderRadius:`6px`,padding:`8px 10px`,fontSize:`12px`,boxShadow:`0 4px 16px rgba(0,0,0,0.14)`,zIndex:3,pointerEvents:`none`,minWidth:`170px`}}),W={top:16,right:20,bottom:24,left:28},G=L-W.left-W.right,K=R-W.top-W.bottom,q=l(null),J=d(()=>{let e=U.value.trends||[];if(!e.length)return null;let t=G,n=K,r=Math.max(1,...e.map(e=>Math.max(e.total_count,e.verified_count))),i=n=>W.left+t*n/Math.max(1,e.length-1),a=e=>W.top+n-n*e/r;return{totalPoints:e.map((e,t)=>`${i(t)},${a(e.total_count)}`).join(` `),verifiedPoints:e.map((e,t)=>`${i(t)},${a(e.verified_count)}`).join(` `),points:e.map((e,t)=>({index:t,x:i(t),y:a(e.verified_count),yTotal:a(e.total_count),...e})),firstDate:e[0].date,lastDate:e[e.length-1].date,maxY:r}}),Y=d(()=>{let e=U.value.trends||[];return e.length===1?e[0]:null});function X(e){let t=J.value;if(!t||!t.points[e])return;let n=t.points[e];q.value={index:e,x:n.x,y:n.y,date:n.date,total_count:n.total_count,verified_count:n.verified_count,cancelled_count:n.cancelled_count,verify_rate:n.verify_rate}}function Fe(){q.value=null}function Ie(e){let t=J.value;if(!t)return;let n=e.currentTarget.getBoundingClientRect(),r=e.clientX-n.left,i=Math.max(W.left,Math.min(L-W.right,r)),a=G>0?(i-W.left)/G:0;X(Math.round(a*Math.max(0,t.points.length-1)))}async function Z(){y.value=!0;try{let{data:e}=await v.get(`/dashboard/stats`,{params:{venue_id:H.venue_id||void 0,start_date:H.dateRange?.[0]||void 0,end_date:H.dateRange?.[1]||void 0}});U.value=e}catch(t){e.error(t?.response?.data?.message??`加载统计失败`)}finally{y.value=!1}}async function Q(){let{data:e}=await v.get(`/me`);z.value=e?.role===`super_admin`,z.value?B.value=(await v.get(`/venues`)).data:B.value=e?.venues||[]}function Le(){Z()}return n(async()=>{await Q(),await Z()}),(e,n)=>{let l=i(`a-option`),d=i(`a-select`),f=i(`a-range-picker`),_=i(`a-button`),v=i(`a-space`),V=i(`a-card`),X=i(`a-table-column`),Q=i(`a-table`),Re=i(`a-empty`),$=i(`a-tag`);return t(),p(`div`,ne,[g(V,{class:`query-card`,bordered:!1,title:`工作台 / 数据看板`},{default:a(()=>[g(v,{wrap:``},{default:a(()=>[z.value?(t(),s(d,{key:0,modelValue:H.venue_id,"onUpdate:modelValue":n[0]||=e=>H.venue_id=e,style:{width:`220px`},"allow-clear":``,placeholder:`筛选场馆`},{default:a(()=>[(t(!0),p(ee,null,te(B.value,e=>(t(),s(l,{key:e.id,value:e.id},{default:a(()=>[o(u(e.name),1)]),_:2},1032,[`value`]))),128))]),_:1},8,[`modelValue`])):c(``,!0),g(f,{modelValue:H.dateRange,"onUpdate:modelValue":n[1]||=e=>H.dateRange=e,"value-format":`YYYY-MM-DD`,shortcuts:Me,style:{width:`260px`}},null,8,[`modelValue`]),g(_,{type:`primary`,loading:y.value,onClick:Le},{default:a(()=>[...n[2]||=[o(`查询`,-1)]]),_:1},8,[`loading`]),g(_,{loading:y.value,onClick:Z},{default:a(()=>[...n[3]||=[o(`刷新统计`,-1)]]),_:1},8,[`loading`])]),_:1})]),_:1}),m(`div`,re,[m(`div`,null,[m(`div`,ie,[n[4]||=m(`div`,{class:`hero-title`},`全市实时总人数`,-1),m(`div`,ae,u(U.value.realtime.city_total),1)])]),m(`div`,null,[m(`div`,oe,[n[5]||=m(`div`,{class:`hero-title`},`总预约`,-1),m(`div`,se,u(U.value.summary.total_count),1)])]),m(`div`,null,[m(`div`,ce,[n[6]||=m(`div`,{class:`hero-title`},`已核销`,-1),m(`div`,le,u(U.value.summary.verified_count),1)])]),m(`div`,null,[m(`div`,ue,[n[7]||=m(`div`,{class:`hero-title`},`已取消`,-1),m(`div`,de,u(U.value.summary.cancelled_count),1)])]),m(`div`,null,[m(`div`,fe,[n[8]||=m(`div`,{class:`hero-title`},`待核销`,-1),m(`div`,pe,u(U.value.summary.pending_count),1)])])]),m(`div`,me,[m(`div`,null,[m(`div`,he,[n[10]||=m(`div`,{class:`metric-title`},`核销率`,-1),m(`div`,ge,[o(u(Ne.value),1),n[9]||=m(`span`,{class:`metric-suffix`},`%`,-1)])])]),m(`div`,null,[m(`div`,_e,[n[11]||=m(`div`,{class:`metric-title`},`黑名单人数(去重)`,-1),m(`div`,ve,u(U.value.summary.blacklisted_unique),1)])]),m(`div`,null,[m(`div`,x,[n[12]||=m(`div`,{class:`metric-title`},`活动场次`,-1),m(`div`,S,u(U.value.summary.activity_sessions),1)])]),m(`div`,null,[m(`div`,C,[n[13]||=m(`div`,{class:`metric-title`},`活跃场馆数`,-1),m(`div`,w,u(U.value.summary.active_venue_count),1)])])]),g(V,{class:`panel-card`,bordered:!1,title:`实时客流(全部场馆,按人数排序)`},{extra:a(()=>[g(_,{size:`small`,loading:y.value,onClick:Z},{default:a(()=>[...n[14]||=[o(`刷新实时客流`,-1)]]),_:1},8,[`loading`])]),default:a(()=>[g(Q,{data:U.value.realtime.venues,pagination:!1,"row-key":`venue_id`,size:`small`,scroll:{y:360}},{columns:a(()=>[g(X,{title:`场馆`,"data-index":`venue_name`,"min-width":240}),g(X,{title:`当前人数`,"data-index":`current_count`,width:120})]),_:1},8,[`data`])]),_:1}),g(V,{class:`panel-card`,bordered:!1,title:`核销统计(按活动发生时间)`},{default:a(()=>[Y.value?(t(),p(`div`,T,[m(`div`,E,u(h(b)(Y.value.date)),1),m(`div`,D,[m(`div`,O,[n[15]||=m(`div`,{class:`single-label`},`总预约`,-1),m(`div`,k,u(Y.value.total_count),1)]),m(`div`,A,[n[16]||=m(`div`,{class:`single-label`},`已核销`,-1),m(`div`,j,u(Y.value.verified_count),1)]),m(`div`,M,[n[17]||=m(`div`,{class:`single-label`},`已取消`,-1),m(`div`,N,u(Y.value.cancelled_count),1)]),m(`div`,P,[n[18]||=m(`div`,{class:`single-label`},`核销率`,-1),m(`div`,F,u((Y.value.verify_rate*100).toFixed(2))+`%`,1)])])])):J.value?(t(),p(`div`,ye,[q.value?(t(),p(`div`,{key:0,style:r(Pe.value)},[m(`div`,null,u(h(b)(q.value.date)),1),m(`div`,null,`总预约:`+u(q.value.total_count),1),m(`div`,null,`已核销:`+u(q.value.verified_count),1),m(`div`,null,`已取消:`+u(q.value.cancelled_count),1),m(`div`,null,`核销率:`+u((q.value.verify_rate*100).toFixed(2))+`%`,1)],4)):c(``,!0),m(`div`,be,[(t(),p(`svg`,{width:L,height:R},[m(`line`,{x1:W.left,y1:R-W.bottom,x2:L-W.right,y2:R-W.bottom,stroke:`#c9cdd4`},null,8,xe),m(`line`,{x1:W.left,y1:W.top,x2:W.left,y2:R-W.bottom,stroke:`#c9cdd4`},null,8,Se),m(`polyline`,{points:J.value.totalPoints,fill:`none`,stroke:`#165dff`,"stroke-width":`2`},null,8,Ce),m(`polyline`,{points:J.value.verifiedPoints,fill:`none`,stroke:`#00b42a`,"stroke-width":`2`},null,8,we),q.value?(t(),p(`line`,{key:0,x1:q.value.x,x2:q.value.x,y1:W.top,y2:R-W.bottom,stroke:`#94a3b8`,"stroke-dasharray":`4 4`},null,8,Te)):c(``,!0),q.value?(t(),p(`circle`,{key:1,cx:q.value.x,cy:J.value.points[q.value.index]?.yTotal,r:`3`,fill:`#165dff`},null,8,Ee)):c(``,!0),q.value?(t(),p(`circle`,{key:2,cx:q.value.x,cy:q.value.y,r:`3`,fill:`#00b42a`},null,8,De)):c(``,!0),m(`rect`,{x:W.left,y:W.top,width:G,height:K,fill:`transparent`,style:{cursor:`crosshair`},onMousemove:Ie,onMouseleave:Fe},null,40,I),m(`text`,{x:W.left,y:R-4,"font-size":`12`,fill:`#86909c`},u(h(b)(J.value.firstDate)),9,Oe),m(`text`,{x:L-W.right-80,y:R-4,"font-size":`12`,fill:`#86909c`},u(h(b)(J.value.lastDate)),9,ke),m(`text`,{x:4,y:W.top+6,"font-size":`12`,fill:`#86909c`},u(J.value.maxY),9,Ae)]))]),g(v,{size:`large`},{default:a(()=>[...n[19]||=[m(`span`,null,[m(`span`,{style:{display:`inline-block`,width:`10px`,height:`10px`,background:`#165dff`,"margin-right":`6px`}}),o(`总预约`)],-1),m(`span`,null,[m(`span`,{style:{display:`inline-block`,width:`10px`,height:`10px`,background:`#00b42a`,"margin-right":`6px`}}),o(`已核销`)],-1)]]),_:1})])):(t(),s(Re,{key:2,description:`暂无趋势数据`}))]),_:1}),z.value?(t(),s(V,{key:0,class:`panel-card`,bordered:!1,title:`场馆对比(全部场馆,按总预约数排序)`},{default:a(()=>[g(Q,{data:U.value.compare_venues,pagination:!1,"row-key":`venue_id`,size:`small`,scroll:{y:420}},{columns:a(()=>[g(X,{title:`场馆`,"data-index":`venue_name`,"min-width":220}),g(X,{title:`总预约`,"data-index":`total_count`,width:120}),g(X,{title:`已核销`,"data-index":`verified_count`,width:120}),g(X,{title:`已取消`,"data-index":`cancelled_count`,width:120}),g(X,{title:`核销率`,width:120},{cell:a(({record:e})=>[o(u((e.verify_rate*100).toFixed(2))+`%`,1)]),_:1}),g(X,{title:`取消率`,width:120},{cell:a(({record:e})=>[o(u((e.cancel_rate*100).toFixed(2))+`%`,1)]),_:1}),g(X,{title:`预警`,width:180},{cell:a(({record:e})=>[g(v,null,{default:a(()=>[e.warning_low_verify?(t(),s($,{key:0,color:`orange`},{default:a(()=>[...n[20]||=[o(`低核销率`,-1)]]),_:1})):c(``,!0),e.warning_high_cancel?(t(),s($,{key:1,color:`red`},{default:a(()=>[...n[21]||=[o(`高取消率`,-1)]]),_:1})):c(``,!0),!e.warning_low_verify&&!e.warning_high_cancel?(t(),p(`span`,je,`-`)):c(``,!0)]),_:2},1024)]),_:1})]),_:1},8,[`data`])]),_:1})):c(``,!0)])}}}),[[`__scopeId`,`data-v-a1f78db8`]]);export{z as default}; |