PageSourceSearch

https://www.superschool.link/assets/StudentBatchUpdatePage-YKUVS8J2.js

js superschool.link collected 2026-09-25 03:20:45 UTC 14,673 bytes, 6 lines download raw bytes

1import{a as Z,r as f,j as e}from"./vendor-react-wpXF2Dvf.js";import{a as ee}from"./vendor-query-fYiNqPbw.js";import{bh as re,bi as se,bm as te,aL as ne,bp as ae,aG as ie}from"./main-BDOnhuy4.js";import{a2 as x,A as C,Y as b,a0 as j,q as le,u as oe,R as de,k as l,T as G,b5 as D}from"./superschool-ui-DXud_9UO.js";import{A as k,F as ce}from"./ActionButtonPanel-CSDYB4NV.js";import{L as ue}from"./LoadingDialog-BqlYR8XZ.js";import{S as me,B as he}from"./BulkApplyConfirm-B15D3pGy.js";import{e as pe}from"./download-excel-CDUeOdkM.js";import{b2 as B,aD as R,a8 as fe,S as g}from"./superschool-sdk-BmtTBy0Q.js";import{r as ge}from"./readXlsxFileBrowser-DEJ8AfCu.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./vendor-react-pdf-3ecbNM6a.js";import"./vendor-i18n-BUJziXlB.js";import"./vendor-radix-kOLjYi5a.js";import"./vendor-recharts-DgZqauKz.js";import"./vendor-tiptap-DtaI5KiI.js";import"./ImageNFileUpload-BGwuA8lv.js";import"./addfile-eQB3_APc.js";import"./fileNameGuard-DsoHfV4f.js";import"./xlsx-Bi4a-sJm.js";const A=["로그인 ID(이 컬럼의 데이터는 수정하지 마세요.)","이전학년(이 컬럼의 데이터는 수정하지 마세요.)","이전반(이 컬럼의 데이터는 수정하지 마세요.)","이전번호(이 컬럼의 데이터는 수정하지 마세요.)","이름","학년(숫자만)","반(숫자만)","번호(숫자만)"],z=["이전 학년(숫자만)","이전 반(숫자만)","이전 번호(숫자만)","이름","학년(숫자만)","반(숫자만)","번호(숫자만)"];function Ue(){const o=Z(),u=ee(),[t,c]=f.useState(null),[r,y]=f.useState(B().toString()),[O,N]=f.useState(!1),[K,S]=f.useState(!1),[T,_]=f.useState(!1),[U,w]=f.useState(new Set),[$,E]=f.useState(!1),P=a=>{L(a)},{data:xe,refetch:M}=R().useGetUnassignedStudentList(Number(r),{query:{enabled:!1,queryKey:["/api-v2/users/management/unassigned/student/list",r]}}),{mutate:Y}=R().useStudentKlassBulkUpsert({onSuccess:async()=>{await u.invalidateQueries({queryKey:["/api-v2/student/list"]}),C({message:`${r}학년도 ${t==null?void 0:t.list.length}명의 신입생 일괄 편성이 완료되었습니다.`,type:"success"}),o(`/admin/student?year=${r}`)},onError:a=>{var s,n;x({title:"학생 일괄 진급/편성에 실패하였습니다.",description:(n=(s=a==null?void 0:a.data)==null?void 0:s.message)==null?void 0:n.ko,confirmText:"확인"})}}),q=async()=>{if(!t||t.type!=="forNextGrade")return;const a=t.list,s=[];let n=0;C({message:"학생 일괄 진급/편성을 진행중입니다. 잠시만 기다려 주세요.",type:"info"}),_(!0);const d=a.reduce((i,p,m)=>{const h=`${p.newGrade}-${p.newKlass}`;return i[h]||(i[h]=[]),i[h].push({item:p,index:m}),i},{});if(await Promise.all(Object.entries(d).map(async([i,p])=>{var m,h;for(const{item:v,index:X}of p)try{await ae({...v,adventYear:Number(r)})}catch(J){s[X]=((h=(m=J.response)==null?void 0:m.data)==null?void 0:h.message)||"처리 중 오류가 발생했습니다.",n++}})),_(!1),n===0)await u.invalidateQueries({queryKey:["/api-v2/student/list"]}),C({message:`${r}학년도 ${t==null?void 0:t.list.length}명의 재학생 일괄 진급/편성이 완료되었습니다.`,type:"success"}),o(`/admin/student?year=${r}`);else{const i=new Set;s.forEach((m,h)=>{m&&i.add(h)}),w(i);const p=s.find(m=>m)||"처리 중 오류가 발생했습니다.";x({title:"학생 일괄 진급/편성을 실패하였습니다.",description:p,confirmText:"확인"})}},V=async()=>{if(t){if(t.type==="forFreshmen"&&t.list.filter(s=>!s.loginId||!s.newGrade||s.newKlass===null||s.newStudentNumber===null).length>0){const s=new Set;t.list.forEach((n,d)=>{(!n.loginId||!n.newGrade||n.newKlass===null||n.newStudentNumber===null)&&s.add(d)}),w(s),x({title:"입력하지 않은 필수 항목이 있습니다.",description:"로그인 ID, 학년, 반, 번호를 모두 입력해 주세요.",confirmText:"확인"});return}if(t.type==="forNextGrade"&&t.list.filter(s=>!s.oldGrade||!s.oldKlass||!s.oldStudentNumber||!s.name||!s.newGrade||!s.newKlass||!s.newStudentNumber).length>0){const s=new Set;t.list.forEach((n,d)=>{(!n.oldGrade||!n.oldKlass||!n.oldStudentNumber||!n.name||!n.newGrade||!n.newKlass||!n.newStudentNumber)&&s.add(d)}),w(s),x({title:"입력하지 않은 필수 항목이 있습니다.",description:"이전 학년, 이전 반, 이전 번호, 이름, 학년, 반, 번호를 모두 입력해 주세요.",confirmText:"확인"});return}E(!0)}},H=a=>a.length===A.length&&A.every((s,n)=>
1a[n]===s)?{isValid:!0,type:"forFreshmen"}:a.length===z.length&&z.every((s,n)=>a[n]===s)?{isValid:!0,type:"forNextGrade"}:{isValid:!1,type:null},Q=a=>a.map(([s,n,d,i,p,m,h,v])=>({loginId:s,oldGrade:n,oldKlass:d,oldStudentNumber:i,name:p,newGrade:m,newKlass:h,newStudentNumber:v})),W=a=>a.map(([s,n,d,i,p,m,h])=>({oldGrade:Number(s),oldKlass:Number(n),oldStudentNumber:Number(d),name:String(i),newGrade:Number(p),newKlass:Number(m),newStudentNumber:Number(h)}));async function L(a){try{w(new Set);const[s,...n]=await ge(a),d=H(s);if(!d.isValid){x({title:"올바른 양식으로 작성해주세요.",description:"양식 다운로드 후 다시 시도해주세요.",confirmText:"확인"});return}if(d.type==="forFreshmen"){const i=Q(n);c({type:"forFreshmen",list:i})}else if(d.type==="forNextGrade"){const i=W(n);c({type:"forNextGrade",list:i})}}catch(s){console.error("엑셀 파일 읽기 오류:",s),alert(`엑셀파일을 읽는 중 오류가 발생했습니다.
2양식 다운로드하여 새로운 엑셀 파일을 작성하신 후,
3다시 시도해주세요.`)}}return e.jsxs(re,{headerChildren:e.jsx(e.Fragment,{children:e.jsxs(b,{direction:"col",gap:"2",items:"start",justify:"center",children:[e.jsx(l,{variant:"title",className:"text-[32px] font-bold",children:"학생 일괄 진급/편성"}),e.jsx(l,{size:"sm",weight:"sm",variant:"dim",children:"엑셀 파일을 업로드하여 학생의 학년, 반, 번호를 일괄로 수정할 수 있습니다."})]})}),children:[e.jsxs(se,{children:[e.jsxs(b,{gap:"6",className:"mb-6",children:[e.jsx(k,{title:"엑셀 양식 다운로드",description:"학생 일괄 진급/편성을 위한 엑셀 양식을 다운로드해 주세요.",button:e.jsx(j,{iconName:"ssDownload",variant:"solid",color:"secondary",position:"front",stroke:!0,size:"lg",iconColor:"white",customSize:{width:"12px",height:"12px"},onClick:()=>N(!0),className:"shrink-0",children:"엑셀 다운로드"})}),e.jsx(k,{title:"수정 파일 명단 업로드",description:"학적 수정이 완료된 엑셀 파일을 업로드해 주세요.",button:t&&t.list.length>0?e.jsxs(le,{children:[e.jsx(oe,{className:"shrink-0",children:e.jsx(j,{iconName:"Plus",variant:"solid",color:"secondary",size:"lg",position:"front",stroke:!0,strokeWidth:2,onClick:()=>S(!0),children:"엑셀 파일 재업로드"})}),e.jsx(de,{side:"bottom",align:"end",children:e.jsx(l,{size:"sm",weight:"sm",className:"text-white",children:"학생 리스트가 새 파일로 덮어쓰기 됩니다."})})]}):e.jsx(j,{iconName:"Plus",variant:"solid",color:"secondary",position:"front",stroke:!0,size:"lg",iconColor:"white",onClick:()=>S(!0),className:"shrink-0",children:"엑셀 파일 업로드"})})]}),e.jsx(te,{children:e.jsxs(b,{direction:"col",justify:"between",gap:"4",className:"h-full p-6",children:[e.jsxs(b,{items:"start",justify:"between",gap:"2",children:[e.jsxs(b,{items:"center",gap:"2",children:[t&&(t.type==="forFreshmen"?e.jsx(G,{title:"신입생",size:"lg",variant:"sub",color:"primary",className:"border-primary-400 h-8 shrink-0 border"}):e.jsx(G,{title:"재학생",size:"lg",variant:"sub",color:"primary",className:"border-primary-400 h-8 shrink-0 border"})),t&&t.list.length>0&&e.jsxs(l,{size:"md",weight:"md",className:"shrink-0 text-gray-600",children:["총 ",e.jsxs("span",{className:"font-bold",children:[t.list.length,"명"]})]})]}),e.jsxs(b,{direction:"col",gap:"2",items:"end",children:[e.jsx(j,{iconName:"Plus",variant:"solid",color:"primary",size:"sm",position:"front",stroke:!0,strokeWidth:2,iconColor:"white",className:"shrink-0",disabled:!t,onClick:V,children:"일괄 진급/편성 적용"}),t&&e.jsx(l,{variant:"primary",children:"* 엑셀 파일 업로드 후 [일괄 진급/편성 적용] 버튼을 꼭 눌러주세요."})]})]}),e.jsx(be,{excelData:t,invalidStudentIndices:U})]})})]}),e.jsx(me,{isOpen:O,setIsOpen:N,text:{title:"학생 일괄 진급/편성",description:"업로드할 파일의 형식을 선택해주세요",leftButton:{title:"신입생 학번 부여",description:`학번이 없는 학생에게 학번 등록
4*'신입생 학번 부여'의 경우 선택한 학년도 학생 명단이 다운로드 됩니다.`},rightButton:{title:"재학생 진급 처리",description:"기존 학생의 학년 학번 수정"}},onLeftButtonClick:async()=>{const{data:a}=await M(),s=a??[];if(s.length>0){const d=`로그인 ID(이 컬럼의 데이터는 수정하지 마세요.),이전학년(이 컬럼의 데이터는 수정하지 마세요.),이전반(이 컬럼의 데이터는 수정하지 마세요.),이전번호(이 컬럼의 데이터는 수정하지 마세요.),이름,학년(숫자만),반(숫자만),번호(숫자만)
5`+fe(s,[i=>i.grade,i=>i.number]).map(i=>[i.email,i.grade,"미지정",`${i.number} (임시)`,i.name].join(",")).join(`
6`);pe(d,"(슈퍼스쿨양식)학생_일괄편성_신입생_학번_부여")}else x({title:`${r}학년도에 등록된 신입생 명단이 없습니다.`,description:"'일괄 추가'를 먼저 진행해 주세요.",confirmText:"확인"});N(!1)},onRightButtonClick:()=>{ne.saveAs("https://kr.object.gov-ncloudstorage.com/superschool/storage/%28%EC%8A%88%ED%8D%BC%EC%8A%A4%EC%BF%A8%EC%96%91%EC%8B%9D%29%ED%95%99%EC%83%9D_%EC%9D%BC%EA%B4%84%ED%8E%B8%EC%84%B1_%EC%A7%84%EA%B8%89%EC%83%9D_%ED%95%99%EB%B2%88_%EC%9E%AC%EB%B0%B0%EC%A0%95.xlsx","(슈퍼스쿨양식)학생_일괄편성_재학생_진급_처리.xlsx"),N(!1)}}),K&&e.jsx(ce,{isOpen:K,setIsOpen:S,title:"학생 일괄 진급/편성",description:"학생 일괄 진급/편성 양식 다운로드 및 작성 후 업로드 해주세요.",accept:".xlsx",handleFileUpload:P}),e.jsx(ue,{isOpen:T,setIsOpen:_,title:"등록중 ...",description:"학생 일괄 진급/편성 중입니다. 페이지를 벗어나거나 새로고침하지 마세요."}),e.jsx(he,{isOpen:$,currentSchoolYear:B(),selectedSchoolYear:Number(r),setSelectedSchoolYear:a=>y(a.toString()),description:`${r}학년도에 총 ${t==null?void 0:t.list.length}명 학생을 일괄 진급/편성합니다.`,setIsOpen:E,onConfirm:()=>{t&&t.type==="forFreshmen"?Y({data:{schoolYear:Number(r),list:t.list.map(a=>({loginId:a.loginId,grade:a.newGrade,klass:a.newKlass,studentNumber:a.newStudentNumber}))}}):q()}})]})}function I(){return e.jsxs(b,{direction:"col",gap:"12",items:"center",justify:"center",className:"h-full",children:[e.jsx("img",{src:ie,className:"h-36 w-36 object-contain"}),e.jsxs(l,{weight:"md",className:"text-gray-600",children:["양식을 다운로드한 뒤 학생 명단을 작성하여",e.jsx("br",{}),"업로드해 주세요."]})]})}function ye({excelList:o,invalidStudentIndices:u}){const t=[{header:"로그인 ID",accessorKey:"loginId",size:120,cellRenderer:r=>e.jsx(l,{children:r??"-"})},{header:"이전 학년",accessorKey:"oldGrade",size:100,cellRenderer:r=>e.jsx(l,{children:r??"-"})},{header:"이전 반",accessorKey:"oldKlass",size:100,cellRenderer:r=>e.jsx(l,{children:r??"-"})},{header:"이전 번호",accessorKey:"oldStudentNumber",size:120,cellRenderer:r=>e.jsx(l,{children:r??"-"})},{header:"이름",accessorKey:"name",size:120,cellRenderer:r=>e.jsx(l,{children:r||"-"})},{header:"학년",accessorKey:"newGrade",size:100,cellRenderer:r=>e.jsx(l,{children:r||"-"})},{header:"반",accessorKey:"newKlass",size:100,cellRenderer:r=>e.jsx(l,{children:r??"-"})},{header:"번호",accessorKey:"newStudentNumber",size:100,cellRenderer:r=>e.jsx(l,{children:r??"-"})}],c=f.useMemo(()=>o==null?void 0:o.map((r,y)=>({index:y,loginId:r.loginId,oldGrade:r.oldGrade,oldKlass:r.oldKlass,oldStudentNumber:r.oldStudentNumber,name:r.name,newGrade:r.newGrade,newKlass:r.newKlass,newStudentNumber:r.newStudentNumber,className:u.has(y)?"bg-primary-100":""})),[o,u]);return e.jsx(D,{columns:t,data:c,manualPagination:!0,customEmptyState:e.jsx(I,{}),className:g("flex min-h-0 flex-1 flex-col overflow-hidden [&_div]:rounded-none [&_div]:border-x-0! [&_div]:border-gray-100",c.length===0?"h-full [&_div]:border-b-0!":""),tableWrapperClassName:g(c.length===0?"h-full":""),tableClassName:g(c.length===0?"h-full":""),headerClassName:"[&_th]:text-center [&_th]:text-gray-500 [&_th]:font-medium [&_tr:hover]:!bg-transparent [&_tr]:border-gray-100",bodyClassName:g("[&_td]:!px-4 [&_td]:!py-2 [&_td]:text-center [&_tr]:border-gray-100 [&_tr:hover]:!bg-white [&_tr.bg-primary-100:hover]:!bg-primary-100",c.length===0?"h-full":"")})}function F({excelList:o,invalidStudentIndices:u}){const t=[{header:"이전 학년",accessorKey:"oldGrade",size:100,cellRenderer:r=>e.jsx(l,{children:r||"-"})},{header:"이전 반",accessorKey:"oldKlass",size:100,cellRenderer:r=>e.jsx(l,{children:r||"-"})},{header:"이전 번호",accessorKey:"oldStudentNumber",size:100,cellRenderer:r=>e.jsx(l,{children:r||"-"})},{header:"이름",accessorKey:"name",size:120,cellRenderer:r=>e.jsx(l,{children:r||"-"})},{header:"학년",accessorKey:"newGrade",size:100,cellRenderer:r=>e.jsx(l,{children:r||"-"})},{header:"반",accessorKey:"newKlass",size:100,cellRenderer:r=>e.jsx(l,{children:r||"-"})},{header:"번호",accessorKey:"newStudentNumber",size:100,cellRenderer:r=>e.jsx(l,{children:r||"-"})}],c=f.useMemo(()=>o==null?void 0:o.map((r,y)=>({index:y,oldGrade:r.oldGrade,oldKlass:r.oldKlass,oldStudentNumber:r.oldStudentNumber,name:r.name,newGrade:r.newGrade,newKlass:r.newKlass,newStudentNumber:r.newStudentNumber,className:u.has(y)?"bg-primary-100":""})),[o,u]);return e.jsx(D,{columns:t,data:c,manualPagination:!0,customEmptyState:e.jsx(I,{}),className:g("flex min-h-0 flex-1 flex-col overflow-hidden [&_div]:rounded-none [&_div]:border-x-0! [&_div]:border-gray-100",c.length===0?"h-full [&_div]:border-b-0!":""),tableWrapperClassName:g(c.length===0?"h-full":""),tableClassName:g(c.length===0?"h-full":""),headerClassName:"[&_th]:text-center [&_th]:text-gray-500 [&_th]:font-medium [&_tr:hover]:!bg-transparent [&_tr]:border-gray-100",bodyClassName:g("[&_td]:!px-4 [&_td]:!py-2 [&_td]:text-center [&_tr]:border-gray-100 [&_tr:hover]:!bg-white [&_tr.bg-primary-100:hover]:!bg-primary-100",c.length===0?"h-full":"")})}function be({excelData:o,invalidStudentIndices:u}){return o?o.type==="forFreshmen"?e.jsx(ye,{excelList:o.list,invali
6dStudentIndices:u}):e.jsx(F,{excelList:o.list,invalidStudentIndices:u}):e.jsx(F,{excelList:(o==null?void 0:o.list)??[],invalidStudentIndices:u})}export{Ue as StudentBatchUpdatePage};

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.