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
10 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import{n as e}from"./axios-CiYFffbI.js";import{A as t,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,q as m,u as h,ut as g,v as _,y as v,z as ee}from"./runtime-core.esm-bundler-CnFWH3R5.js";import{i as y,o as b,r as x}from"./index-CPGARLlG.js";import{n as S,t as C}from"./datetime-3T8f3S0H.js";import{n as w,t as T}from"./reservationStatus-B4mW5yim.js";import{n as E,t as D}from"./h5Http-nx8aETIZ.js";function O(){if(typeof navigator>`u`)return null;let e=navigator.mediaDevices;if(e?.getUserMedia)return t=>e.getUserMedia(t);let t=navigator,n=t.getUserMedia||t.webkitGetUserMedia||t.mozGetUserMedia||t.msGetUserMedia;return n?e=>new Promise((t,r)=>{try{n.call(navigator,e,t,r)}catch(e){r(e)}}):null}function te(){return typeof window>`u`?`no-api`:!window.isSecureContext&&window.location.hostname!==`localhost`&&window.location.hostname!==`127.0.0.1`?`insecure`:O()?null:`no-api`}var ne={class:`m-scan`},re={class:`m-scan-head`},k={key:0,class:`m-scan-venue`},ie={class:`m-scan-stats`,"aria-label":`今日预约统计`},ae={key:0,class:`m-scan-stats-loading`},oe={class:`m-scan-stat`},se={class:`m-scan-stat-num`},ce={class:`m-scan-stat m-scan-stat--verified`},le={class:`m-scan-stat-num`},ue={class:`m-scan-main`},de=[`disabled`],fe={class:`cam-wrap`},pe={key:0,class:`today-modal-summary`},me={key:1,class:`today-list`},he={class:`today-row`},ge={class:`today-name`},_e={class:`today-act`},ve={class:`today-meta`},A=b(v({__name:`VerifyScan`,setup(v){let b=y(),A=x(),j=f(()=>A.path.startsWith(`/m/`)?`/m/verify/login`:`/h5/verify/login`),M=u(!1),N=u(!1),P=u(!1),F=u(null),I=u(null),L=null,R=u(``),z=u(``),B=u(null),V=u(!1),H=u(!1),ye=()=>{let e=new Date;return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,`0`)}-${String(e.getDate()).padStart(2,`0`)}`},U=u([]),W=u(!1),G=u(null),K=f(()=>{if(G.value)return G.value;let e=0,t=0;for(let n of U.value)n.status!==`cancelled`&&(e+=1),n.status===`verified`&&(t+=1);return{total_orders:e,verified_orders:t}}),q=u(null),J=f(()=>{let e=q.value;if(!e)return``;let t=e.venues??[];if(e.role===`super_admin`&&t.length===0)return`全部场馆`;let n=t.map(e=>e.name).filter(Boolean);return n.length?n.join(``):`未绑定场馆`});async function be(){try{let{data:e}=await E.get(`/me`);q.value=e}catch{q.value=null}}function xe(e){let t=e.trim();if(!t)return``;let n=t.match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i);if(n)return n[0];try{let e=new URL(t,window.location.origin),n=e.searchParams.get(`token`)||e.searchParams.get(`qr_token`)||e.searchParams.get(`t`);if(n)return n.trim()}catch{}return t}async function Y(){W.value=!0;try{let e=ye(),[t,n]=await Promise.allSettled([E.get(`/reservations`,{params:{status:`all`,start_date:e,end_date:e,date_field:`activity_day`}}),E.get(`/reservations/today-summary`)]);if(t.status===`rejected`)throw t.reason;let r=t.value.data;U.value=Array.isArray(r)?r:[],n.status===`fulfilled`?G.value=n.value.data:G.value=null}catch(t){e.error(t?.response?.data?.message??`加载今日报名失败`),U.value=[],G.value=null}finally{W.value=!1}}async function X(t){let n=xe(t);if(!n){e.warning(`未能识别二维码内容`);return}z.value=n,V.value=!0,B.value=null;try{let{data:e}=await E.get(`/reservations/preview`,{params:{qr_token:n}});B.value=e,N.value=!0,$()}catch(t){let n=t?.response?.data?.message??`查询预约失败`;e.error(n)}finally{V.value=!1}}async function Se(){if(z.value){H.value=!0;try{let{data:t}=await E.post(`/reservations/verify`,{qr_token:z.value});e.success(t?.message??`核销成功`),B.value={reservation:t.reservation,can_verify:!1,verify_block_reason:null},await Y()}catch(t){let n=t?.response?.data?.message??`核销失败`;e.error(n),z.value&&await X(z.value)}finally{H.value=!1}}}async function Z(){return!B.value||!B.value.can_verify?(Q(),!0):(await Se(),!1)}function Q(){N.value=!1,B.value=null,z.value=``}function $(){M.value=!1,L&&=(window.clearInterval(L),null),I.value&&=(I.value.getTracks().forEach(e=>e.stop()),null)}async function Ce(){if(!localStorage.getItem(`szkp_h5_verify_token`)){b.replace(j.value);return}if(te()===`insecure`){e.warning(`非安全访问(需 https无法调用摄像头请使用 https 地址打开本页。`);return}let t=O();if(!t){e.warning(`当前环境无摄像头接口(常见于微信内置浏览器等),请使用系统自带浏览器打开本页。`);return}R.value=``,M.value=!0;try{I.value=await t({video:{facingMode:`environment`},audio:!1}),await new Promise(e=>requestAnimationFrame(e)),F.value&&(F.value.srcObject=I.value,await F.value.play()),we()}catch{e.error(`无法打开摄像头,请检查权限设置`),$()}}function we(){let t=window.BarcodeDetector;if(!t){e.warning(`当前浏览器不支持实时识别二维码,请升级系统浏览器或使用其它手机`);return}let n=new t({formats:[`qr_code`]});L&&window.clearInterval(L),L=window.setInterval(async()=>{if(F.value)try{let e=(await n.detect(F.value))?.[0]?.rawValue||``;e&&e!==R.value&&(R.value=e,await X(e))}catch{}},400)}async function Te(){$();try{await E.post(`/auth/logout`)}catch{}localStorage.removeItem(D),localStorage.removeItem(`${D}_saved_at`),b.replace(j.value)}return m(P,e=>{e&&Y()}),r(()=>{if(!localStorage.getItem(`szkp_h5_verify_token`)){b.replace(j.value);return}be(),Y()}),t(()=>{$()}),(e,t)=>{let r=i(`a-button`),u=i(`a-modal`),f=i(`a-alert`),m=i(`a-descriptions-item`),v=i(`a-tag`),y=i(`a-descriptions`),b=i(`a-spin`),x=i(`a-empty`);return n(),p(`div`,ne,[h(`header`,re,[h(`div`,null,[t[4]||=h(`div`,{class:`m-scan-brand`},`核销`,-1),t[5]||=h(`div`,{class:`m-scan-sub`},`扫码核对信息后核销`,-1),J.value?(n(),p(`div`,k,`当前场馆:`+d(J.value),1)):c(``,!0)]),_(r,{size:`small`,onClick:Te},{default:a(()=>[...t[6]||=[o(`退出`,-1)]]),_:1})]),h(`section`,ie,[W.value?(n(),p(`div`,ae,`统计加载中…`)):(n(),p(l,{key:1},[h(`div`,oe,[t[7]||=h(`div`,{class:`m-scan-stat-label`},`今日预约数`,-1),h(`div`,se,d(K.value.total_orders),1)]),h(`div`,ce,[t[8]||=h(`div`,{class:`m-scan-stat-label`},`已核销数`,-1),h(`div`,le,d(K.value.verified_orders),1)])],64))]),h(`main`,ue,[h(`button`,{type:`button`,class:`m-scan-btn`,disabled:V.value,onClick:Ce},[...t[9]||=[h(`span`,{class:`m-scan-btn-icon`,"aria-hidden":`true`},null,-1),h(`span`,null,`扫码核销`,-1)]],8,de),t[11]||=h(`p`,{class:`m-scan-hint`},`将打开手机摄像头,对准用户预约二维码即可识别。`,-1),t[12]||=h(`p`,{class:`m-scan-hint m-scan-hint--sub`},`仅支持核销「活动日为今天」的预约;其它日期将提示原因且无法核销。`,-1),_(r,{long:``,class:`m-scan-secondary`,onClick:t[0]||=e=>P.value=!0},{default:a(()=>[...t[10]||=[o(`查看今日报名(按活动日)`,-1)]]),_:1})]),_(u,{visible:M.value,"onUpdate:visible":t[1]||=e=>M.value=e,title:`扫描预约二维码`,footer:!1,"mask-closable":!0,"unmount-on-close":!0,width:`min(100%, 420px)`,onCancel:$},{default:a(()=>[h(`div`,fe,[h(`video`,{ref_key:`videoRef`,ref:F,class:`cam-video`,muted:``,playsinline:``},null,512),t[14]||=h(`p`,{class:`cam-tip`},`请将二维码置于取景框中央`,-1),_(r,{long:``,onClick:$},{default:a(()=>[...t[13]||=[o(`取消`,-1)]]),_:1})])]),_:1},8,[`visible`]),_(u,{visible:N.value,"onUpdate:visible":t[2]||=e=>N.value=e,title:`预约信息`,"modal-class":`m-verify-res-modal`,"modal-style":{width:`min(calc(100vw - 24px), 440px)`,maxWidth:`100%`},"body-style":{maxHeight:`min(72vh, 520px)`,overflowY:`auto`,padding:`12px 16px 8px`},"ok-loading":H.value||V.value,"ok-text":B.value?.can_verify?`立即核销`:`关闭`,"ok-button-props":{size:`large`,long:!0},"cancel-button-props":{size:`large`},"on-before-ok":Z,onCancel:Q},{default:a(()=>[_(b,{loading:V.value,style:{width:`100%`}},{default:a(()=>[B.value?(n(),p(l,{key:0},[!B.value.can_verify&&B.value.verify_block_reason?(n(),s(f,{key:0,type:`warning`,style:{"margin-bottom":`12px`}},{default:a(()=>[o(d(B.value.verify_block_reason),1)]),_:1})):c(``,!0),_(y,{column:1,size:`small`,class:`m-verify-res-desc`},{default:a(()=>[_(m,{label:`场馆`},{default:a(()=>[o(d(B.value.reservation.venue?.name??`-`),1)]),_:1}),_(m,{label:`活动`},{default:a(()=>[o(d(B.value.reservation.activity?.title??`-`),1)]),_:1}),_(m,{label:`预约日期`},{default:a(()=>[o(d(g(S)(B.value.reservation.activity_day?.activity_date??null)),1)]),_:1}),_(m,{label:`报名人`},{default:a(()=>[o(d(B.value.reservation.visitor_name??`-`),1)]),_:1}),_(m,{label:`手机`},{default:a(()=>[o(d(B.value.reservation.visitor_phone??`-`),1)]),_:1}),_(m,{label:`预约类型`},{default:a(()=>[o(d(g(w)(B.value.reservation.booking_type,B.value.reservation.ticket_count)),1)]),_:1}),_(m,{label:`状态`},{default:a(()=>[_(v,{color:B.value.reservation.status===`verified`?`green`:B.value.reservation.status===`pending`?`arcoblue`:B.value.reservation.status===`expired`?`orange`:`gray`},{default:a(()=>[o(d(g(T)(B.value.reservation.status)),1)]),_:1},8,[`color`])]),_:1}),B.value.reservation.verified_at?(n(),s(m,{key:0,label:`核销时间`},{default:a(()=>[o(d(g(C)(B.value.reservation.verified_at)),1)]),_:1})):c(``,!0)]),_:1})],64)):c(``,!0)]),_:1},8,[`loading`])]),_:1},8,[`visible`,`ok-loading`,`ok-text`]),_(u,{visible:P.value,"onUpdate:visible":t[3]||=e=>P.value=e,title:`今日报名(活动日为今天)`,footer:!1,width:`min(100%, 440px)`,onOpen:Y},{default:a(()=>[W.value?c(``,!0):(n(),p(`div`,pe,[t[15]||=o(` 今日预约数 `,-1),h(`strong`,null,d(K.value.total_orders),1),t[16]||=o(` · 已核销数 `,-1),h(`strong`,null,d(K.value.verified_orders),1)])),_(b,{loading:W.value,style:{width:`100%`,"min-height":`80px`}},{default:a(()=>[U.value.length?(n(),p(`div`,me,[(n(!0),p(l,null,ee(U.value,e=>(n(),p(`div`,{key:e.id,class:`today-item`},[h(`div`,he,[h(`span`,ge,d(e.visitor_name||`未填写`),1),_(v,{size:`small`,color:e.status===`verified`?`green`:e.status===`pending`?`arcoblue`:e.status===`expired`?`orange`:`gray`},{default:a(()=>[o(d(g(T)(e.status)),1)]),_:2},1032,[`color`])]),h(`div`,_e,d(e.activity?.title??``),1),h(`div`,ve,d(g(w)(e.booking_type,e.ticket_count))+` · 活动日 `+d(g(S)(e.activity_day?.activity_date??null))+` · 预约时间 `+d(g(C)(e.created_at)),1)]))),128))])):(n(),s(x,{key:0,description:`今日(活动日为今天)暂无预约记录`}))]),_:1},8,[`loading`])]),_:1},8,[`visible`])])}}}),[[`__scopeId`,`data-v-39d404e1`]]);export{A as default};