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
14 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{$t as e,C as t,D as n,Et as r,G as ee,O as te,P as i,Q as ne,S as a,T as o,W as s,Y as c,_ as l,_t as u,at as d,ct as f,d as re,f as ie,h as p,in as m,k as h,m as ae,q as g,tn as oe,w as _,x as v}from"./vue.runtime.esm-bundler-CACvpnko.js";import{T as se,h as y}from"./index-D5exsJys.js";import{r as b,t as x}from"./datetimeShanghai-F85iiY-2.js";import{t as S}from"./browser-CV5_KXzQ.js";import{t as ce}from"./audienceTicket-ByROqmS7.js";import{a as le,c as ue,l as de,o as fe,s as pe}from"./audience-sCSbyFK6.js";var C=S(),w=[`width`,`height`],T=h({__name:`QrCanvas`,props:{value:{},size:{default:180}},setup(e){let t=e,n=u(null);async function r(){let e=n.value;!e||!t.value||await(0,C.toCanvas)(e,t.value,{width:t.size,margin:1,errorCorrectionLevel:`M`,color:{dark:`#111827`,light:`#ffffff`}})}return d(()=>[t.value,t.size],()=>{r()}),s(()=>{r()}),(t,r)=>(g(),o(`canvas`,{ref_key:`canvasRef`,ref:n,width:e.size,height:e.size},null,8,w))}}),me={class:`container-fluid p-3 p-md-4 audience-admin-page`},he={class:`d-flex justify-content-between align-items-start flex-wrap gap-3 mb-3`},ge={class:`d-flex gap-2`},_e={key:0,class:`alert alert-warning`},ve={class:`audience-admin-kpis mb-3`,"aria-label":`实时数据概览`},ye={class:`audience-admin-panel mb-3`},be={class:`audience-session-cards row g-2`},xe=[`onClick`],Se={class:`audience-manage-card-top`},Ce={class:`session-type`},we=[`disabled`,`onClick`],Te={class:`session-date`},Ee={class:`session-number-row`},De={class:`session-progress`},Oe={class:`session-card-foot`},ke={key:0,class:`col-12 text-secondary small py-3`},Ae={class:`audience-admin-panel`},je={class:`audience-admin-panel-head audience-list-head`},Me={class:`d-flex gap-2 flex-wrap audience-list-actions`},Ne=[`disabled`],Pe={class:`audience-list-toolbar`},Fe={class:`audience-session-switcher`},Ie={class:`audience-session-tabs`,role:`tablist`,"aria-label":`切换场次`},Le=[`onClick`],Re={class:`filter-panel audience-list-filter`,role:`search`,"aria-label":`名单筛选`},ze={class:`audience-filter-controls`},Be={class:`table-responsive`},Ve={class:`table table-hover align-middle mb-0 audience-checkin-table`},He={key:0},Ue={class:`audience-name-cell`},We=[`disabled`,`onClick`],Ge={class:`audience-table-footer`},Ke={key:0,class:`d-flex gap-2`},qe=[`disabled`],Je=[`disabled`],Ye={id:`manageTicketModal`,class:`modal fade`,tabindex:`-1`,"aria-hidden":`true`},Xe={class:`modal-dialog modal-dialog-centered modal-sm`},Ze={class:`modal-content ticket-preview-card`},Qe={key:0,class:`modal-body text-center pt-0`},$e={class:`ticket-event-badge`},et={class:`mt-3 mb-1`},tt={class:`text-secondary small`},nt={class:`ticket-code`},rt={id:`manageCheckinQrModal`,class:`modal fade`,tabindex:`-1`,"aria-hidden":`true`},it={class:`modal-dialog modal-dialog-centered`},at={class:`modal-content checkin-entry-card`},ot={class:`modal-header border-0 pb-0`},st={class:`modal-body pt-2`},ct={key:0,"aria-label":`选择核销场次`},lt={class:`checkin-session-list`},ut=[`disabled`,`onClick`],dt={class:`checkin-session-region`},ft={class:`checkin-session-info`},pt={class:`checkin-session-count`},mt={key:1,class:`text-center`,"aria-label":`场次核销二维码`},ht={class:`checkin-entry-session`},gt=[`href`],_t={class:`checkin-entry-link`},vt=[`href`],E=h({__name:`ManageAudienceView`,setup(h){let S=i(`manageCompetitionId`,u(null)),C=i(`manageCompetitionSlug`,u(``)),w=i(`manageCompetitionName`,u(``)),E=u(!1),D=u(!1),O=u(null),k=u(`刷新数据`),A=u([]),j=u([]),M=u(null),N=u(null),P=u(``),F=u(``),I=u(1),L=u(15),R=u(0),z=u(null),B=u(`list`),V=u(null),H=u(`复制`),yt=v(()=>{let e=M.value;return!e||!e.registered_count?`0.0%`:`${(e.checkin_rate*100).toFixed(1)}%`}),bt=v(()=>M.value?.today_checked_in_count??0),xt=v(()=>A.value.find(e=>e.id===N.value)??null),U=v(()=>A.value.find(e=>e.id===V.value)??null),W=v(()=>C.value?ce(C.value,V.value):``);function G(e){return e.is_final?`总决赛`:`预选赛`}function K(e){let t=e.name||``;return t.includes(`上海`)?`上海`:t.includes(`苏州`)?`苏州`:t.includes(`深圳`)?`深圳`:t.slice(0,2)||`场次`}function St(e){let t=b(e.signup_start_at),n=b(e.signup_end_at);if(!t||!n)return``;let r=e=>e.slice(5,10).replace(`-`,`.`);return`报名 ${r(t)} — ${r(n)}`}function q(e){return e.capacity?Math.min(100,Math.round(e.registered_count/e.capacity*100)):0}function Ct(e){return e.registered_count?Math.round((e.checked_in_count??0)/e.registered_count*100):0}function wt(e){let t=e.match(/(\d{4})-(\d{2})-(\d{2})/);if(t)return new Date(`${t[1]}-${t[2]}-${t[3]}T23:59:59+08:00`);let n=e.match(/(\d{4})年(\d{1,2})月(\d{1,2})日/);return n?new Date(`${n[1]}-${String(n[2]).padStart(2,`0`)}-${String(n[3]).padStart(2,`0`)}T23:59:59+08:00`):null}function J(e){let t=wt(e.event_date_text||``);return t?t.getTime()<Date.now():e.status===`expired`}async function Y(){let e=S.value;e&&(A.value=await ue(e),(!N.value||!A.value.some(e=>e.id===N.value))&&(N.value=A.value[0]?.id??null))}async function X(){let e=S.value;e&&(M.value=await fe(e))}async function Z(e=I.value){let t=S.value;if(!t||!N.value){j.value=[],R.value=0;return}E.value=!0;try{let n=await pe(t,{page:e,per_page:L.value,keyword:P.value.trim()||void 0,audience_session_id:N.value,checkin_status:F.value||void 0});j.value=n.data,I.value=n.meta.current_page,L.value=n.meta.per_page,R.value=n.meta.total}catch(e){y.error(e instanceof Error?e.message:`加载观众报名失败`)}finally{E.value=!1}}async function Q(){try{await Y(),await Promise.all([X(),Z(1)])}catch(e){y.error(e instanceof Error?e.message:`加载失败`)}}async function Tt(){await Q(),k.value=`已更新`,window.setTimeout(()=>{k.value=`刷新数据`},900)}function Et(e){N.value=e}async function Dt(e){let t=S.value;if(!(!t||O.value)){O.value=e.id;try{let n=await de(t,e.id,{enabled:!e.enabled});A.value=A.value.map(e=>e.id===n.id?n:e)}catch(e){y.error(e instanceof Error?e.message:`更新场次失败`)}finally{O.value=null}}}async function Ot(){let e=S.value;if(e){D.value=!0;try{await le(e,{keyword:P.value.trim()||void 0,audience_session_id:N.value??void 0,checkin_status:F.value||void 0}),y.success(`已开始下载`)}catch(e){y.error(e instanceof Error?e.message:`导出失败`)}finally{D.value=!1}}}function kt(e){z.value=e;let t=document.getElementById(`manageTicketModal`);t&&se.getOrCreateInstance(t).show()}function At(){B.value=`list`,V.value=null;let e=document.getElementById(`manageCheckinQrModal`);e&&se.getOrCreateInstance(e).show()}function jt(e){J(e)||(V.value=e.id,B.value=`qr`)}async function Mt(){try{await navigator.clipboard.writeText(W.value),H.value=`已复制`}catch{H.value=`请长按复制`}window.setTimeout(()=>{H.value=`复制`},1400)}d(N,()=>{Z(1)}),d(S,()=>{N.value=null,Q()});let $=null;return s(()=>{Q(),$=window.setInterval(()=>{X(),Y()},8e3)}),ee(()=>{$!=null&&window.clearInterval($)}),(ee,i)=>{let s=ne(`loading`);return g(),o(`div`,me,[a(`div`,he,[i[7]||=a(`div`,null,[a(`h5`,{class:`mb-1 section-title`},`观众报名与入场核销`)],-1),a(`div`,ge,[a(`button`,{class:`btn btn-light border btn-sm`,type:`button`,onClick:Tt},m(k.value),1),a(`button`,{class:`btn btn-primary btn-sm`,type:`button`,onClick:At},`核销入口`)])]),r(S)?(g(),o(l,{key:1},[a(`section`,ve,[a(`article`,null,[i[8]||=a(`span`,null,`累计报名`,-1),a(`strong`,null,m(M.value?.registered_count??0),1),i[9]||=a(`small`,null,`人`,-1)]),a(`article`,null,[i[10]||=a(`span`,null,`已核销入场`,-1),a(`strong`,null,m(M.value?.checked_in_count??0),1),i[11]||=a(`small`,null,`人`,-1)]),a(`article`,null,[i[12]||=a(`span`,null,`综合到场率`,-1),a(`strong`,null,m(yt.value),1),i[13]||=a(`small`,null,`实时`,-1)]),a(`article`,null,[i[14]||=a(`span`,null,`今日新增核销`,-1),a(`strong`,null,m(bt.value),1),i[15]||=a(`small`,null,`人`,-1)])]),a(`section`,ye,[i[20]||=a(`div`,{class:`audience-admin-panel-head`},[a(`div`,null,[a(`h6`,null,`场次管理`)]),a(`span`,{class:`live-indicator`},[a(`i`),n(`数据实时更新`)])],-1),a(`div`,be,[(g(!0),o(l,null,c(A.value,t=>(g(),o(`div`,{key:t.id,class:`col-12 col-md-6 col-lg-3`},[a(`article`,{class:e([`audience-manage-card`,{"is-selected":t.id===N.value}]),onClick:e=>Et(t.id)},[a(`div`,Se,[a(`span`,Ce,m(G(t)),1),a(`button`,{class:e([`session-switch`,{"is-open":t.enabled&&t.status===`open`}]),type:`button`,disabled:O.value===t.id,onClick:p(e=>Dt(t),[`stop`])},[i[16]||=a(`i`,null,null,-1),n(m(t.enabled&&t.status===`open`?`报名中`:`未开放`),1)],10,we)]),a(`h6`,null,m(t.name),1),a(`p`,Te,m(t.event_date_text)+` · `+m(St(t)),1),a(`div`,Ee,[a(`div`,null,[i[17]||=a(`span`,null,`已报名`,-1),a(`strong`,null,[n(m(t.registered_count),1),a(`small`,null,` / `+m(t.capacity),1)])]),a(`div`,null,[i[19]||=a(`span`,null,`已到场`,-1),a(`strong`,null,[n(m(t.checked_in_count??0),1),i[18]||=a(`small`,null,`人`,-1)])])]),a(`div`,De,[a(`i`,{style:oe({width:`${q(t)}%`})},null,4)]),a(`div`,Oe,[a(`span`,null,`名额使用 `+m(q(t))+`%`,1),a(`b`,null,`到场率 `+m(Ct(t))+`%`,1)])],10,xe)]))),128)),A.value.length?_(``,!0):(g(),o(`div`,ke,`暂无观众场次,请先在赛事中心配置。`))])]),a(`section`,Ae,[a(`div`,je,[i[21]||=a(`div`,null,[a(`h6`,null,`报名与核销名单`)],-1),a(`div`,Me,[a(`button`,{class:`btn btn-light border btn-sm`,type:`button`,disabled:D.value,onClick:Ot},` 导出名单 `,8,Ne)])]),a(`div`,Pe,[a(`div`,Fe,[a(`div`,Ie,[(g(!0),o(l,null,c(A.value,t=>(g(),o(`button`,{key:`tab-${t.id}`,class:e([`audience-session-tab`,{"is-active":t.id===N.value}]),type:`button`,role:`tab`,onClick:e=>Et(t.id)},[n(m(t.name),1),a(`span`,null,m(t.registered_count),1)],10,Le))),128))])]),a(`div`,Re,[a(`div`,ze,[f(a(`input`,{"onUpdate:modelValue":i[0]||=e=>P.value=e,class:`form-control form-control-sm`,type:`search`,placeholder:`搜索姓名、手机号、单位或票号`,onKeydown:i[1]||=ae(p(e=>Z(1),[`prevent`]),[`enter`])},null,544),[[ie,P.value]]),f(a(`select`,{"onUpdate:modelValue":i[2]||=e=>F.value=e,class:`form-select form-select-sm`},[...i[22]||=[a(`option`,{value:``},`全部状态`,-1),a(`option`,{value:`checked_in`},`已入场`,-1),a(`option`,{value:`not_checked_in`},`待入场`,-1)]],512),[[re,F.value]]),a(`button`,{class:`btn btn-primary btn-sm`,type:`button`,onClick:i[3]||=e=>Z(1)},`查询`)])])]),f((g(),o(`div`,Be,[a(`table`,Ve,[i[25]||=a(`thead`,null,[a(`tr`,null,[a(`th`,null,`姓名`),a(`th`,null,`手机号`),a(`th`,null,`所属单位`),a(`th`,null,`票号`),a(`th`,null,`报名时间`),a(`th`,null,`入场状态`),a(`th`,null,`核销时间`),a(`th`,null,`操作`)])],-1),a(`tbody`,null,[j.value.length?_(``,!0):(g(),o(`tr`,He,[...i[23]||=[a(`td`,{colspan:`8`,class:`text-center text-secondary py-4`},`暂无符合条件的数据`,-1)]])),(g(!0),o(l,null,c(j.value,t=>(g(),o(`tr`,{key:t.id},[a(`td`,Ue,m(t.name),1),a(`td`,null,m(t.phone),1),a(`td`,null,m(t.company||`—`),1),a(`td`,null,[a(`code`,null,m(t.ticket_code||`—`),1)]),a(`td`,null,m(r(x)(t.registered_at)),1),a(`td`,null,[a(`span`,{class:e([`checkin-status`,t.checked_in?`checked`:`pending`])},[i[24]||=a(`i`,null,null,-1),n(m(t.checked_in?`已入场`:`待入场`),1)],2)]),a(`td`,null,m(t.checked_in_at?r(x)(t.checked_in_at):`—`),1),a(`td`,null,[a(`button`,{class:`btn btn-sm btn-outline-primary ticket-btn`,type:`button`,disabled:!t.ticket_code,onClick:e=>kt(t)},` 查看票码 `,8,We)])]))),128))])])])),[[s,E.value]]),a(`div`,Ge,[a(`span`,null,`显示 `+m(j.value.length)+` / `+m(R.value)+` 条`,1),R.value>L.value?(g(),o(`nav`,Ke,[a(`button`,{class:`btn btn-sm btn-light border`,type:`button`,disabled:I.value<=1,onClick:i[4]||=e=>Z(I.value-1)},` 上一页 `,8,qe),a(`button`,{class:`btn btn-sm btn-light border`,type:`button`,disabled:I.value*L.value>=R.value,onClick:i[5]||=e=>Z(I.value+1)},` 下一页 `,8,Je)])):_(``,!0)])])],64)):(g(),o(`div`,_e,`赛事信息加载失败,请检查链接 slug。`)),a(`div`,Ye,[a(`div`,Xe,[a(`div`,Ze,[i[27]||=a(`div`,{class:`modal-header border-0`},[a(`h5`,{class:`modal-title`},`电子入场票`),a(`button`,{class:`btn-close`,"data-bs-dismiss":`modal`,"aria-label":`关闭`})],-1),z.value?(g(),o(`div`,Qe,[a(`span`,$e,m(r(w)||`科创大赛`),1),a(`h6`,et,m(xt.value?.name||z.value.session_name),1),a(`p`,tt,m(z.value.name)+` · `+m(z.value.phone),1),r(C)&&z.value.ticket_code?(g(),t(T,{key:0,value:z.value.ticket_code,size:168},null,8,[`value`])):_(``,!0),a(`code`,nt,m(z.value.ticket_code),1),i[26]||=a(`p`,{class:`small text-secondary mt-3 mb-0`},`入场时请出示此码,每张票仅可核销一次`,-1)])):_(``,!0)])])]),a(`div`,rt,[a(`div`,it,[a(`div`,at,[a(`div`,ot,[a(`div`,null,[i[28]||=a(`span`,{class:`checkin-entry-eyebrow`},`核销人员入口`,-1),a(`h5`,{class:e([`modal-title mt-1`,{"visually-hidden":B.value===`qr`}])},m(B.value===`qr`?`手机扫码核销`:`选择核销场次`),3)]),i[29]||=a(`button`,{class:`btn-close`,"data-bs-dismiss":`modal`,"aria-label":`关闭`},null,-1)]),a(`div`,st,[B.value===`list`?(g(),o(`section`,ct,[i[33]||=a(`p`,{class:`checkin-entry-guide`},`当前共有多个地区与场次,请确认后进入对应核销通道。`,-1),a(`div`,lt,[(g(!0),o(l,null,c(A.value,t=>(g(),o(`button`,{key:`ck-${t.id}`,class:e([`checkin-session-option`,{"is-expired":J(t)}]),type:`button`,disabled:J(t),onClick:e=>jt(t)},[a(`span`,dt,m(K(t)),1),a(`span`,ft,[a(`strong`,null,m(t.name),1),a(`small`,null,m(G(t))+` · `+m(t.event_date_text),1)]),a(`span`,pt,[J(t)?(g(),o(l,{key:0},[i[30]||=a(`em`,null,`已过期`,-1),i[31]||=a(`small`,null,`不可进入核销`,-1)],64)):(g(),o(l,{key:1},[a(`b`,null,m(t.checked_in_count??0),1),n(` / `+m(t.registered_count)+` `,1),i[32]||=a(`small`,null,`已核销 / 已报名`,-1)],64))]),a(`i`,null,m(J(t)?`—`:`›`),1)],10,ut))),128))])])):(g(),o(`section`,mt,[a(`button`,{class:`checkin-entry-back`,type:`button`,onClick:i[6]||=e=>B.value=`list`},`‹ 返回场次列表`),a(`p`,ht,m(U.value?`${K(U.value)}地区 · ${U.value.name} · ${U.value.event_date_text}`:``),1),a(`a`,{class:`checkin-entry-qr`,href:W.value,target:`_blank`,"aria-label":`打开手机核销页面`},[te(T,{value:W.value,size:168},null,8,[`value`]),i[34]||=a(`i`,null,`核销`,-1)],8,gt),i[35]||=a(`p`,{class:`checkin-entry-tip`},[n(`请使用手机扫描二维码`),a(`br`),n(`进入该场次的核销工作台`)],-1),a(`div`,_t,[a(`span`,null,m(W.value),1),a(`button`,{type:`button`,onClick:Mt},m(H.value),1)]),a(`a`,{class:`btn btn-outline-primary btn-sm w-100 mt-3`,href:W.value,target:`_blank`},` 本机预览手机核销页 `,8,vt)]))])])])])])}}});export{E as default};