PageSourceSearch

https://bngts.com/_nuxt/tMA6Rz8Y.js

js bngts.com collected 2026-10-02 01:26:55 UTC 11,287 bytes, 1 lines download raw bytes

1import{d as Se,A as i,a6 as Ie,C as $e,T as Ce,b as g,o as m,e as a,g as z,k as Ne,i as r,j as c,t as S,I as re,D as ae,E as we,G as le,H as De,F as Re,r as Te,S as Le,a5 as Ae,p as Be}from"./DrlufBBD.js";import{_ as Ee}from"./C3sl8jeo.js";import{u as Me}from"./BYDppTfa.js";import"./CqkleIqs.js";import"./BkIdC3H5.js";const Oe=Ae(Ee),Ke={class:"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between"},Ue={key:0,class:"draft-actions","aria-label":"스트리머 행 편집 도구"},We=["disabled"],ze=["disabled"],Fe=["disabled"],Ve=["disabled"],Ge={key:0,class:"draft-help"},Pe=["role"],je={class:"search-controls"},Xe={class:"relative search-field"},He={class:"search-field"},Je=["value"],qe={key:2,class:"grid-state",role:"status"},Ye=["disabled"],C=40,I=200,oe=3,Qe=Se({__name:"ContentStreamerGrid",props:{contentId:{},shareToken:{default:""},userTone:{type:Boolean,default:!1},initialData:{default:null}},setup(se){const u=se;let ne=0;const R=[{label:"SOOP",value:"soop"},{label:"치지직",value:"chzzk"},{label:"YouTube",value:"youtube"},{label:"Twitch",value:"twitch"}],ie=new Set(R.map(({value:e})=>e)),de=e=>`${String(e.platform||"").toLowerCase()}:${String(e.streamerId||"").replace(/\s/g,"")}`,F=e=>{const t=Array.isArray(e.roles)?e.roles.map(String).slice(0,3):[];return{...e,key:`saved:${e.platform}:${e.streamerId}`,originalKey:`${e.platform}:${e.streamerId}`,roles:t,role1:t[0]||"",role2:t[1]||"",role3:t[2]||"",guild:e.guild||"",visible:e.visible!==!1}},V=e=>({key:`draft:${++ne}`,streamerId:"",platform:"soop",no:e,roles:[],role1:"",role2:"",role3:"",guild:"",visible:!0,userNick:"",fanCount:0,isLive:!1}),T=e=>Array.from({length:Math.min(oe,Math.max(0,I-e))},(t,o)=>V(e+o+1)),ue=e=>!e.originalKey&&!String(e.streamerId||"").trim()&&![e.role1,e.role2,e.role3].some(t=>String(t||"").trim())&&!String(e.guild||"").trim(),L=(u.initialData?.streamers||[]).map(F),$=i(L.map(e=>({...e}))),ce=["editor","owner","admin"].includes(u.initialData?.permission||"viewer"),l=i([...L,...ce?T(L.length):[]]),G=i(u.initialData?.permission||"viewer"),b=i(null),N=i(""),k=i(""),_=i(!u.initialData),x=i(""),n=i(!1),A=i(""),B=i(!1),P=i(null),E=Me(),f=c(()=>["editor","owner","admin"].includes(G.value)),j=e=>({platform:String(e.platform||"").toLowerCase(),streamerId:String(e.streamerId||"").replace(/\s/g,""),no:Number(e.no)||0,roles:[e.role1,e.role2,e.role3].map(t=>String(t||"").trim()).filter(Boolean),guild:String(e.guild||"").trim(),visible:e.visible!==!1}),M=c(()=>l.value.filter(e=>!ue(e))),me=c(()=>Array.from(new Set(l.value.flatMap(e=>[e.role1,e.role2,e.role3].map(t=>String(t||"").trim()).filter(Boolean)))).sort((e,t)=>e.localeCompare(t,"ko-KR"))),fe=c(()=>k.value?l.value.filter(e=>[e.role1,e.role2,e.role3].map(t=>String(t||"").trim()).includes(k.value)):l.value),w=c(()=>JSON.stringify(M.value.map(j))!==JSON.stringify($.value.map(j))),X=c(()=>w.value||n.value),H=c(()=>u.shareToken?{"x-content-share-token":u.shareToken}:void 0),p=()=>f.value&&!n.value,pe=c(()=>[{field:"platform",label:"플랫폼",options:R},{field:"isLive",label:"방송 상태",options:[{label:"LIVE",value:!0},{label:"OFFLINE",value:!1}]},{field:"visible",label:"노출 상태",options:[{label:"노출",value:!0},{label:"숨김",value:!1}]}]),ve=c(()=>[{field:"no",headerName:"순서",width:90,editable:p,cellDataType:"number"},{field:"platform",headerName:"플랫폼",width:110,editable:p,selectOptions:R},{field:"streamerId",headerName:"스트리머 ID",minWidth:160,editable:p},{field:"userNick",headerName:"닉네임",minWidth:150},{field:"fanCount",headerName:"애청자",width:110,cellDataType:"number"},{field:"role1",headerName:"역할 1",minWidth:130,editable:p},{field:"role2",headerName:"역할 2",minWidth:130,editable:p},{field:"role3",headerName:"역할 3",minWidth:130,editable:p},{field:"guild",headerName:"길드",editable:p},{field:"visible",headerName:"노출",width:100,editable:p,cellDataType:"boolean"},{field:"isLive",headerName:"라이브",width:100,cellDataType:"boolean"}]),J=c(()=>`/api/manage/contents/${encodeURIComponent(u.contentId)}/streamers`),q=(e,t)=>e?.data?.message||e?.message||t,d=(e,t=!1)=>{A.value=e,B.value=t},Y=e=>{const t=e.map(F);$.value=t.map(o=>({...o,roles:[...o.roles]})),l.value=[...t,...f.value?T(t.length):[]],b.value=null},ge=()=>{l.value=[...$.value.map(e=>({...e,roles:[...e.roles]})),...f.value?T($.value.length):[]],b.value=null,d("저장하지 않은 변경사항을 취소했습니다.")},be=()=>{if(!f.value||n.value)return;const e=Math.min(oe,I-l.value.length);if(e<=0){d(`스트리머 행은 최대 ${I}개까지 편집할 수 있습니다.`,!0);return}const t=Math.max(0,...M.value.map(o=>Number(o.no)||0))+1;l.value=[...l.value,...Array.from({length:e},(o,s)=>V(t+s))],d(`빈 행 ${e}개를 추가했습니다. 입력 후 수정하기를 눌러 저장하세요.`)},he=()=>{if(!b.value||n.value)return;const e=b.value;l.value=l.value.filter(t=>
1t.key!==e.key),b.value=null,d(e.originalKey?"행을 초안에서 제거했습니다. 수정하기를 누르면 실제 목록에서 삭제됩니다.":"빈 행을 제거했습니다.")},Q=async()=>{if(!(_.value&&u.initialData)){_.value=!0,x.value="";try{const e=await $fetch(J.value,{headers:H.value});G.value=e.permission,Y(e.streamers),d("스트리머 목록을 최신 상태로 불러왔습니다.")}catch(e){x.value=q(e,"잠시 후 다시 시도해 주세요."),l.value.length&&d(x.value,!0)}finally{_.value=!1}}},ye=async()=>{await Q(),x.value&&(await Le(),P.value?.focus())},ke=({data:e})=>{!f.value||n.value||(e.roles=[e.role1,e.role2,e.role3].map(t=>String(t||"")).filter(Boolean),e.streamerId=String(e.streamerId||""),(!e.originalKey||de(e)!==e.originalKey)&&(e.userNick=e.streamerId.replace(/\s/g,""),e.fanCount=0,e.isLive=!1),d("변경사항이 초안에 반영됐습니다. 수정하기를 눌러 저장하세요."))},_e=()=>{const e=M.value;if(e.length>I)return{error:`스트리머는 최대 ${I}명까지 저장할 수 있습니다.`};const t=new Set,o=[];for(const[h,v]of e.entries()){const y=h+1,O=String(v.platform||"").trim().toLowerCase(),K=String(v.streamerId||"").replace(/\s/g,"");if(!ie.has(O))return{error:`${y}행의 플랫폼을 확인해 주세요.`};if(!K)return{error:`${y}행의 스트리머 ID는 필수입니다.`};const U=Number(v.no);if(!Number.isInteger(U)||U<0)return{error:`${y}행의 순서는 0 이상의 정수여야 합니다.`};const D=[v.role1,v.role2,v.role3].map(W=>String(W||"").trim()).filter(Boolean);if(D.some(W=>Array.from(W).length>C))return{error:`${y}행의 각 역할은 ${C}자 이하여야 합니다.`};if(new Set(D).size!==D.length)return{error:`${y}행에 같은 역할을 중복 입력할 수 없습니다.`};const ee=String(v.guild||"").trim();if(Array.from(ee).length>C)return{error:`${y}행의 길드는 ${C}자 이하여야 합니다.`};const te=`${O}:${K}`;if(t.has(te))return{error:`${y}행의 스트리머가 목록에 중복되어 있습니다.`};t.add(te),o.push({platform:O,streamerId:K,no:U,roles:D,guild:ee||null,visible:v.visible!==!1})}const s=$.value.map(h=>({platform:String(h.platform).toLowerCase(),streamerId:String(h.streamerId)})).filter(h=>!t.has(`${h.platform}:${h.streamerId}`));return{rows:o,deleted:s}},xe=async()=>{if(!f.value||n.value||!w.value)return;const e=_e();if("error"in e){d(e.error,!0),E.error(e.error);return}n.value=!0,d("스트리머 변경사항을 저장하는 중입니다.");try{const t=await $fetch(`${J.value}/bulk`,{method:"PUT",headers:H.value,body:e});Y(t.rows),k.value="",d("스트리머 변경사항을 저장했습니다."),E.success("스트리머 변경사항을 저장했습니다.")}catch(t){const o=q(t,"스트리머 변경사항을 저장하지 못했습니다.");d(o,!0),E.error(o)}finally{n.value=!1}},Z=e=>{X.value&&(e.preventDefault(),e.returnValue="")};return Ie(()=>X.value?window.confirm("입력 중이거나 저장이 완료되지 않은 스트리머 변경사항이 있습니다. 이 페이지를 나갈까요?"):!0),$e(()=>{u.initialData||Q(),window.addEventListener("beforeunload",Z)}),Ce(()=>window.removeEventListener("beforeunload",Z)),(e,t)=>{const o=Oe;return m(),g("section",{class:re(["streamer-grid space-y-4",{"user-tone":u.userTone}])},[a("div",Ke,[t[4]||(t[4]=a("div",null,[a("h2",{class:"text-xl font-bold text-dark-text"},"스트리머"),a("p",{class:"text-sm text-dark-text-secondary"}," 셀 클릭 후 Enter 또는 더블 클릭으로 수정합니다. 역할과 길드는 자유롭게 입력할 수 있습니다. ")],-1)),r(f)?(m(),g("div",Ue,[a("button",{type:"button",class:"action-button rounded-lg border border-dark-border bg-dark-surface px-4 py-2 text-dark-text",disabled:r(n)||r(l).length>=I,onClick:t[0]||(t[0]=s=>be())}," 빈 행 3개 추가 ",8,We),a("button",{type:"button",disabled:!r(b)||r(n),class:"action-button rounded-lg border border-red-700 px-4 py-2 text-red-300 disabled:opacity-40",onClick:he}," 선택 행 제거 ",8,ze),a("button",{type:"button",class:"action-button rounded-lg border border-dark-border bg-dark-surface px-4 py-2 text-dark-text",disabled:!r(w)||r(n),onClick:ge}," 변경 취소 ",8,Fe),a("button",{type:"button",class:"action-button rounded-lg bg-primary px-4 py-2 font-medium text-white",disabled:!r(w)||r(n),onClick:xe},S(r(n)?"저장 중…":"수정하기"),9,Ve)])):z("",!0)]),r(f)?(m(),g("p",Ge," 빈 행에 플랫폼, 스트리머 ID, 역할 1~3, 길드를 연속 입력한 뒤 수정하기를 누르세요. 역할은 최대 3개, 각 역할과 길드는 "+S(C)+"자까지이며 빈 값도 허용됩니다. 표시 이름은 저장 후 조회된 닉네임으로 자동 반영됩니다. ")):z("",!0),r(A)?(m(),g("p",{key:1,class:re(["page-message",{error:r(B)}]),role:r(B)?"alert":"status","aria-live":"polite"},S(r(A)),11,Pe)):z("",!0),a("div",je,[a("div",Xe,[t[5]||(t[5]=a("label",{for:"content-streamer-search"},"스트리머 목록 검색",-1)),ae(a("input",{id:"content-streamer-search","onUpdate:modelValue":t[1]||(t[1]=s=>le(N)?N.value=s:null),placeholder:"세 역할을 포함한 그리드 전체 검색",type:"search",class:"w-full rounded-lg border border-dark-border bg-dark-surface px-4 py-2 text-dark-text"},null,512),[[we,r(N)]])]),a("label",He,[t[7]||(t[7]=a("span",null,"역할 필터",-1)),ae(a("select",{"onUpdate:modelValue":t[2]||(t[2]=s=>le(k)?k.value=s:null),class:"rounded-lg border border-dark-border bg-dark-surface px-3 py-2 text-dark-text"},[t[6]||(t[6]=a("option",{value:""},"전체 역할",-1)),(m(!0),g(Re,null,Te(r(me),s=>(m(),g("option",{key:s,value:s},S(s),9,Je))),128))],512),[[De,r(k)]])])]),r(_)&&!r(l).length?(m(),g("div",qe," 스트리머 목록을 불러오는 중입니다. ")):r(x)&&!r(l).length?(m(),g("div",{key:3,ref_key:"loadErrorAlert",ref:P,class:"grid-state grid-error",role:"alert",tabindex:"-1"},[t[8]||(t[8]=a("strong",null,"스트리머 목록을 불러오지 못했습니다.",-1)),a("span",null,S(r(x)),1),a("button",{type:"button",disabled:r(_),onClick:ye},S(r(_)?"다시 불러오는 중…":"다시 시도"),9,Ye)],512)):(m(),Ne(o,{key:4,rows:r(fe),columns:r(ve),search:r(N),filters:r(pe),"row-id":"key",onSelectionChanged:t[3]||(t[3]=s=>b.value=s),onCellChanged:ke},null,8,["rows","columns","search","filters"]))],2)}}}),lt=Object.assign(Be(Qe,[["__scopeId","data-v-20f7493f"]]),{__name:"AdminContentStreamerGrid"});export{lt as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.