新增后端图标校验与色槽规范化,前端展示 BoardBadge/骨架屏,发帖与板块管理页增加未保存确认。 Co-authored-by: Cursor <cursoragent@cursor.com>
2 lines
8.5 KiB
JavaScript
2 lines
8.5 KiB
JavaScript
import{r as n,j as e}from"./react-vendor-BdyZmpPe.js";import{_ as Z,Z as G,u as J,a as V,F as q,b,c as u,d as f,e as g,f as N,o as K,s as D}from"./form-DggfNWHU.js";import{c as i,j as Q,i as S,k as U,l as W,m as X,S as A,B as _,o as Y,b as y,n as j}from"./index-Cp7Ff9NP.js";import{I as k}from"./input-y6vZyHhN.js";import{T as ee}from"./textarea-Dcf0-FNg.js";import{B as se}from"./badge-xzbTTsRq.js";import{D as re,a as ae,b as oe,c as ne,e as ie}from"./dialog-DXwuwWJi.js";import{A as te,g as le,a as ce,b as de,c as xe,d as me,e as he,f as je,h as pe}from"./alert-dialog-C2PKamsV.js";import{J as be}from"./ui-vendor-B26O8baZ.js";function E(r){return Z(G,r)}const F=n.forwardRef(({className:r,...a},o)=>e.jsx("div",{className:"relative w-full overflow-auto",children:e.jsx("table",{ref:o,className:i("w-full caption-bottom text-sm",r),...a})}));F.displayName="Table";const R=n.forwardRef(({className:r,...a},o)=>e.jsx("thead",{ref:o,className:i("[&_tr]:border-b",r),...a}));R.displayName="TableHeader";const O=n.forwardRef(({className:r,...a},o)=>e.jsx("tbody",{ref:o,className:i("[&_tr:last-child]:border-0",r),...a}));O.displayName="TableBody";const I=n.forwardRef(({className:r,...a},o)=>e.jsx("tr",{ref:o,className:i("border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",r),...a}));I.displayName="TableRow";const m=n.forwardRef(({className:r,...a},o)=>e.jsx("th",{ref:o,className:i("h-10 px-3 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",r),...a}));m.displayName="TableHead";const h=n.forwardRef(({className:r,...a},o)=>e.jsx("td",{ref:o,className:i("p-3 align-middle [&:has([role=checkbox])]:pr-0",r),...a}));h.displayName="TableCell";function ue({value:r,onChange:a,board:o}){const p={id:o.id,icon:r||void 0,color_index:o.color_index},t=Q(p),v=S(p);return e.jsxs("div",{className:"board-appearance-picker",children:[e.jsxs("div",{className:"board-appearance-picker__preview",children:[e.jsx("span",{className:i("board-appearance-picker__preview-icon",`sidebar-board-icon--${v}`),children:e.jsx(t,{"aria-hidden":!0})}),e.jsx("span",{className:"board-appearance-picker__preview-hint",children:"预览"})]}),e.jsxs("div",{className:"board-icon-grid",role:"listbox","aria-label":"选择板块图标",children:[e.jsx("button",{type:"button",role:"option","aria-selected":!r,className:i("board-icon-option",!r&&"board-icon-option--active"),title:"自动(按板块 ID)",onClick:()=>a(""),children:e.jsx("span",{className:"board-icon-option__auto",children:"A"})}),U.map(({key:l,label:c,Icon:w})=>e.jsx("button",{type:"button",role:"option","aria-selected":r===l,"aria-label":c,title:c,className:i("board-icon-option",r===l&&"board-icon-option--active"),onClick:()=>a(l),children:e.jsx(w,{"aria-hidden":!0})},l))]})]})}function fe({value:r,onChange:a,boardId:o}){return e.jsxs("div",{className:"board-color-grid",role:"listbox","aria-label":"选择板块色标",children:[e.jsx("button",{type:"button",role:"option","aria-selected":r<0,className:i("board-color-option board-color-option--auto",r<0&&"board-color-option--active"),title:"自动(按板块 ID)",onClick:()=>a(-1),children:"A"}),Array.from({length:W},(p,t)=>e.jsx("button",{type:"button",role:"option","aria-selected":r===t,className:i("board-color-option",`board-color-option--${t}`,r===t&&"board-color-option--active"),title:`色标 ${t+1}`,onClick:()=>a(t)},t))]})}const ge=K({name:D().min(1,"请输入名称").max(64),description:D().max(500).optional(),sort_order:E().min(0),icon:D().max(64).optional(),color_index:E().min(-1).max(7)});function Be(){const{ready:r}=X(),[a,o]=n.useState([]),[p,t]=n.useState(!0),[v,l]=n.useState(!1),[c,w]=n.useState(null),[P,T]=n.useState(!1),d=J({resolver:V(ge),defaultValues:{name:"",description:"",sort_order:1,icon:"",color_index:-1}}),H=d.watch("color_index"),B=(c==null?void 0:c.id)??a.length+1,C=()=>{t(!0),y.boards().then(s=>o(s.boards??[])).catch(s=>j.error(s.message)).finally(()=>t(!1))};n.useEffect(()=>{r&&C()},[r]);const L=()=>{w(null),d.reset({name:"",description:"",sort_order:a.length+1,icon:"",color_index:-1}),l(!0)},z=s=>{w(s),d.reset({name:s.name,description:s.description??"",sort_order:s.sort_order,icon:s.icon??"",color_index:s.color_index??-1}),l(!0)},$=async s=>{T(!0);try{const x={name:s.name,description:s.description??"",sort_order:s.sort_order,icon:s.icon??"",color_index:s.color_index??-1};c?(await y.updateBoard(c.id,x),j.success("板块已更新")):(await y.createBoard(x),j.success("板块已创建")),l(!1),C(),window.dispatchEvent(new Event("boards-refresh"))}catch(x){j.error(x instanceof Error?x.message:"操作失败")}finally{T(!1)}},M=async s=>{try{await y.deleteBoard(s),j.success("板块已删除"),C(),window.dispatchEvent(new Event("boards-refresh"))}catch(x){j.error(x instanceof Error?x.message:"删除失败")}};return r?e.jsxs("div",{className:"admin-page",children:[e.jsx("div",{className:"admin-page-head",children:e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start"},children:[e.jsxs("div",{children:[e.jsx("h1",{children:"板块管理"}),e.jsx("p",{children:"创建、编辑或删除论坛板块;可为每个板块自定义图标与色标"})]}),e.jsxs(_,{onClick:L,children:[e.jsx(be,{}),"新建板块"]})]})}),e.jsx("div",{className:"admin-card",children:p?e.jsx("div",{className:"flex justify-center py-12",children:e.jsx(A,{size:"lg"})}):e.jsxs(e.Fragment,{children:[e.jsxs(F,{children:[e.jsx(R,{children:e.jsxs(I,{children:[e.jsx(m,{className:"w-[60px]",children:"ID"}),e.jsx(m,{className:"w-[52px]",children:"图标"}),e.jsx(m,{children:"名称"}),e.jsx(m,{children:"简介"}),e.jsx(m,{className:"w-[70px]",children:"排序"}),e.jsx(m,{className:"w-[80px]",children:"帖子数"}),e.jsx(m,{className:"w-[160px]",children:"操作"})]})}),e.jsx(O,{children:a.map(s=>{const x=S(s);return e.jsxs(I,{children:[e.jsx(h,{children:s.id}),e.jsx(h,{children:e.jsx("span",{className:i("board-table-icon",`sidebar-board-icon--${x}`),children:e.jsx(Y,{board:s})})}),e.jsx(h,{children:e.jsx("strong",{children:s.name})}),e.jsx(h,{className:"max-w-[200px] truncate",children:s.description}),e.jsx(h,{children:s.sort_order}),e.jsx(h,{children:e.jsx(se,{variant:"secondary",children:s.post_count??0})}),e.jsx(h,{children:e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(_,{variant:"ghost",size:"sm",onClick:()=>z(s),children:"编辑"}),e.jsxs(te,{children:[e.jsx(le,{asChild:!0,children:e.jsx(_,{variant:"ghost",size:"sm",className:"text-destructive hover:text-destructive",children:"删除"})}),e.jsxs(ce,{children:[e.jsxs(de,{children:[e.jsx(xe,{children:"确定删除该板块?"}),e.jsx(me,{children:"删除后该板块下的帖子将无法通过板块筛选,此操作不可撤销。"})]}),e.jsxs(he,{children:[e.jsx(je,{children:"取消"}),e.jsx(pe,{onClick:()=>M(s.id),children:"删除"})]})]})]})]})})]},s.id)})})]}),a.length===0&&e.jsx("div",{className:"empty-state",children:e.jsx("p",{children:"还没有板块,点击右上角创建第一个"})})]})}),e.jsx(re,{open:v,onOpenChange:l,children:e.jsxs(ae,{className:"board-manage-dialog",children:[e.jsx(oe,{children:e.jsx(ne,{children:c?"编辑板块":"新建板块"})}),e.jsx(q,{...d,children:e.jsxs("form",{onSubmit:d.handleSubmit($),className:"space-y-4",children:[e.jsx(b,{control:d.control,name:"name",render:({field:s})=>e.jsxs(u,{children:[e.jsx(f,{children:"板块名称"}),e.jsx(g,{children:e.jsx(k,{maxLength:64,placeholder:"如:技术交流",...s})}),e.jsx(N,{})]})}),e.jsx(b,{control:d.control,name:"description",render:({field:s})=>e.jsxs(u,{children:[e.jsx(f,{children:"简介"}),e.jsx(g,{children:e.jsx(ee,{rows:3,maxLength:500,placeholder:"板块说明(可选)",...s})}),e.jsx(N,{})]})}),e.jsx(b,{control:d.control,name:"icon",render:({field:s})=>e.jsxs(u,{children:[e.jsx(f,{children:"板块图标"}),e.jsx(g,{children:e.jsx(ue,{value:s.value??"",onChange:s.onChange,board:{id:B,color_index:H}})}),e.jsx(N,{})]})}),e.jsx(b,{control:d.control,name:"color_index",render:({field:s})=>e.jsxs(u,{children:[e.jsx(f,{children:"色标颜色"}),e.jsx(g,{children:e.jsx(fe,{value:s.value??-1,onChange:s.onChange,boardId:B})}),e.jsx(N,{})]})}),e.jsx(b,{control:d.control,name:"sort_order",render:({field:s})=>e.jsxs(u,{children:[e.jsx(f,{children:"排序"}),e.jsx(g,{children:e.jsx(k,{type:"number",min:0,...s})}),e.jsx(N,{})]})}),e.jsxs(ie,{children:[e.jsx(_,{type:"button",variant:"outline",onClick:()=>l(!1),children:"取消"}),e.jsx(_,{type:"submit",loading:P,children:c?"保存":"创建"})]})]})})]})})]}):e.jsx("div",{className:"flex justify-center py-16",children:e.jsx(A,{size:"lg"})})}export{Be as default};
|