(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[920],{754:(e,t,a)=>{"use strict";a.r(t),a.d(t,{default:()=>c});var n=a(1333),l=a(8166),r=a(4705),s=a(8312),i=a(2787);function o(e){let{config:t}=e,[a,l]=(0,r.useState)([]),[o,d]=(0,r.useState)(0),[c,m]=(0,r.useState)(1),[u,x]=(0,r.useState)(""),[p,h]=(0,r.useState)(!1),[b,y]=(0,r.useState)(""),[g,f]=(0,r.useState)(!1),[v,j]=(0,r.useState)(null),[N,w]=(0,r.useState)({}),[S,_]=(0,r.useState)(!1),k=t.fields.filter(e=>!e.hideInTable),C=(0,r.useCallback)((e,a)=>{h(!0),y(""),s.F.listResource(t.key,{page:e,pageSize:20,keyword:a}).then(e=>{l(e.items),d(e.total),m(e.page)}).catch(e=>y(e.message)).finally(()=>h(!1))},[t.key]);(0,r.useEffect)(()=>{x(""),C(1,"")},[t.key,C]);let T=Math.max(1,Math.ceil(o/20));return(0,n.jsxs)("div",{className:"space-y-4",children:[(0,n.jsx)(i.$T,{message:b}),(0,n.jsxs)(i.Zp,{title:"".concat(t.title,"(共 ").concat(o," 条)"),action:(0,n.jsxs)("div",{className:"flex gap-2",children:[(0,n.jsx)(i.pd,{value:u,onChange:x,placeholder:"搜索…"}),(0,n.jsx)(i.$n,{variant:"ghost",onClick:()=>C(1,u),children:"搜索"}),(0,n.jsx)(i.$n,{onClick:()=>{let e={};for(let r of t.fields){var a,n,l;e[r.name]="select"===r.type?String(null!=(l=null==(n=r.options)||null==(a=n[0])?void 0:a.value)?l:1):""}w(e),j(null),f(!0)},children:"新建"})]}),children:[(0,n.jsx)("p",{className:"mb-3 text-xs text-gray-500",children:t.description}),p?(0,n.jsx)("div",{className:"py-10 text-center text-sm text-gray-400",children:"加载中…"}):0===a.length?(0,n.jsx)(i.Sv,{}):(0,n.jsx)("div",{className:"overflow-x-auto",children:(0,n.jsxs)("table",{className:"w-full text-sm",children:[(0,n.jsx)("thead",{children:(0,n.jsxs)("tr",{className:"border-b border-gray-200 text-left text-xs text-gray-500",children:[(0,n.jsx)("th",{className:"px-2 py-2",children:"ID"}),k.map(e=>(0,n.jsx)("th",{className:"px-2 py-2",children:e.label},e.name)),(0,n.jsx)("th",{className:"px-2 py-2 text-right",children:"操作"})]})}),(0,n.jsx)("tbody",{children:a.map(e=>(0,n.jsxs)("tr",{className:"border-b border-gray-100 hover:bg-gray-50",children:[(0,n.jsx)("td",{className:"px-2 py-2 text-gray-400",children:String(e.id)}),k.map(t=>{let a=function(e,t){let a=t[e.name];if(null==a||""===a)return"—";if("select"===e.type&&e.options){let t=e.options.find(e=>e.value===Number(a));return t?t.label:String(a)}return"date"===e.type?String(a).slice(0,10):String(a)}(t,e);return(0,n.jsx)("td",{className:"max-w-[280px] truncate px-2 py-2",title:a,children:a},t.name)}),(0,n.jsxs)("td",{className:"whitespace-nowrap px-2 py-2 text-right",children:[(0,n.jsx)(i.$n,{variant:"ghost",onClick:()=>(e=>{let a={};for(let n of t.fields)a[n.name]=function(e,t){if(null==t)return"";if("date"===e.type){let e=new Date(String(t));return isNaN(e.getTime())?"":e.toISOString().slice(0,10)}return String(t)}(n,e[n.name]);w(a),j(e),f(!0)})(e),children:"编辑"})," ",(0,n.jsx)(i.$n,{variant:"danger",onClick:()=>{window.confirm("确定删除这条记录吗?此操作不可撤销。")&&(y(""),s.F.deleteResource(t.key,Number(e.id)).then(()=>C(c,u)).catch(e=>y(e.message)))},children:"删除"})]})]},String(e.id)))})]})}),(0,n.jsxs)("div",{className:"mt-4 flex items-center justify-between text-sm text-gray-500",children:[(0,n.jsxs)("span",{children:["第 ",c," / ",T," 页"]}),(0,n.jsxs)("div",{className:"flex gap-2",children:[(0,n.jsx)(i.$n,{variant:"ghost",disabled:c<=1,onClick:()=>C(c-1,u),children:"上一页"}),(0,n.jsx)(i.$n,{variant:"ghost",disabled:c>=T,onClick:()=>C(c+1,u),children:"下一页"})]})]})]}),(0,n.jsx)(i.aF,{open:g,title:"".concat(v?"编辑":"新建").concat(t.title),onClose:()=>f(!1),footer:(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(i.$n,{variant:"ghost",onClick:()=>f(!1),children:"取消"}),(0,n.jsx)(i.$n,{onClick:()=>{let e=function(e,t){let a={};for(let n of e){let e=t[n.name];void 0!==e&&(""===e?a[n.name]="number"===n.type?0:null:"number"===n.type||"select"===n.type?a[n.name]=Number(e):a[n.name]=e)}return a}(t.fields.filter(e=>!(v&&e.immutable)),N);_(!0),y(""),(v?s.F.updateResource(t.key,Number(v.id),e):s.F.createResource(t.key,e)).then(()=>{f(!1),C(c,u)}).catch(e=>y(e.message)).finally(()=>_(!1))},disabled:S,children:S?"保存中…":"保存"})]}),children:(0,n.jsx)("div",{className:"space-y-3",children:t.fields.map(e=>{var t,a,l,r;let s=!!(v&&e.immutable);return(0,n.jsxs)("div",{children:[(0,n.jsxs)("label",{className:"mb-1 block text-sm text-gray-600",children:[e.label,e.immutable&&(0,n.jsx)("span",{className:"ml-2 text-xs text-orange-500",children:"创建后不可修改"})]}),"textarea"===e.type?(0,n.jsx)(i.TM,{value:null!=(t=N[e.name])?t:"",onChange:t=>w({...N,[e.name]:t})}):"select"===e.type?(0,n.jsx)(i.l6,{value:null!=(a=N[e.name])?a:"",onChange:t=>w({...N,[e.name]:t}),options:null!=(l=e.options)?l:[]}):(0,n.jsx)("div",{className:s?"pointer-events-none opacity-60":"",children:(0,n.jsx)(i.pd,{value:null!=(r=N[e.name])?r:"",onChange:t=>w({...N,[e.name]:t}),type:"number"===e.type?"number":"date"===e.type?"date":"text",placeholder:e.placeholder})}),e.hint&&(0,n.jsx)("p",{className:"mt-1 text-xs text-gray-400",children:e.hint})]},e.name)})})})]})}var d=a(4357);function c(){var e;let t=(0,l.useParams)(),a=null!=(e=null==t?void 0:t.resource)?e:"",r=(0,d.MW)(a);return r?(0,n.jsxs)("div",{className:"space-y-4",children:[(0,n.jsx)("h1",{className:"text-lg font-semibold text-gray-900",children:r.title}),(0,n.jsx)(o,{config:r})]}):(0,n.jsxs)("div",{className:"rounded-lg border border-gray-200 bg-white p-6 text-sm text-gray-500",children:["未知的资源类型:",a]})}},1910:(e,t,a)=>{"use strict";a.d(t,{L:()=>s,M3:()=>i,WG:()=>r,gf:()=>l});let n="yelay_admin_token";function l(){var e;return null!=(e=window.localStorage.getItem(n))?e:""}function r(e){window.localStorage.setItem(n,e)}function s(){window.localStorage.removeItem(n)}function i(){return""!==l()}},2787:(e,t,a)=>{"use strict";a.d(t,{$T:()=>c,$n:()=>l,Sv:()=>m,TM:()=>s,Zp:()=>o,aF:()=>d,l6:()=>i,pd:()=>r});var n=a(1333);function l(e){let{children:t,onClick:a,variant:l="primary",disabled:r,type:s="button"}=e;return(0,n.jsx)("button",{type:s,onClick:a,disabled:r,className:"rounded-md px-3 py-1.5 text-sm font-medium transition disabled:cursor-not-allowed disabled:opacity-50 ".concat({primary:"bg-blue-600 text-white hover:bg-blue-700",ghost:"bg-white text-gray-700 border border-gray-300 hover:bg-gray-50",danger:"bg-red-600 text-white hover:bg-red-700"}[l]),children:t})}function r(e){let{value:t,onChange:a,placeholder:l,type:r="text"}=e;return(0,n.jsx)("input",{type:r,value:t,placeholder:l,onChange:e=>a(e.target.value),className:"w-full rounded-md border border-gray-300 px-3 py-1.5 text-sm outline-none focus:border-blue-500"})}function s(e){let{value:t,onChange:a}=e;return(0,n.jsx)("textarea",{value:t,rows:6,onChange:e=>a(e.target.value),className:"w-full rounded-md border border-gray-300 px-3 py-1.5 font-mono text-xs outline-none focus:border-blue-500"})}function i(e){let{value:t,onChange:a,options:l}=e;return(0,n.jsx)("select",{value:t,onChange:e=>a(e.target.value),className:"w-full rounded-md border border-gray-300 px-3 py-1.5 text-sm outline-none focus:border-blue-500",children:l.map(e=>(0,n.jsx)("option",{value:String(e.value),children:e.label},e.value))})}function o(e){let{title:t,children:a,action:l}=e;return(0,n.jsxs)("section",{className:"rounded-lg border border-gray-200 bg-white p-5 shadow-sm",children:[(t||l)&&(0,n.jsxs)("header",{className:"mb-4 flex items-center justify-between",children:[t&&(0,n.jsx)("h2",{className:"text-base font-semibold text-gray-900",children:t}),l]}),a]})}function d(e){let{open:t,title:a,onClose:l,children:r,footer:s}=e;return t?(0,n.jsx)("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4",children:(0,n.jsxs)("div",{className:"max-h-[85vh] w-full max-w-2xl overflow-auto rounded-lg bg-white shadow-xl",children:[(0,n.jsxs)("header",{className:"flex items-center justify-between border-b border-gray-200 px-5 py-3",children:[(0,n.jsx)("h3",{className:"text-base font-semibold",children:a}),(0,n.jsx)("button",{onClick:l,className:"text-gray-400 hover:text-gray-600","aria-label":"关闭",children:"✕"})]}),(0,n.jsx)("div",{className:"px-5 py-4",children:r}),s&&(0,n.jsx)("footer",{className:"flex justify-end gap-2 border-t border-gray-200 px-5 py-3",children:s})]})}):null}function c(e){let{message:t,kind:a="error"}=e;return t?(0,n.jsx)("div",{className:"mb-3 rounded-md border px-3 py-2 text-sm ".concat("error"===a?"bg-red-50 text-red-700 border-red-200":"bg-green-50 text-green-700 border-green-200"),children:t}):null}function m(e){let{text:t="暂无数据"}=e;return(0,n.jsx)("div",{className:"py-10 text-center text-sm text-gray-400",children:t})}},4357:(e,t,a)=>{"use strict";a.d(t,{MW:()=>s,le:()=>r,u_:()=>i});let n={name:"status",label:"状态",type:"select",options:[{value:1,label:"启用"},{value:0,label:"停用"}]},l={name:"sort_order",label:"排序",type:"number",hideInTable:!0},r=[{key:"courses",title:"课程",description:"付费课程。注意 code 是视频目录名与封面名,创建后不可修改。",fields:[{name:"code",label:"课程标识",type:"text",immutable:!0,hint:"64 位哈希,对应视频目录"},{name:"title",label:"课程名称",type:"text"},{name:"intro",label:"课程介绍",type:"text"},{name:"price_fen",label:"价格(分)",type:"number"},{name:"cover_image",label:"封面文件",type:"text",hideInTable:!0},n,l]},{key:"lessons",title:"课时",description:"课程下的视频。chapter_id 与 play_id 参与视频路径拼接,改动会使旧地址失效。",filterByCourse:!0,fields:[{name:"course_id",label:"课程 ID",type:"number"},{name:"chapter_id",label:"章节 ID",type:"text"},{name:"play_id",label:"播放 ID",type:"text"},{name:"chapter_title",label:"章节名称",type:"text"},{name:"lesson_title",label:"视频名称",type:"text"},{name:"duration",label:"时长",type:"text"},{name:"published_at",label:"发布日期",type:"date"},l]},{key:"home-courses",title:"首页新课",description:"首页「新课上线」的长图页面。course_name 决定图片路径,不要改动。",fields:[{name:"course_name",label:"条目名称",type:"text",hint:"对应 Images/NewCourse/{名称}.png"},{name:"intro",label:"简介",type:"text"},{name:"course_id",label:"关联课程 ID",type:"number",hint:"留空则长图页不显示购买按钮"},{name:"content",label:"长图内容",type:"textarea",hideInTable:!0},{name:"published_at",label:"发布日期",type:"date",hideInTable:!0},n,l]},{key:"home-free-courses",title:"首页试听",description:"首页「自我学习」入口。course_name 决定图片路径。",fields:[{name:"series_no",label:"序号",type:"number",hint:"对应免费试听课的 series_no"},{name:"course_name",label:"条目名称",type:"text"},{name:"intro",label:"简介",type:"text"},n,l]},{key:"banners",title:"轮播图",description:"首页顶部轮播。filename 对应 Images/Banner/{文件名}。",fields:[{name:"filename",label:"图片文件名",type:"text"},n,l]},{key:"articles",title:"知识速通",description:"首页「知识速通」文章。legacy_page_id 对应缩略图 WebPages/{id}.png。",fields:[{name:"title",label:"标题",type:"text"},{name:"legacy_page_id",label:"图片编号",type:"text"},{name:"intro",label:"简介",type:"text"},{name:"publisher",label:"发布人",type:"text",hideInTable:!0},{name:"content",label:"正文",type:"textarea",hideInTable:!0},{name:"published_at",label:"发布日期",type:"date"},n,l]},{key:"products",title:"支付商品",description:"课程与微信虚拟支付道具的映射。微信道具 ID 与价格必须先在小程序后台创建。",fields:[{name:"course_id",label:"课程 ID",type:"number"},{name:"wx_product_id",label:"微信道具 ID",type:"text"},{name:"name",label:"商品名称",type:"text"},{name:"price_fen",label:"价格(分)",type:"text"},n]}],s=e=>r.find(t=>t.key===e),i={0:"待支付",1:"已支付",2:"已开通",3:"已退款",4:"已关闭"}},8166:(e,t,a)=>{"use strict";var n=a(8874);a.o(n,"useParams")&&a.d(t,{useParams:function(){return n.useParams}}),a.o(n,"usePathname")&&a.d(t,{usePathname:function(){return n.usePathname}}),a.o(n,"useRouter")&&a.d(t,{useRouter:function(){return n.useRouter}})},8312:(e,t,a)=>{"use strict";a.d(t,{F:()=>i});var n=a(1910);let l="http://127.0.0.1:3000".replace(/\/+$/,"");async function r(e){var t,a,r,s,i;let o,d=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},c=(0,n.gf)(),m={"content-type":"application/json",...null!=(t=d.headers)?t:{}};c&&(m.Authorization="Bearer ".concat(c));try{o=await fetch("".concat(l).concat(e),{...d,headers:m})}catch(e){throw{code:-1,message:"无法连接服务端,请检查网络或接口地址"}}let u=null;try{u=await o.json()}catch(e){throw{code:-1,message:"服务端返回异常(HTTP ".concat(o.status,")")}}if(401===o.status)throw(0,n.L)(),window.location.pathname.startsWith("/login")||(window.location.href="/login"),{code:null!=(a=null==u?void 0:u.code)?a:2e3,message:null!=(r=null==u?void 0:u.message)?r:"登录已失效,请重新登录"};if(!u||0!==u.code)throw{code:null!=(s=null==u?void 0:u.code)?s:-1,message:null!=(i=null==u?void 0:u.message)?i:"请求失败"};return u.data}let s=e=>{let t=Object.entries(e).filter(e=>{let[,t]=e;return void 0!==t&&""!==t}).map(e=>{let[t,a]=e;return"".concat(encodeURIComponent(t),"=").concat(encodeURIComponent(String(a)))});return t.length?"?".concat(t.join("&")):""},i={base:l,request:r,login:(e,t)=>r("/admin/v1/auth/login",{method:"POST",body:JSON.stringify({username:e,password:t})}),bootstrap:(e,t)=>r("/admin/v1/auth/bootstrap",{method:"POST",body:JSON.stringify({username:e,password:t})}),stats:()=>r("/admin/v1/stats"),listUsers:(e,t,a)=>r("/admin/v1/users".concat(s({page:e,pageSize:t,keyword:a}))),updateUser:(e,t)=>r("/admin/v1/users/".concat(e),{method:"PATCH",body:JSON.stringify(t)}),listResource:(e,t)=>r("/admin/v1/data/".concat(e).concat(s(t))),createResource:(e,t)=>r("/admin/v1/data/".concat(e),{method:"POST",body:JSON.stringify(t)}),updateResource:(e,t,a)=>r("/admin/v1/data/".concat(e,"/").concat(t),{method:"PATCH",body:JSON.stringify(a)}),deleteResource:(e,t)=>r("/admin/v1/data/".concat(e,"/").concat(t),{method:"DELETE"}),listSettings:()=>r("/admin/v1/settings"),upsertSetting:(e,t,a)=>r("/admin/v1/settings",{method:"PUT",body:JSON.stringify({key:e,value:t,remark:a})}),listOrders:(e,t,a)=>r("/admin/v1/orders".concat(s({page:e,pageSize:t,status:a}))),refundOrder:(e,t)=>r("/admin/v1/orders/".concat(e,"/refund"),{method:"POST",body:JSON.stringify({reason:t})}),listEntitlements:e=>r("/admin/v1/entitlements".concat(s({userId:e}))),grantEntitlement:(e,t,a)=>r("/admin/v1/entitlements",{method:"POST",body:JSON.stringify({userId:e,courseId:t,note:a})}),revokeEntitlement:(e,t)=>r("/admin/v1/entitlements".concat(s({userId:e,courseId:t})),{method:"DELETE"})}},8630:(e,t,a)=>{Promise.resolve().then(a.bind(a,754))}},e=>{e.O(0,[964,857,358],()=>e(e.s=8630)),_N_E=e.O()}]);