From cff69826137846e40c7fa942dc7ddd5715738a8a Mon Sep 17 00:00:00 2001 From: Blizzard Date: Thu, 30 Jul 2026 12:53:22 +0800 Subject: [PATCH] =?UTF-8?q?chore(admin):=20=E5=88=A0=E6=8E=89=E5=81=9C?= =?UTF-8?q?=E7=94=A8=E7=9A=84=E8=80=81=E6=96=B9=E6=A1=88=EF=BC=8C=E5=85=BB?= =?UTF-8?q?=E6=8A=A4=E6=96=B9=E6=A1=88=E9=A1=B5=E6=8C=89=E7=8C=AB=E7=8B=97?= =?UTF-8?q?=E5=88=86=20tab?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 停用的 8 套直接删了 上一个提交把老方案(按 3 段配的)改名停用没删,理由是「万一新内容有问题 还能翻回去看」。你要求删掉,删了。 走 service 的 DeleteTemplate 而不是直接删主表:明细要跟着一起清。 复查孤儿明细 0 条。剩 10 套(5 阶段 × 2 物种,各一套)。 已套用出去的计划节点不受影响 —— 套用时就展开成实体行、和模板断开了。 ## 按猫狗分 tab 混在一起 10 套要上下找,而且阶段名两边一样(幼年期/青年期…),扫一眼分不清 哪套是猫的。tab 上带条数,「阶段」列不再重复物种。 顺带两处: 行按阶段顺序排 —— 数据库按 sort 排,但 sort 是全局的,分物种看时会跳号 新建时默认跟当前 tab 的物种,省一步点击 品种管理页本来就有猫狗 tab;记录事项页不分物种(记录类型猫狗共用)。 Co-Authored-By: Claude Opus 5 --- .../{index-BOP-ztlG.js => index-BH08rQ_o.js} | 4 +- pets-be/internal/admin/dist/index.html | 2 +- pets-be/web/admin/src/pages/CareTemplates.tsx | 45 +++++++++++++++---- 3 files changed, 40 insertions(+), 11 deletions(-) rename pets-be/internal/admin/dist/assets/{index-BOP-ztlG.js => index-BH08rQ_o.js} (96%) diff --git a/pets-be/internal/admin/dist/assets/index-BOP-ztlG.js b/pets-be/internal/admin/dist/assets/index-BH08rQ_o.js similarity index 96% rename from pets-be/internal/admin/dist/assets/index-BOP-ztlG.js rename to pets-be/internal/admin/dist/assets/index-BH08rQ_o.js index 2167b8d..3a10f21 100644 --- a/pets-be/internal/admin/dist/assets/index-BOP-ztlG.js +++ b/pets-be/internal/admin/dist/assets/index-BH08rQ_o.js @@ -56,8 +56,8 @@ Please change the parent to i[2])return!0}r=r.parentNode}while(r&&r!==n.body);return!1},wd=function(e){return[e.scrollTop,e.scrollHeight,e.clientHeight]},Td=function(e){return[e.scrollLeft,e.scrollWidth,e.clientWidth]},Ed=function(e,t){return e===`v`?xd(t):Sd(t)},Dd=function(e,t){return e===`v`?wd(t):Td(t)},Od=function(e,t){return e===`h`&&t===`rtl`?-1:1},kd=function(e,t,n,r,i){var a=Od(e,window.getComputedStyle(t).direction),o=a*r,s=n.target,c=t.contains(s),l=!1,u=o>0,d=0,f=0;do{if(!s)break;var p=Dd(e,s),m=p[0],h=p[1]-p[2]-a*m;(m||h)&&Ed(e,s)&&(d+=h,f+=m);var g=s.parentNode;s=g&&g.nodeType===Node.DOCUMENT_FRAGMENT_NODE?g.host:g}while(!c&&s!==document.body||c&&(t.contains(s)||t===s));return(u&&(i&&Math.abs(d)<1||!i&&o>d)||!u&&(i&&Math.abs(f)<1||!i&&-o>f))&&(l=!0),l},Ad=function(e){return`changedTouches`in e?[e.changedTouches[0].clientX,e.changedTouches[0].clientY]:[0,0]},jd=function(e){return[e.deltaX,e.deltaY]},Md=function(e){return e&&`current`in e?e.current:e},Nd=function(e,t){return e[0]===t[0]&&e[1]===t[1]},Pd=function(e){return` .block-interactivity-${e} {pointer-events: none;} .allow-interactivity-${e} {pointer-events: all;} -`},Fd=0,Id=[];function Ld(e){var t=S.useRef([]),n=S.useRef([0,0]),r=S.useRef(),i=S.useState(Fd++)[0],a=S.useState(od)[0],o=S.useRef(e);S.useEffect(function(){o.current=e},[e]),S.useEffect(function(){if(e.inert){document.body.classList.add(`block-interactivity-${i}`);var t=Fu([e.lockRef.current],(e.shards||[]).map(Md),!0).filter(Boolean);return t.forEach(function(e){return e.classList.add(`allow-interactivity-${i}`)}),function(){document.body.classList.remove(`block-interactivity-${i}`),t.forEach(function(e){return e.classList.remove(`allow-interactivity-${i}`)})}}},[e.inert,e.lockRef.current,e.shards]);var s=S.useCallback(function(e,t){if(`touches`in e&&e.touches.length===2||e.type===`wheel`&&e.ctrlKey)return!o.current.allowPinchZoom;var i=Ad(e),a=n.current,s=`deltaX`in e?e.deltaX:a[0]-i[0],c=`deltaY`in e?e.deltaY:a[1]-i[1],l,u=e.target,d=Math.abs(s)>Math.abs(c)?`h`:`v`;if(`touches`in e&&d===`h`&&u.type===`range`)return!1;var f=window.getSelection(),p=f&&f.anchorNode;if(p&&(p===u||p.contains(u)))return!1;var m=Cd(d,u);if(!m)return!0;if(m?l=d:(l=d===`v`?`h`:`v`,m=Cd(d,u)),!m)return!1;if(!r.current&&`changedTouches`in e&&(s||c)&&(r.current=l),!l)return!0;var h=r.current||l;return kd(h,t,e,h===`h`?s:c,!0)},[]),c=S.useCallback(function(e){var n=e;if(!(!Id.length||Id[Id.length-1]!==a)){var r=`deltaY`in n?jd(n):Ad(n),i=t.current.filter(function(e){return e.name===n.type&&(e.target===n.target||n.target===e.shadowParent)&&Nd(e.delta,r)})[0];if(i&&i.should){n.cancelable&&n.preventDefault();return}if(!i){var c=(o.current.shards||[]).map(Md).filter(Boolean).filter(function(e){return e.contains(n.target)});(c.length>0?s(n,c[0]):!o.current.noIsolation)&&n.cancelable&&n.preventDefault()}}},[]),l=S.useCallback(function(e,n,r,i){var a={name:e,delta:n,target:r,should:i,shadowParent:Rd(r)};t.current.push(a),setTimeout(function(){t.current=t.current.filter(function(e){return e!==a})},1)},[]),u=S.useCallback(function(e){n.current=Ad(e),r.current=void 0},[]),d=S.useCallback(function(t){l(t.type,jd(t),t.target,s(t,e.lockRef.current))},[]),f=S.useCallback(function(t){l(t.type,Ad(t),t.target,s(t,e.lockRef.current))},[]);S.useEffect(function(){return Id.push(a),e.setCallbacks({onScrollCapture:d,onWheelCapture:d,onTouchMoveCapture:f}),document.addEventListener(`wheel`,c,$),document.addEventListener(`touchmove`,c,$),document.addEventListener(`touchstart`,u,$),function(){Id=Id.filter(function(e){return e!==a}),document.removeEventListener(`wheel`,c,$),document.removeEventListener(`touchmove`,c,$),document.removeEventListener(`touchstart`,u,$)}},[]);var p=e.removeScrollBar,m=e.inert;return S.createElement(S.Fragment,null,m?S.createElement(a,{styles:Pd(i)}):null,p?S.createElement(gd,{noRelative:e.noRelative,gapMode:e.gapMode}):null)}function Rd(e){for(var t=null;e!==null;)e instanceof ShadowRoot&&(t=e.host,e=e.host),e=e.parentNode;return t}var zd=Yu(Xu,Ld),Bd=S.forwardRef(function(e,t){return S.createElement(Qu,Nu({},e,{ref:t,sideCar:zd}))});Bd.classNames=Qu.classNames;var Vd=function(e){return typeof document>`u`?null:(Array.isArray(e)?e[0]:e).ownerDocument.body},Hd=new WeakMap,Ud=new WeakMap,Wd={},Gd=0,Kd=function(e){return e&&(e.host||Kd(e.parentNode))},qd=function(e,t){return t.map(function(t){if(e.contains(t))return t;var n=Kd(t);return n&&e.contains(n)?n:(console.error(`aria-hidden`,t,`in not contained inside`,e,`. Doing nothing`),null)}).filter(function(e){return!!e})},Jd=function(e,t,n,r){var i=qd(t,Array.isArray(e)?e:[e]);Wd[n]||(Wd[n]=new WeakMap);var a=Wd[n],o=[],s=new Set,c=new Set(i),l=function(e){!e||s.has(e)||(s.add(e),l(e.parentNode))};i.forEach(l);var u=function(e){!e||c.has(e)||Array.prototype.forEach.call(e.children,function(e){if(s.has(e))u(e);else try{var t=e.getAttribute(r),i=t!==null&&t!==`false`,c=(Hd.get(e)||0)+1,l=(a.get(e)||0)+1;Hd.set(e,c),a.set(e,l),o.push(e),c===1&&i&&Ud.set(e,!0),l===1&&e.setAttribute(n,`true`),i||e.setAttribute(r,`true`)}catch(t){console.error(`aria-hidden: cannot operate on `,e,t)}})};return u(t),s.clear(),Gd++,function(){o.forEach(function(e){var t=Hd.get(e)-1,i=a.get(e)-1;Hd.set(e,t),a.set(e,i),t||(Ud.has(e)||e.removeAttribute(r),Ud.delete(e)),i||e.removeAttribute(n)}),Gd--,Gd||(Hd=new WeakMap,Hd=new WeakMap,Ud=new WeakMap,Wd={})}},Yd=function(e,t,n){n===void 0&&(n=`data-aria-hidden`);var r=Array.from(Array.isArray(e)?e:[e]),i=t||Vd(e);return i?(r.push.apply(r,Array.from(i.querySelectorAll(`[aria-live], script`))),Jd(r,i,n,`aria-hidden`)):function(){return null}},Xd=`Dialog`,[Zd,Qd]=Pl(Xd),[$d,ef]=Zd(Xd),tf=e=>{let{__scopeDialog:t,children:n,open:r,defaultOpen:i,onOpenChange:a,modal:o=!0}=e,s=S.useRef(null),c=S.useRef(null),[l,u]=Bl({prop:r,defaultProp:i??!1,onChange:a,caller:Xd});return(0,U.jsx)($d,{scope:t,triggerRef:s,contentRef:c,contentId:Z(),titleId:Z(),descriptionId:Z(),open:l,onOpenChange:u,onOpenToggle:S.useCallback(()=>u(e=>!e),[u]),modal:o,children:n})};tf.displayName=Xd;var nf=`DialogTrigger`,rf=S.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,i=ef(nf,n),a=Bc(t,i.triggerRef);return(0,U.jsx)(cl.button,{type:`button`,"aria-haspopup":`dialog`,"aria-expanded":i.open,"aria-controls":i.open?i.contentId:void 0,"data-state":wf(i.open),...r,ref:a,onClick:Nl(e.onClick,i.onOpenToggle)})});rf.displayName=nf;var af=`DialogPortal`,[of,sf]=Zd(af,{forceMount:void 0}),cf=e=>{let{__scopeDialog:t,forceMount:n,children:r,container:i}=e,a=ef(af,t);return(0,U.jsx)(of,{scope:t,forceMount:n,children:S.Children.map(r,e=>(0,U.jsx)(Cu,{present:n||a.open,children:(0,U.jsx)(xu,{asChild:!0,container:i,children:e})}))})};cf.displayName=af;var lf=`DialogOverlay`,uf=S.forwardRef((e,t)=>{let n=sf(lf,e.__scopeDialog),{forceMount:r=n.forceMount,...i}=e,a=ef(lf,e.__scopeDialog);return a.modal?(0,U.jsx)(Cu,{present:r||a.open,children:(0,U.jsx)(ff,{...i,ref:t})}):null});uf.displayName=lf;var df=Vc(`DialogOverlay.RemoveScroll`),ff=S.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,i=ef(lf,n),a=Bc(t,$l());return(0,U.jsx)(Bd,{as:df,allowPinchZoom:!0,shards:[i.contentRef],children:(0,U.jsx)(cl.div,{"data-state":wf(i.open),...r,ref:a,style:{pointerEvents:`auto`,...r.style}})})}),pf=`DialogContent`,mf=S.forwardRef((e,t)=>{let n=sf(pf,e.__scopeDialog),{forceMount:r=n.forceMount,...i}=e,a=ef(pf,e.__scopeDialog);return(0,U.jsx)(Cu,{present:r||a.open,children:a.modal?(0,U.jsx)(hf,{...i,ref:t}):(0,U.jsx)(gf,{...i,ref:t})})});mf.displayName=pf;var hf=S.forwardRef((e,t)=>{let n=ef(pf,e.__scopeDialog),r=S.useRef(null),i=Bc(t,n.contentRef,r);return S.useEffect(()=>{let e=r.current;if(e)return Yd(e)},[]),(0,U.jsx)(_f,{...e,ref:i,trapFocus:n.open,disableOutsidePointerEvents:n.open,onCloseAutoFocus:Nl(e.onCloseAutoFocus,e=>{e.preventDefault(),n.triggerRef.current?.focus()}),onPointerDownOutside:Nl(e.onPointerDownOutside,e=>{let t=e.detail.originalEvent,n=t.button===0&&t.ctrlKey===!0;(t.button===2||n)&&e.preventDefault()}),onFocusOutside:Nl(e.onFocusOutside,e=>e.preventDefault())})}),gf=S.forwardRef((e,t)=>{let n=ef(pf,e.__scopeDialog),r=S.useRef(!1),i=S.useRef(!1);return(0,U.jsx)(_f,{...e,ref:t,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:t=>{e.onCloseAutoFocus?.(t),t.defaultPrevented||(r.current||n.triggerRef.current?.focus(),t.preventDefault()),r.current=!1,i.current=!1},onInteractOutside:t=>{e.onInteractOutside?.(t),t.defaultPrevented||(r.current=!0,t.detail.originalEvent.type===`pointerdown`&&(i.current=!0));let a=t.target;n.triggerRef.current?.contains(a)&&t.preventDefault(),t.detail.originalEvent.type===`focusin`&&i.current&&t.preventDefault()}})}),_f=S.forwardRef((e,t)=>{let{__scopeDialog:n,trapFocus:r,onOpenAutoFocus:i,onCloseAutoFocus:a,...o}=e,s=ef(pf,n);return ju(),(0,U.jsx)(U.Fragment,{children:(0,U.jsx)(cu,{asChild:!0,loop:!0,trapped:r,onMountAutoFocus:i,onUnmountAutoFocus:a,children:(0,U.jsx)(Xl,{role:`dialog`,id:s.contentId,"aria-describedby":s.descriptionId,"aria-labelledby":s.titleId,"data-state":wf(s.open),...o,ref:t,deferPointerDownOutside:!0,onDismiss:()=>s.onOpenChange(!1)})})})}),vf=`DialogTitle`,yf=S.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,i=ef(vf,n);return(0,U.jsx)(cl.h2,{id:i.titleId,...r,ref:t})});yf.displayName=vf;var bf=`DialogDescription`,xf=S.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,i=ef(bf,n);return(0,U.jsx)(cl.p,{id:i.descriptionId,...r,ref:t})});xf.displayName=bf;var Sf=`DialogClose`,Cf=S.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,i=ef(Sf,n);return(0,U.jsx)(cl.button,{type:`button`,...r,ref:t,onClick:Nl(e.onClick,()=>i.onOpenChange(!1))})});Cf.displayName=Sf;function wf(e){return e?`open`:`closed`}var Tf=tf,Ef=S.forwardRef(({className:e,children:t,...n},r)=>(0,U.jsxs)(cf,{children:[(0,U.jsx)(uf,{className:`fixed inset-0 z-50 bg-black/40 data-[state=open]:animate-in data-[state=closed]:animate-out`}),(0,U.jsxs)(mf,{ref:r,className:Lc(`fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border bg-card p-6 shadow-lg rounded-xl`,e),...n,children:[t,(0,U.jsx)(Cf,{className:`absolute right-4 top-4 opacity-70 hover:opacity-100`,children:(0,U.jsx)(ls,{className:`h-4 w-4`})})]})]}));Ef.displayName=`DialogContent`;function Df({className:e,...t}){return(0,U.jsx)(`div`,{className:Lc(`flex flex-col space-y-1.5`,e),...t})}function Of({className:e,...t}){return(0,U.jsx)(`h2`,{className:Lc(`text-lg font-semibold`,e),...t})}var kf={id:0,icon:`📘`,title:``,description:``,content:``,category:``,related_sheet_type:``,published:!0};function Af(){let{page:e,setPage:t,data:n,totalPages:r,reload:i}=yl(z.articles),[a,o]=(0,S.useState)(!1),[s,c]=(0,S.useState)(kf);function l(e){c({...e}),o(!0)}function u(){c({...kf}),o(!0)}async function d(){await z.saveArticle(s),o(!1),i()}async function f(e){await z.deleteArticle(e),i()}let p=e=>t=>c({...s,[e]:t.target.value});return(0,U.jsxs)(`div`,{children:[(0,U.jsxs)(`div`,{className:`flex items-center justify-between mb-6`,children:[(0,U.jsx)(`h1`,{className:`text-2xl font-bold`,children:`文章管理`}),(0,U.jsx)(W,{onClick:u,children:`新建文章`})]}),(0,U.jsx)(pl,{children:(0,U.jsxs)(gl,{className:`pt-6`,children:[(0,U.jsxs)(bl,{children:[(0,U.jsx)(xl,{children:(0,U.jsxs)(Cl,{children:[(0,U.jsx)(q,{children:`ID`}),(0,U.jsx)(q,{children:`标题`}),(0,U.jsx)(q,{children:`分类`}),(0,U.jsx)(q,{children:`关联弹层`}),(0,U.jsx)(q,{children:`状态`}),(0,U.jsx)(q,{className:`text-right`,children:`操作`})]})}),(0,U.jsx)(Sl,{children:n?.list?.map(e=>(0,U.jsxs)(Cl,{children:[(0,U.jsx)(J,{children:e.id}),(0,U.jsxs)(J,{className:`font-medium`,children:[(0,U.jsx)(`span`,{className:`mr-1`,children:e.icon}),e.title]}),(0,U.jsx)(J,{children:e.category||`—`}),(0,U.jsx)(J,{children:e.related_sheet_type||`—`}),(0,U.jsx)(J,{children:e.published?(0,U.jsx)(Tl,{variant:`success`,children:`已发布`}):(0,U.jsx)(Tl,{variant:`muted`,children:`草稿`})}),(0,U.jsxs)(J,{className:`text-right space-x-2 whitespace-nowrap`,children:[(0,U.jsx)(W,{variant:`outline`,size:`sm`,onClick:()=>l(e),children:`编辑`}),(0,U.jsx)(W,{variant:`destructive`,size:`sm`,onClick:()=>f(e.id),children:`删除`})]})]},e.id))})]}),(0,U.jsx)(El,{page:e,totalPages:r,total:n?.total??0,onChange:t})]})}),(0,U.jsx)(Tf,{open:a,onOpenChange:o,children:(0,U.jsxs)(Ef,{children:[(0,U.jsx)(Df,{children:(0,U.jsx)(Of,{children:s.id?`编辑文章`:`新建文章`})}),(0,U.jsxs)(`div`,{className:`grid grid-cols-2 gap-3`,children:[(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`图标(emoji)`}),(0,U.jsx)(G,{value:s.icon,onChange:p(`icon`)})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`分类`}),(0,U.jsx)(G,{value:s.category,onChange:p(`category`)})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5 col-span-2`,children:[(0,U.jsx)(K,{children:`标题`}),(0,U.jsx)(G,{value:s.title,onChange:p(`title`)})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5 col-span-2`,children:[(0,U.jsx)(K,{children:`简介`}),(0,U.jsx)(G,{value:s.description,onChange:p(`description`)})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`关联弹层类型`}),(0,U.jsx)(G,{value:s.related_sheet_type,onChange:p(`related_sheet_type`)})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`发布状态`}),(0,U.jsxs)(`select`,{className:`flex h-9 w-full rounded-md border border-input bg-card px-3 text-sm`,value:s.published?`1`:`0`,onChange:e=>c({...s,published:e.target.value===`1`}),children:[(0,U.jsx)(`option`,{value:`1`,children:`已发布`}),(0,U.jsx)(`option`,{value:`0`,children:`草稿`})]})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5 col-span-2`,children:[(0,U.jsx)(K,{children:`正文`}),(0,U.jsx)(`textarea`,{className:`flex min-h-24 w-full rounded-md border border-input bg-card px-3 py-2 text-sm`,value:s.content,onChange:p(`content`)})]})]}),(0,U.jsxs)(`div`,{className:`flex justify-end gap-2 pt-2`,children:[(0,U.jsx)(W,{variant:`outline`,onClick:()=>o(!1),children:`取消`}),(0,U.jsx)(W,{onClick:d,children:`保存`})]})]})})]})}var jf=[{key:`cat`,label:`猫猫`,Icon:Uo},{key:`dog`,label:`狗狗`,Icon:qo}],Mf={vaccine:`疫苗`,deworm:`驱虫`,weight:`体重`,monthlyReport:`月报`},Nf=[`vaccine`,`deworm`,`weight`,`monthlyReport`],Pf=[{key:`daily`,label:`每天`},{key:`weekly`,label:`每周`},{key:`monthly`,label:`每月`},{key:`once`,label:`一次性`}],Ff=[`一`,`二`,`三`,`四`,`五`,`六`,`日`],If=`h-9 rounded-md border border-input bg-card px-2 text-sm shrink-0`,Lf=1;function Rf(e){return{_k:Lf++,kind:e.kind===`reminder`?`reminder`:`plan`,title:e.title||``,description:e.description||``,priority:e.priority||``,sheet_type:e.sheet_type||``,repeat:e.repeat||`once`,day:e.day??0,weekdays:e.weekdays||``,month_day:e.month_day??1,reminder_type:e.reminder_type||`vaccine`,offset_days:e.offset_days??0,frequency:e.frequency||``}}function zf(e){return Rf({kind:e,repeat:e===`plan`?`daily`:``})}function Bf(){let[e,t]=(0,S.useState)([]),[n,r]=(0,S.useState)([]),[i,a]=(0,S.useState)([]),[o,s]=(0,S.useState)(!1),[c,l]=(0,S.useState)({id:``,species:`cat`,stage:`成年期`,name:``,summary:``,sort:0,enabled:!0}),[u,d]=(0,S.useState)([]),[f,p]=(0,S.useState)(``),[m,h]=(0,S.useState)(!1),[g,_]=(0,S.useState)(!1);function v(){z.careTemplates().then(e=>t(e||[])).catch(()=>t([]))}(0,S.useEffect)(()=>{v(),z.careTemplateMeta().then(e=>{r(e?.record_types||[]),a(e?.stages||[])}).catch(()=>{})},[]);function y(){l({id:``,species:`cat`,stage:`成年期`,name:``,summary:``,sort:0,enabled:!0}),d([]),p(``),s(!0)}async function b(e){p(``);let t=await z.careTemplate(e.id);l({...e}),d((t?.items||[]).map(Rf)),s(!0)}async function x(){p(``),h(!0);try{await z.saveCareTemplate({...c,items:u}),s(!1),v()}catch(e){p(e?.message||`保存失败`)}finally{h(!1)}}async function C(e){confirm(`删除方案「${e.name||e.stage}」?已经套用出去的计划不受影响。`)&&(await z.deleteCareTemplate(e.id).catch(e=>alert(e?.message||`删除失败`)),v())}async function w(){_(!0);try{let e=await z.genCareTemplate(c.species,c.stage);d((e?.items||[]).map(Rf))}catch(e){p(e?.message||`AI 生成失败`)}finally{_(!1)}}let T=(e,t,n)=>d(r=>r.map(r=>r._k===e?{...r,[t]:n}:r)),ee=e=>d(t=>t.filter(t=>t._k!==e));function te(e,t){let n=String(t+1),r=e.weekdays.split(`,`).filter(Boolean),i=r.includes(n)?r.filter(e=>e!==n):[...r,n].sort();T(e._k,`weekdays`,i.join(`,`))}let ne=u.filter(e=>e.kind===`plan`),E=u.filter(e=>e.kind===`reminder`);function D(e){let t=e.items||[],n={daily:0,weekly:0,monthly:0,once:0,rem:0};return t.forEach(e=>{e.kind===`reminder`?n.rem++:e.repeat===`daily`?n.daily++:e.repeat===`weekly`?n.weekly++:e.repeat===`monthly`?n.monthly++:n.once++}),n}return(0,U.jsxs)(`div`,{children:[(0,U.jsxs)(`div`,{className:`mb-6 flex items-center justify-between`,children:[(0,U.jsxs)(`div`,{children:[(0,U.jsx)(`h1`,{className:`text-2xl font-bold`,children:`养护方案`}),(0,U.jsx)(`p`,{className:`mt-1 text-sm text-muted-foreground`,children:`用户建档最后一步从这里挑一套,也可以选「先空着自己排」。同一个物种阶段可以配多套。`})]}),(0,U.jsxs)(W,{onClick:y,children:[(0,U.jsx)(rs,{className:`h-4 w-4`}),` 新建方案`]})]}),(0,U.jsx)(pl,{children:(0,U.jsx)(gl,{className:`pt-6`,children:(0,U.jsxs)(bl,{children:[(0,U.jsx)(xl,{children:(0,U.jsxs)(Cl,{children:[(0,U.jsx)(q,{className:`w-24`,children:`物种/阶段`}),(0,U.jsx)(q,{children:`方案名`}),(0,U.jsx)(q,{children:`内容`}),(0,U.jsx)(q,{className:`w-20`,children:`状态`}),(0,U.jsx)(q,{className:`w-32 text-right`,children:`操作`})]})}),(0,U.jsxs)(Sl,{children:[e.map(e=>{let t=D(e);return(0,U.jsxs)(Cl,{children:[(0,U.jsxs)(J,{className:`text-muted-foreground`,children:[e.species===`dog`?`狗`:`猫`,` · `,e.stage]}),(0,U.jsxs)(J,{children:[(0,U.jsx)(`div`,{className:`font-medium`,children:e.name||`(未命名)`}),(0,U.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:e.summary})]}),(0,U.jsxs)(J,{className:`text-xs text-muted-foreground`,children:[`每天 `,t.daily,` · 每周 `,t.weekly,` · 每月 `,t.monthly,` · 一次性 `,t.once,` · 提醒 `,t.rem]}),(0,U.jsx)(J,{children:e.enabled?(0,U.jsx)(Tl,{children:`启用`}):(0,U.jsx)(Tl,{variant:`secondary`,children:`停用`})}),(0,U.jsxs)(J,{className:`text-right`,children:[(0,U.jsx)(W,{variant:`ghost`,size:`sm`,onClick:()=>b(e),children:`编辑`}),(0,U.jsx)(W,{variant:`ghost`,size:`sm`,onClick:()=>C(e),children:`删除`})]})]},e.id)}),!e.length&&(0,U.jsx)(Cl,{children:(0,U.jsx)(J,{colSpan:5,className:`py-10 text-center text-muted-foreground`,children:`还没有方案 —— 用户建档后计划页会是空的,只能自己排`})})]})]})})}),(0,U.jsx)(Tf,{open:o,onOpenChange:s,children:(0,U.jsxs)(Ef,{className:`max-h-[88vh] max-w-4xl overflow-y-auto`,children:[(0,U.jsx)(Df,{children:(0,U.jsx)(Of,{children:c.id?`编辑方案`:`新建方案`})}),(0,U.jsxs)(`div`,{className:`grid gap-4`,children:[(0,U.jsxs)(`div`,{className:`grid grid-cols-2 gap-4`,children:[(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`物种`}),(0,U.jsx)(`div`,{className:`flex gap-2`,children:jf.map(e=>(0,U.jsxs)(W,{type:`button`,size:`sm`,variant:c.species===e.key?`default`:`outline`,onClick:()=>l({...c,species:e.key}),children:[(0,U.jsx)(e.Icon,{className:`h-4 w-4`}),` `,e.label]},e.key))})]}),(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`阶段`}),(0,U.jsx)(`select`,{className:If,value:c.stage,onChange:e=>l({...c,stage:e.target.value}),children:i.map(e=>(0,U.jsx)(`option`,{value:e,children:e},e))})]})]}),(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`方案名(用户建档时看到的就是这个)`}),(0,U.jsx)(G,{value:c.name,onChange:e=>l({...c,name:e.target.value}),placeholder:`幼猫标准照护`})]}),(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`一句话摘要`}),(0,U.jsx)(G,{value:c.summary,onChange:e=>l({...c,summary:e.target.value}),placeholder:`每天清砂盆和喂食,每周称体重,含疫苗驱虫提醒`})]}),(0,U.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,U.jsx)(`input`,{id:`ct-enabled`,type:`checkbox`,checked:c.enabled,onChange:e=>l({...c,enabled:e.target.checked})}),(0,U.jsx)(K,{htmlFor:`ct-enabled`,className:`cursor-pointer`,children:`启用(停用后建档时挑不到)`})]}),(0,U.jsxs)(`div`,{className:`rounded-md border p-3`,children:[(0,U.jsxs)(`div`,{className:`mb-3 flex items-center justify-between`,children:[(0,U.jsxs)(`div`,{className:`font-medium`,children:[`计划事项(`,ne.length,`)`]}),(0,U.jsxs)(`div`,{className:`flex gap-2`,children:[(0,U.jsxs)(W,{size:`sm`,variant:`outline`,onClick:w,disabled:g,children:[(0,U.jsx)(cs,{className:`h-4 w-4`}),` `,g?`生成中…`:`AI 起草`]}),(0,U.jsxs)(W,{size:`sm`,variant:`outline`,onClick:()=>d([...u,zf(`plan`)]),children:[(0,U.jsx)(rs,{className:`h-4 w-4`}),` 加一条`]})]})]}),(0,U.jsxs)(`div`,{className:`mb-3 flex items-start gap-2 rounded bg-muted p-2 text-xs text-muted-foreground`,children:[(0,U.jsx)(Yo,{className:`mt-0.5 h-3.5 w-3.5 shrink-0`}),(0,U.jsx)(`span`,{children:`「关联记录事项」= 用户在小程序点这条计划时,直接跳到哪个记录表单。 比如「记录一次体重」关联体重,点了就是体重表单,不用自己去记录页找。 这个下拉读的是记录事项那一页的配置。`})]}),(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[ne.map(e=>(0,U.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,U.jsx)(G,{className:`min-w-40 flex-1`,placeholder:`做什么`,value:e.title,onChange:t=>T(e._k,`title`,t.target.value)}),(0,U.jsx)(G,{className:`min-w-40 flex-1`,placeholder:`说明`,value:e.description,onChange:t=>T(e._k,`description`,t.target.value)}),(0,U.jsx)(`select`,{className:If,value:e.repeat,onChange:t=>T(e._k,`repeat`,t.target.value),children:Pf.map(e=>(0,U.jsx)(`option`,{value:e.key,children:e.label},e.key))}),e.repeat===`weekly`&&(0,U.jsx)(`div`,{className:`flex gap-1`,children:Ff.map((t,n)=>(0,U.jsx)(`button`,{type:`button`,onClick:()=>te(e,n),className:`h-7 w-7 rounded text-xs `+(e.weekdays.split(`,`).includes(String(n+1))?`bg-primary text-primary-foreground`:`border border-input bg-card`),children:t},t))}),e.repeat===`monthly`&&(0,U.jsx)(G,{type:`number`,className:`w-20`,placeholder:`几号`,value:e.month_day,onChange:t=>T(e._k,`month_day`,Number(t.target.value)||1)}),e.repeat===`once`&&(0,U.jsx)(G,{type:`number`,className:`w-24`,placeholder:`第N天`,value:e.day,onChange:t=>T(e._k,`day`,Number(t.target.value)||0)}),(0,U.jsxs)(`select`,{className:If,value:e.priority,onChange:t=>T(e._k,`priority`,t.target.value),children:[(0,U.jsx)(`option`,{value:``,children:`普通`}),(0,U.jsx)(`option`,{value:`重要`,children:`重要`})]}),(0,U.jsxs)(`select`,{className:If,value:e.sheet_type,onChange:t=>T(e._k,`sheet_type`,t.target.value),children:[(0,U.jsx)(`option`,{value:``,children:`不关联`}),n.map(e=>(0,U.jsx)(`option`,{value:e.code,children:e.label},e.code))]}),(0,U.jsx)(W,{variant:`ghost`,size:`sm`,onClick:()=>ee(e._k),children:(0,U.jsx)(os,{className:`h-4 w-4`})})]},e._k)),!ne.length&&(0,U.jsx)(`p`,{className:`py-4 text-center text-sm text-muted-foreground`,children:`还没有计划事项`})]})]}),(0,U.jsxs)(`div`,{className:`rounded-md border p-3`,children:[(0,U.jsxs)(`div`,{className:`mb-3 flex items-center justify-between`,children:[(0,U.jsxs)(`div`,{className:`font-medium`,children:[`到期提醒(`,E.length,`)`]}),(0,U.jsxs)(W,{size:`sm`,variant:`outline`,onClick:()=>d([...u,zf(`reminder`)]),children:[(0,U.jsx)(rs,{className:`h-4 w-4`}),` 加一条`]})]}),(0,U.jsx)(`p`,{className:`mb-3 text-xs text-muted-foreground`,children:`提醒不占计划页的格子,只在到期时冒出来。疫苗和驱虫这两类建档时就会自动建 (漏针是真会出事的),不用等用户挑方案。`}),(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[E.map(e=>(0,U.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,U.jsx)(`select`,{className:If,value:e.reminder_type,onChange:t=>T(e._k,`reminder_type`,t.target.value),children:Nf.map(e=>(0,U.jsx)(`option`,{value:e,children:Mf[e]},e))}),(0,U.jsx)(G,{className:`min-w-40 flex-1`,placeholder:`提醒标题`,value:e.title,onChange:t=>T(e._k,`title`,t.target.value)}),(0,U.jsx)(G,{type:`number`,className:`w-28`,placeholder:`N天后到期`,value:e.offset_days,onChange:t=>T(e._k,`offset_days`,Number(t.target.value)||0)}),(0,U.jsx)(G,{className:`w-40`,placeholder:`频率说明`,value:e.frequency,onChange:t=>T(e._k,`frequency`,t.target.value)}),(0,U.jsx)(W,{variant:`ghost`,size:`sm`,onClick:()=>ee(e._k),children:(0,U.jsx)(os,{className:`h-4 w-4`})})]},e._k)),!E.length&&(0,U.jsx)(`p`,{className:`py-4 text-center text-sm text-muted-foreground`,children:`还没有提醒`})]})]}),f&&(0,U.jsx)(`p`,{className:`text-sm text-destructive`,children:f}),(0,U.jsx)(W,{onClick:x,disabled:m,children:m?`保存中…`:`保存方案`})]})]})})]})}var Vf={id:``,code:``,label:``,icon:`note`,group:`daily`,sort:0,enabled:!0,form:`simple`,locked:!1,fields_raw:``},Hf=[{key:`daily`,label:`日常`},{key:`health`,label:`健康`},{key:`care`,label:`洗护`},{key:`clean`,label:`清洁`}],Uf=`number:体重:kg 数值,落 num_value +`},Fd=0,Id=[];function Ld(e){var t=S.useRef([]),n=S.useRef([0,0]),r=S.useRef(),i=S.useState(Fd++)[0],a=S.useState(od)[0],o=S.useRef(e);S.useEffect(function(){o.current=e},[e]),S.useEffect(function(){if(e.inert){document.body.classList.add(`block-interactivity-${i}`);var t=Fu([e.lockRef.current],(e.shards||[]).map(Md),!0).filter(Boolean);return t.forEach(function(e){return e.classList.add(`allow-interactivity-${i}`)}),function(){document.body.classList.remove(`block-interactivity-${i}`),t.forEach(function(e){return e.classList.remove(`allow-interactivity-${i}`)})}}},[e.inert,e.lockRef.current,e.shards]);var s=S.useCallback(function(e,t){if(`touches`in e&&e.touches.length===2||e.type===`wheel`&&e.ctrlKey)return!o.current.allowPinchZoom;var i=Ad(e),a=n.current,s=`deltaX`in e?e.deltaX:a[0]-i[0],c=`deltaY`in e?e.deltaY:a[1]-i[1],l,u=e.target,d=Math.abs(s)>Math.abs(c)?`h`:`v`;if(`touches`in e&&d===`h`&&u.type===`range`)return!1;var f=window.getSelection(),p=f&&f.anchorNode;if(p&&(p===u||p.contains(u)))return!1;var m=Cd(d,u);if(!m)return!0;if(m?l=d:(l=d===`v`?`h`:`v`,m=Cd(d,u)),!m)return!1;if(!r.current&&`changedTouches`in e&&(s||c)&&(r.current=l),!l)return!0;var h=r.current||l;return kd(h,t,e,h===`h`?s:c,!0)},[]),c=S.useCallback(function(e){var n=e;if(!(!Id.length||Id[Id.length-1]!==a)){var r=`deltaY`in n?jd(n):Ad(n),i=t.current.filter(function(e){return e.name===n.type&&(e.target===n.target||n.target===e.shadowParent)&&Nd(e.delta,r)})[0];if(i&&i.should){n.cancelable&&n.preventDefault();return}if(!i){var c=(o.current.shards||[]).map(Md).filter(Boolean).filter(function(e){return e.contains(n.target)});(c.length>0?s(n,c[0]):!o.current.noIsolation)&&n.cancelable&&n.preventDefault()}}},[]),l=S.useCallback(function(e,n,r,i){var a={name:e,delta:n,target:r,should:i,shadowParent:Rd(r)};t.current.push(a),setTimeout(function(){t.current=t.current.filter(function(e){return e!==a})},1)},[]),u=S.useCallback(function(e){n.current=Ad(e),r.current=void 0},[]),d=S.useCallback(function(t){l(t.type,jd(t),t.target,s(t,e.lockRef.current))},[]),f=S.useCallback(function(t){l(t.type,Ad(t),t.target,s(t,e.lockRef.current))},[]);S.useEffect(function(){return Id.push(a),e.setCallbacks({onScrollCapture:d,onWheelCapture:d,onTouchMoveCapture:f}),document.addEventListener(`wheel`,c,$),document.addEventListener(`touchmove`,c,$),document.addEventListener(`touchstart`,u,$),function(){Id=Id.filter(function(e){return e!==a}),document.removeEventListener(`wheel`,c,$),document.removeEventListener(`touchmove`,c,$),document.removeEventListener(`touchstart`,u,$)}},[]);var p=e.removeScrollBar,m=e.inert;return S.createElement(S.Fragment,null,m?S.createElement(a,{styles:Pd(i)}):null,p?S.createElement(gd,{noRelative:e.noRelative,gapMode:e.gapMode}):null)}function Rd(e){for(var t=null;e!==null;)e instanceof ShadowRoot&&(t=e.host,e=e.host),e=e.parentNode;return t}var zd=Yu(Xu,Ld),Bd=S.forwardRef(function(e,t){return S.createElement(Qu,Nu({},e,{ref:t,sideCar:zd}))});Bd.classNames=Qu.classNames;var Vd=function(e){return typeof document>`u`?null:(Array.isArray(e)?e[0]:e).ownerDocument.body},Hd=new WeakMap,Ud=new WeakMap,Wd={},Gd=0,Kd=function(e){return e&&(e.host||Kd(e.parentNode))},qd=function(e,t){return t.map(function(t){if(e.contains(t))return t;var n=Kd(t);return n&&e.contains(n)?n:(console.error(`aria-hidden`,t,`in not contained inside`,e,`. Doing nothing`),null)}).filter(function(e){return!!e})},Jd=function(e,t,n,r){var i=qd(t,Array.isArray(e)?e:[e]);Wd[n]||(Wd[n]=new WeakMap);var a=Wd[n],o=[],s=new Set,c=new Set(i),l=function(e){!e||s.has(e)||(s.add(e),l(e.parentNode))};i.forEach(l);var u=function(e){!e||c.has(e)||Array.prototype.forEach.call(e.children,function(e){if(s.has(e))u(e);else try{var t=e.getAttribute(r),i=t!==null&&t!==`false`,c=(Hd.get(e)||0)+1,l=(a.get(e)||0)+1;Hd.set(e,c),a.set(e,l),o.push(e),c===1&&i&&Ud.set(e,!0),l===1&&e.setAttribute(n,`true`),i||e.setAttribute(r,`true`)}catch(t){console.error(`aria-hidden: cannot operate on `,e,t)}})};return u(t),s.clear(),Gd++,function(){o.forEach(function(e){var t=Hd.get(e)-1,i=a.get(e)-1;Hd.set(e,t),a.set(e,i),t||(Ud.has(e)||e.removeAttribute(r),Ud.delete(e)),i||e.removeAttribute(n)}),Gd--,Gd||(Hd=new WeakMap,Hd=new WeakMap,Ud=new WeakMap,Wd={})}},Yd=function(e,t,n){n===void 0&&(n=`data-aria-hidden`);var r=Array.from(Array.isArray(e)?e:[e]),i=t||Vd(e);return i?(r.push.apply(r,Array.from(i.querySelectorAll(`[aria-live], script`))),Jd(r,i,n,`aria-hidden`)):function(){return null}},Xd=`Dialog`,[Zd,Qd]=Pl(Xd),[$d,ef]=Zd(Xd),tf=e=>{let{__scopeDialog:t,children:n,open:r,defaultOpen:i,onOpenChange:a,modal:o=!0}=e,s=S.useRef(null),c=S.useRef(null),[l,u]=Bl({prop:r,defaultProp:i??!1,onChange:a,caller:Xd});return(0,U.jsx)($d,{scope:t,triggerRef:s,contentRef:c,contentId:Z(),titleId:Z(),descriptionId:Z(),open:l,onOpenChange:u,onOpenToggle:S.useCallback(()=>u(e=>!e),[u]),modal:o,children:n})};tf.displayName=Xd;var nf=`DialogTrigger`,rf=S.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,i=ef(nf,n),a=Bc(t,i.triggerRef);return(0,U.jsx)(cl.button,{type:`button`,"aria-haspopup":`dialog`,"aria-expanded":i.open,"aria-controls":i.open?i.contentId:void 0,"data-state":wf(i.open),...r,ref:a,onClick:Nl(e.onClick,i.onOpenToggle)})});rf.displayName=nf;var af=`DialogPortal`,[of,sf]=Zd(af,{forceMount:void 0}),cf=e=>{let{__scopeDialog:t,forceMount:n,children:r,container:i}=e,a=ef(af,t);return(0,U.jsx)(of,{scope:t,forceMount:n,children:S.Children.map(r,e=>(0,U.jsx)(Cu,{present:n||a.open,children:(0,U.jsx)(xu,{asChild:!0,container:i,children:e})}))})};cf.displayName=af;var lf=`DialogOverlay`,uf=S.forwardRef((e,t)=>{let n=sf(lf,e.__scopeDialog),{forceMount:r=n.forceMount,...i}=e,a=ef(lf,e.__scopeDialog);return a.modal?(0,U.jsx)(Cu,{present:r||a.open,children:(0,U.jsx)(ff,{...i,ref:t})}):null});uf.displayName=lf;var df=Vc(`DialogOverlay.RemoveScroll`),ff=S.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,i=ef(lf,n),a=Bc(t,$l());return(0,U.jsx)(Bd,{as:df,allowPinchZoom:!0,shards:[i.contentRef],children:(0,U.jsx)(cl.div,{"data-state":wf(i.open),...r,ref:a,style:{pointerEvents:`auto`,...r.style}})})}),pf=`DialogContent`,mf=S.forwardRef((e,t)=>{let n=sf(pf,e.__scopeDialog),{forceMount:r=n.forceMount,...i}=e,a=ef(pf,e.__scopeDialog);return(0,U.jsx)(Cu,{present:r||a.open,children:a.modal?(0,U.jsx)(hf,{...i,ref:t}):(0,U.jsx)(gf,{...i,ref:t})})});mf.displayName=pf;var hf=S.forwardRef((e,t)=>{let n=ef(pf,e.__scopeDialog),r=S.useRef(null),i=Bc(t,n.contentRef,r);return S.useEffect(()=>{let e=r.current;if(e)return Yd(e)},[]),(0,U.jsx)(_f,{...e,ref:i,trapFocus:n.open,disableOutsidePointerEvents:n.open,onCloseAutoFocus:Nl(e.onCloseAutoFocus,e=>{e.preventDefault(),n.triggerRef.current?.focus()}),onPointerDownOutside:Nl(e.onPointerDownOutside,e=>{let t=e.detail.originalEvent,n=t.button===0&&t.ctrlKey===!0;(t.button===2||n)&&e.preventDefault()}),onFocusOutside:Nl(e.onFocusOutside,e=>e.preventDefault())})}),gf=S.forwardRef((e,t)=>{let n=ef(pf,e.__scopeDialog),r=S.useRef(!1),i=S.useRef(!1);return(0,U.jsx)(_f,{...e,ref:t,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:t=>{e.onCloseAutoFocus?.(t),t.defaultPrevented||(r.current||n.triggerRef.current?.focus(),t.preventDefault()),r.current=!1,i.current=!1},onInteractOutside:t=>{e.onInteractOutside?.(t),t.defaultPrevented||(r.current=!0,t.detail.originalEvent.type===`pointerdown`&&(i.current=!0));let a=t.target;n.triggerRef.current?.contains(a)&&t.preventDefault(),t.detail.originalEvent.type===`focusin`&&i.current&&t.preventDefault()}})}),_f=S.forwardRef((e,t)=>{let{__scopeDialog:n,trapFocus:r,onOpenAutoFocus:i,onCloseAutoFocus:a,...o}=e,s=ef(pf,n);return ju(),(0,U.jsx)(U.Fragment,{children:(0,U.jsx)(cu,{asChild:!0,loop:!0,trapped:r,onMountAutoFocus:i,onUnmountAutoFocus:a,children:(0,U.jsx)(Xl,{role:`dialog`,id:s.contentId,"aria-describedby":s.descriptionId,"aria-labelledby":s.titleId,"data-state":wf(s.open),...o,ref:t,deferPointerDownOutside:!0,onDismiss:()=>s.onOpenChange(!1)})})})}),vf=`DialogTitle`,yf=S.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,i=ef(vf,n);return(0,U.jsx)(cl.h2,{id:i.titleId,...r,ref:t})});yf.displayName=vf;var bf=`DialogDescription`,xf=S.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,i=ef(bf,n);return(0,U.jsx)(cl.p,{id:i.descriptionId,...r,ref:t})});xf.displayName=bf;var Sf=`DialogClose`,Cf=S.forwardRef((e,t)=>{let{__scopeDialog:n,...r}=e,i=ef(Sf,n);return(0,U.jsx)(cl.button,{type:`button`,...r,ref:t,onClick:Nl(e.onClick,()=>i.onOpenChange(!1))})});Cf.displayName=Sf;function wf(e){return e?`open`:`closed`}var Tf=tf,Ef=S.forwardRef(({className:e,children:t,...n},r)=>(0,U.jsxs)(cf,{children:[(0,U.jsx)(uf,{className:`fixed inset-0 z-50 bg-black/40 data-[state=open]:animate-in data-[state=closed]:animate-out`}),(0,U.jsxs)(mf,{ref:r,className:Lc(`fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border bg-card p-6 shadow-lg rounded-xl`,e),...n,children:[t,(0,U.jsx)(Cf,{className:`absolute right-4 top-4 opacity-70 hover:opacity-100`,children:(0,U.jsx)(ls,{className:`h-4 w-4`})})]})]}));Ef.displayName=`DialogContent`;function Df({className:e,...t}){return(0,U.jsx)(`div`,{className:Lc(`flex flex-col space-y-1.5`,e),...t})}function Of({className:e,...t}){return(0,U.jsx)(`h2`,{className:Lc(`text-lg font-semibold`,e),...t})}var kf={id:0,icon:`📘`,title:``,description:``,content:``,category:``,related_sheet_type:``,published:!0};function Af(){let{page:e,setPage:t,data:n,totalPages:r,reload:i}=yl(z.articles),[a,o]=(0,S.useState)(!1),[s,c]=(0,S.useState)(kf);function l(e){c({...e}),o(!0)}function u(){c({...kf}),o(!0)}async function d(){await z.saveArticle(s),o(!1),i()}async function f(e){await z.deleteArticle(e),i()}let p=e=>t=>c({...s,[e]:t.target.value});return(0,U.jsxs)(`div`,{children:[(0,U.jsxs)(`div`,{className:`flex items-center justify-between mb-6`,children:[(0,U.jsx)(`h1`,{className:`text-2xl font-bold`,children:`文章管理`}),(0,U.jsx)(W,{onClick:u,children:`新建文章`})]}),(0,U.jsx)(pl,{children:(0,U.jsxs)(gl,{className:`pt-6`,children:[(0,U.jsxs)(bl,{children:[(0,U.jsx)(xl,{children:(0,U.jsxs)(Cl,{children:[(0,U.jsx)(q,{children:`ID`}),(0,U.jsx)(q,{children:`标题`}),(0,U.jsx)(q,{children:`分类`}),(0,U.jsx)(q,{children:`关联弹层`}),(0,U.jsx)(q,{children:`状态`}),(0,U.jsx)(q,{className:`text-right`,children:`操作`})]})}),(0,U.jsx)(Sl,{children:n?.list?.map(e=>(0,U.jsxs)(Cl,{children:[(0,U.jsx)(J,{children:e.id}),(0,U.jsxs)(J,{className:`font-medium`,children:[(0,U.jsx)(`span`,{className:`mr-1`,children:e.icon}),e.title]}),(0,U.jsx)(J,{children:e.category||`—`}),(0,U.jsx)(J,{children:e.related_sheet_type||`—`}),(0,U.jsx)(J,{children:e.published?(0,U.jsx)(Tl,{variant:`success`,children:`已发布`}):(0,U.jsx)(Tl,{variant:`muted`,children:`草稿`})}),(0,U.jsxs)(J,{className:`text-right space-x-2 whitespace-nowrap`,children:[(0,U.jsx)(W,{variant:`outline`,size:`sm`,onClick:()=>l(e),children:`编辑`}),(0,U.jsx)(W,{variant:`destructive`,size:`sm`,onClick:()=>f(e.id),children:`删除`})]})]},e.id))})]}),(0,U.jsx)(El,{page:e,totalPages:r,total:n?.total??0,onChange:t})]})}),(0,U.jsx)(Tf,{open:a,onOpenChange:o,children:(0,U.jsxs)(Ef,{children:[(0,U.jsx)(Df,{children:(0,U.jsx)(Of,{children:s.id?`编辑文章`:`新建文章`})}),(0,U.jsxs)(`div`,{className:`grid grid-cols-2 gap-3`,children:[(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`图标(emoji)`}),(0,U.jsx)(G,{value:s.icon,onChange:p(`icon`)})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`分类`}),(0,U.jsx)(G,{value:s.category,onChange:p(`category`)})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5 col-span-2`,children:[(0,U.jsx)(K,{children:`标题`}),(0,U.jsx)(G,{value:s.title,onChange:p(`title`)})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5 col-span-2`,children:[(0,U.jsx)(K,{children:`简介`}),(0,U.jsx)(G,{value:s.description,onChange:p(`description`)})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`关联弹层类型`}),(0,U.jsx)(G,{value:s.related_sheet_type,onChange:p(`related_sheet_type`)})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`发布状态`}),(0,U.jsxs)(`select`,{className:`flex h-9 w-full rounded-md border border-input bg-card px-3 text-sm`,value:s.published?`1`:`0`,onChange:e=>c({...s,published:e.target.value===`1`}),children:[(0,U.jsx)(`option`,{value:`1`,children:`已发布`}),(0,U.jsx)(`option`,{value:`0`,children:`草稿`})]})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5 col-span-2`,children:[(0,U.jsx)(K,{children:`正文`}),(0,U.jsx)(`textarea`,{className:`flex min-h-24 w-full rounded-md border border-input bg-card px-3 py-2 text-sm`,value:s.content,onChange:p(`content`)})]})]}),(0,U.jsxs)(`div`,{className:`flex justify-end gap-2 pt-2`,children:[(0,U.jsx)(W,{variant:`outline`,onClick:()=>o(!1),children:`取消`}),(0,U.jsx)(W,{onClick:d,children:`保存`})]})]})})]})}var jf=[{key:`cat`,label:`猫猫`,Icon:Uo},{key:`dog`,label:`狗狗`,Icon:qo}],Mf={vaccine:`疫苗`,deworm:`驱虫`,weight:`体重`,monthlyReport:`月报`},Nf=[`vaccine`,`deworm`,`weight`,`monthlyReport`],Pf=[{key:`daily`,label:`每天`},{key:`weekly`,label:`每周`},{key:`monthly`,label:`每月`},{key:`once`,label:`一次性`}],Ff=[`一`,`二`,`三`,`四`,`五`,`六`,`日`],If=[`刚到家 0-30 天`,`幼年期`,`青年期`,`成年期`,`中年期`,`老年期`],Lf=`h-9 rounded-md border border-input bg-card px-2 text-sm shrink-0`,Rf=1;function zf(e){return{_k:Rf++,kind:e.kind===`reminder`?`reminder`:`plan`,title:e.title||``,description:e.description||``,priority:e.priority||``,sheet_type:e.sheet_type||``,repeat:e.repeat||`once`,day:e.day??0,weekdays:e.weekdays||``,month_day:e.month_day??1,reminder_type:e.reminder_type||`vaccine`,offset_days:e.offset_days??0,frequency:e.frequency||``}}function Bf(e){return zf({kind:e,repeat:e===`plan`?`daily`:``})}function Vf(){let[e,t]=(0,S.useState)([]),[n,r]=(0,S.useState)(`cat`),[i,a]=(0,S.useState)([]),[o,s]=(0,S.useState)([]),[c,l]=(0,S.useState)(!1),[u,d]=(0,S.useState)({id:``,species:`cat`,stage:`成年期`,name:``,summary:``,sort:0,enabled:!0}),[f,p]=(0,S.useState)([]),[m,h]=(0,S.useState)(``),[g,_]=(0,S.useState)(!1),[v,y]=(0,S.useState)(!1);function b(){z.careTemplates().then(e=>t(e||[])).catch(()=>t([]))}(0,S.useEffect)(()=>{b(),z.careTemplateMeta().then(e=>{a(e?.record_types||[]),s(e?.stages||[])}).catch(()=>{})},[]);function x(){d({id:``,species:n,stage:`成年期`,name:``,summary:``,sort:0,enabled:!0}),p([]),h(``),l(!0)}async function C(e){h(``);let t=await z.careTemplate(e.id);d({...e}),p((t?.items||[]).map(zf)),l(!0)}async function w(){h(``),_(!0);try{await z.saveCareTemplate({...u,items:f}),l(!1),b()}catch(e){h(e?.message||`保存失败`)}finally{_(!1)}}async function T(e){confirm(`删除方案「${e.name||e.stage}」?已经套用出去的计划不受影响。`)&&(await z.deleteCareTemplate(e.id).catch(e=>alert(e?.message||`删除失败`)),b())}async function ee(){y(!0);try{let e=await z.genCareTemplate(u.species,u.stage);p((e?.items||[]).map(zf))}catch(e){h(e?.message||`AI 生成失败`)}finally{y(!1)}}let te=(e,t,n)=>p(r=>r.map(r=>r._k===e?{...r,[t]:n}:r)),ne=e=>p(t=>t.filter(t=>t._k!==e));function E(e,t){let n=String(t+1),r=e.weekdays.split(`,`).filter(Boolean),i=r.includes(n)?r.filter(e=>e!==n):[...r,n].sort();te(e._k,`weekdays`,i.join(`,`))}let D=If,O=e.filter(e=>e.species===n).sort((e,t)=>D.indexOf(e.stage)-D.indexOf(t.stage)),re=f.filter(e=>e.kind===`plan`),ie=f.filter(e=>e.kind===`reminder`);function ae(e){let t=e.items||[],n={daily:0,weekly:0,monthly:0,once:0,rem:0};return t.forEach(e=>{e.kind===`reminder`?n.rem++:e.repeat===`daily`?n.daily++:e.repeat===`weekly`?n.weekly++:e.repeat===`monthly`?n.monthly++:n.once++}),n}return(0,U.jsxs)(`div`,{children:[(0,U.jsxs)(`div`,{className:`mb-6 flex items-center justify-between`,children:[(0,U.jsxs)(`div`,{children:[(0,U.jsx)(`h1`,{className:`text-2xl font-bold`,children:`养护方案`}),(0,U.jsx)(`p`,{className:`mt-1 text-sm text-muted-foreground`,children:`用户建档最后一步从这里挑一套,也可以选「先空着自己排」。同一个物种阶段可以配多套。`})]}),(0,U.jsxs)(W,{onClick:x,children:[(0,U.jsx)(rs,{className:`h-4 w-4`}),` 新建方案`]})]}),(0,U.jsx)(`div`,{className:`mb-4 flex items-center gap-2`,children:jf.map(t=>{let i=e.filter(e=>e.species===t.key).length;return(0,U.jsxs)(W,{size:`sm`,variant:n===t.key?`default`:`outline`,onClick:()=>r(t.key),children:[(0,U.jsx)(t.Icon,{className:`h-4 w-4`}),` `,t.label,` `,i]},t.key)})}),(0,U.jsx)(pl,{children:(0,U.jsx)(gl,{className:`pt-6`,children:(0,U.jsxs)(bl,{children:[(0,U.jsx)(xl,{children:(0,U.jsxs)(Cl,{children:[(0,U.jsx)(q,{className:`w-24`,children:`阶段`}),(0,U.jsx)(q,{children:`方案名`}),(0,U.jsx)(q,{children:`内容`}),(0,U.jsx)(q,{className:`w-20`,children:`状态`}),(0,U.jsx)(q,{className:`w-32 text-right`,children:`操作`})]})}),(0,U.jsxs)(Sl,{children:[O.map(e=>{let t=ae(e);return(0,U.jsxs)(Cl,{children:[(0,U.jsx)(J,{className:`text-muted-foreground`,children:e.stage}),(0,U.jsxs)(J,{children:[(0,U.jsx)(`div`,{className:`font-medium`,children:e.name||`(未命名)`}),(0,U.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:e.summary})]}),(0,U.jsxs)(J,{className:`text-xs text-muted-foreground`,children:[`每天 `,t.daily,` · 每周 `,t.weekly,` · 每月 `,t.monthly,` · 一次性 `,t.once,` · 提醒 `,t.rem]}),(0,U.jsx)(J,{children:e.enabled?(0,U.jsx)(Tl,{children:`启用`}):(0,U.jsx)(Tl,{variant:`secondary`,children:`停用`})}),(0,U.jsxs)(J,{className:`text-right`,children:[(0,U.jsx)(W,{variant:`ghost`,size:`sm`,onClick:()=>C(e),children:`编辑`}),(0,U.jsx)(W,{variant:`ghost`,size:`sm`,onClick:()=>T(e),children:`删除`})]})]},e.id)}),!O.length&&(0,U.jsx)(Cl,{children:(0,U.jsx)(J,{colSpan:5,className:`py-10 text-center text-muted-foreground`,children:`这个物种还没有方案 —— 用户建档后计划页会是空的,只能自己排`})})]})]})})}),(0,U.jsx)(Tf,{open:c,onOpenChange:l,children:(0,U.jsxs)(Ef,{className:`max-h-[88vh] max-w-4xl overflow-y-auto`,children:[(0,U.jsx)(Df,{children:(0,U.jsx)(Of,{children:u.id?`编辑方案`:`新建方案`})}),(0,U.jsxs)(`div`,{className:`grid gap-4`,children:[(0,U.jsxs)(`div`,{className:`grid grid-cols-2 gap-4`,children:[(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`物种`}),(0,U.jsx)(`div`,{className:`flex gap-2`,children:jf.map(e=>(0,U.jsxs)(W,{type:`button`,size:`sm`,variant:u.species===e.key?`default`:`outline`,onClick:()=>d({...u,species:e.key}),children:[(0,U.jsx)(e.Icon,{className:`h-4 w-4`}),` `,e.label]},e.key))})]}),(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`阶段`}),(0,U.jsx)(`select`,{className:Lf,value:u.stage,onChange:e=>d({...u,stage:e.target.value}),children:o.map(e=>(0,U.jsx)(`option`,{value:e,children:e},e))})]})]}),(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`方案名(用户建档时看到的就是这个)`}),(0,U.jsx)(G,{value:u.name,onChange:e=>d({...u,name:e.target.value}),placeholder:`幼猫标准照护`})]}),(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`一句话摘要`}),(0,U.jsx)(G,{value:u.summary,onChange:e=>d({...u,summary:e.target.value}),placeholder:`每天清砂盆和喂食,每周称体重,含疫苗驱虫提醒`})]}),(0,U.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,U.jsx)(`input`,{id:`ct-enabled`,type:`checkbox`,checked:u.enabled,onChange:e=>d({...u,enabled:e.target.checked})}),(0,U.jsx)(K,{htmlFor:`ct-enabled`,className:`cursor-pointer`,children:`启用(停用后建档时挑不到)`})]}),(0,U.jsxs)(`div`,{className:`rounded-md border p-3`,children:[(0,U.jsxs)(`div`,{className:`mb-3 flex items-center justify-between`,children:[(0,U.jsxs)(`div`,{className:`font-medium`,children:[`计划事项(`,re.length,`)`]}),(0,U.jsxs)(`div`,{className:`flex gap-2`,children:[(0,U.jsxs)(W,{size:`sm`,variant:`outline`,onClick:ee,disabled:v,children:[(0,U.jsx)(cs,{className:`h-4 w-4`}),` `,v?`生成中…`:`AI 起草`]}),(0,U.jsxs)(W,{size:`sm`,variant:`outline`,onClick:()=>p([...f,Bf(`plan`)]),children:[(0,U.jsx)(rs,{className:`h-4 w-4`}),` 加一条`]})]})]}),(0,U.jsxs)(`div`,{className:`mb-3 flex items-start gap-2 rounded bg-muted p-2 text-xs text-muted-foreground`,children:[(0,U.jsx)(Yo,{className:`mt-0.5 h-3.5 w-3.5 shrink-0`}),(0,U.jsx)(`span`,{children:`「关联记录事项」= 用户在小程序点这条计划时,直接跳到哪个记录表单。 比如「记录一次体重」关联体重,点了就是体重表单,不用自己去记录页找。 这个下拉读的是记录事项那一页的配置。`})]}),(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[re.map(e=>(0,U.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,U.jsx)(G,{className:`min-w-40 flex-1`,placeholder:`做什么`,value:e.title,onChange:t=>te(e._k,`title`,t.target.value)}),(0,U.jsx)(G,{className:`min-w-40 flex-1`,placeholder:`说明`,value:e.description,onChange:t=>te(e._k,`description`,t.target.value)}),(0,U.jsx)(`select`,{className:Lf,value:e.repeat,onChange:t=>te(e._k,`repeat`,t.target.value),children:Pf.map(e=>(0,U.jsx)(`option`,{value:e.key,children:e.label},e.key))}),e.repeat===`weekly`&&(0,U.jsx)(`div`,{className:`flex gap-1`,children:Ff.map((t,n)=>(0,U.jsx)(`button`,{type:`button`,onClick:()=>E(e,n),className:`h-7 w-7 rounded text-xs `+(e.weekdays.split(`,`).includes(String(n+1))?`bg-primary text-primary-foreground`:`border border-input bg-card`),children:t},t))}),e.repeat===`monthly`&&(0,U.jsx)(G,{type:`number`,className:`w-20`,placeholder:`几号`,value:e.month_day,onChange:t=>te(e._k,`month_day`,Number(t.target.value)||1)}),e.repeat===`once`&&(0,U.jsx)(G,{type:`number`,className:`w-24`,placeholder:`第N天`,value:e.day,onChange:t=>te(e._k,`day`,Number(t.target.value)||0)}),(0,U.jsxs)(`select`,{className:Lf,value:e.priority,onChange:t=>te(e._k,`priority`,t.target.value),children:[(0,U.jsx)(`option`,{value:``,children:`普通`}),(0,U.jsx)(`option`,{value:`重要`,children:`重要`})]}),(0,U.jsxs)(`select`,{className:Lf,value:e.sheet_type,onChange:t=>te(e._k,`sheet_type`,t.target.value),children:[(0,U.jsx)(`option`,{value:``,children:`不关联`}),i.map(e=>(0,U.jsx)(`option`,{value:e.code,children:e.label},e.code))]}),(0,U.jsx)(W,{variant:`ghost`,size:`sm`,onClick:()=>ne(e._k),children:(0,U.jsx)(os,{className:`h-4 w-4`})})]},e._k)),!re.length&&(0,U.jsx)(`p`,{className:`py-4 text-center text-sm text-muted-foreground`,children:`还没有计划事项`})]})]}),(0,U.jsxs)(`div`,{className:`rounded-md border p-3`,children:[(0,U.jsxs)(`div`,{className:`mb-3 flex items-center justify-between`,children:[(0,U.jsxs)(`div`,{className:`font-medium`,children:[`到期提醒(`,ie.length,`)`]}),(0,U.jsxs)(W,{size:`sm`,variant:`outline`,onClick:()=>p([...f,Bf(`reminder`)]),children:[(0,U.jsx)(rs,{className:`h-4 w-4`}),` 加一条`]})]}),(0,U.jsx)(`p`,{className:`mb-3 text-xs text-muted-foreground`,children:`提醒不占计划页的格子,只在到期时冒出来。疫苗和驱虫这两类建档时就会自动建 (漏针是真会出事的),不用等用户挑方案。`}),(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[ie.map(e=>(0,U.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,U.jsx)(`select`,{className:Lf,value:e.reminder_type,onChange:t=>te(e._k,`reminder_type`,t.target.value),children:Nf.map(e=>(0,U.jsx)(`option`,{value:e,children:Mf[e]},e))}),(0,U.jsx)(G,{className:`min-w-40 flex-1`,placeholder:`提醒标题`,value:e.title,onChange:t=>te(e._k,`title`,t.target.value)}),(0,U.jsx)(G,{type:`number`,className:`w-28`,placeholder:`N天后到期`,value:e.offset_days,onChange:t=>te(e._k,`offset_days`,Number(t.target.value)||0)}),(0,U.jsx)(G,{className:`w-40`,placeholder:`频率说明`,value:e.frequency,onChange:t=>te(e._k,`frequency`,t.target.value)}),(0,U.jsx)(W,{variant:`ghost`,size:`sm`,onClick:()=>ne(e._k),children:(0,U.jsx)(os,{className:`h-4 w-4`})})]},e._k)),!ie.length&&(0,U.jsx)(`p`,{className:`py-4 text-center text-sm text-muted-foreground`,children:`还没有提醒`})]})]}),m&&(0,U.jsx)(`p`,{className:`text-sm text-destructive`,children:m}),(0,U.jsx)(W,{onClick:w,disabled:g,children:g?`保存中…`:`保存方案`})]})]})})]})}var Hf={id:``,code:``,label:``,icon:`note`,group:`daily`,sort:0,enabled:!0,form:`simple`,locked:!1,fields_raw:``},Uf=[{key:`daily`,label:`日常`},{key:`health`,label:`健康`},{key:`care`,label:`洗护`},{key:`clean`,label:`清洁`}],Wf=`number:体重:kg 数值,落 num_value options:状态:正常|软便|拉稀 单选,落 category options:症状:呕吐|拉稀:- 末尾 - 表示不落 category(只进标题) text:吃了什么 文本,只进标题 -(留空) 只要「时间 + 描述 + 照片」`;function Wf(){let[e,t]=(0,S.useState)([]),[n,r]=(0,S.useState)(!1),[i,a]=(0,S.useState)(Vf),[o,s]=(0,S.useState)(``);function c(){z.recordTypes().then(e=>t(e||[])).catch(()=>t([]))}(0,S.useEffect)(c,[]);function l(){a({...Vf}),s(``),r(!0)}function u(e){a({...e}),s(``),r(!0)}async function d(){s(``);try{await z.saveRecordType(i),r(!1),c()}catch(e){s(e?.message||`保存失败`)}}async function f(e){if(confirm(`删除「${e.label}」?`))try{await z.deleteRecordType(e.id),c()}catch(e){alert(e?.message||`删除失败`)}}let p=e=>t=>a({...i,[e]:t.target.value});function m(e){return e.fields?.length?(0,U.jsx)(`span`,{className:`space-x-2`,children:e.fields.map((e,t)=>(0,U.jsxs)(`span`,{className:`whitespace-nowrap text-xs`,children:[e.label,e.kind===`number`&&`·数值${e.unit||``}`,e.kind===`text`&&`·文本`,e.kind===`options`&&`·单选${e.to_category?`★`:``}`]},t))}):(0,U.jsx)(`span`,{className:`text-muted-foreground`,children:`时间 + 描述 + 照片`})}let h={};return e.forEach(e=>(h[e.group]=h[e.group]||[]).push(e)),(0,U.jsxs)(`div`,{children:[(0,U.jsxs)(`div`,{className:`mb-6 flex items-center justify-between`,children:[(0,U.jsxs)(`div`,{children:[(0,U.jsx)(`h1`,{className:`text-2xl font-bold`,children:`记录事项`}),(0,U.jsx)(`p`,{className:`mt-1 text-sm text-muted-foreground`,children:`小程序「记一笔」的事项和它们的表单字段。★ 标记的单选会落到 category —— 周报的高风险数、账单的分类统计都读这一列。`})]}),(0,U.jsx)(W,{onClick:l,children:`新增事项`})]}),(0,U.jsx)(pl,{children:(0,U.jsx)(gl,{className:`pt-6`,children:(0,U.jsxs)(bl,{children:[(0,U.jsx)(xl,{children:(0,U.jsxs)(Cl,{children:[(0,U.jsx)(q,{className:`w-20`,children:`分组`}),(0,U.jsx)(q,{className:`w-28`,children:`名称`}),(0,U.jsx)(q,{className:`w-28`,children:`code`}),(0,U.jsx)(q,{children:`表单字段`}),(0,U.jsx)(q,{className:`w-16`,children:`排序`}),(0,U.jsx)(q,{className:`w-24`,children:`状态`}),(0,U.jsx)(q,{className:`w-32 text-right`,children:`操作`})]})}),(0,U.jsxs)(Sl,{children:[Hf.map(e=>(h[e.key]||[]).map((t,n)=>(0,U.jsxs)(Cl,{children:[(0,U.jsx)(J,{className:`text-muted-foreground`,children:n===0?e.label:``}),(0,U.jsx)(J,{className:`font-medium`,children:t.label}),(0,U.jsx)(J,{className:`font-mono text-xs text-muted-foreground`,children:t.code}),(0,U.jsx)(J,{children:m(t)}),(0,U.jsx)(J,{className:`text-muted-foreground`,children:t.sort}),(0,U.jsxs)(J,{children:[t.enabled?(0,U.jsx)(Tl,{children:`启用`}):(0,U.jsx)(Tl,{variant:`secondary`,children:`停用`}),t.locked&&(0,U.jsx)(Tl,{variant:`outline`,className:`ml-1`,children:`内置`})]}),(0,U.jsxs)(J,{className:`text-right`,children:[(0,U.jsx)(W,{variant:`ghost`,size:`sm`,onClick:()=>u(t),children:`编辑`}),!t.locked&&(0,U.jsx)(W,{variant:`ghost`,size:`sm`,onClick:()=>f(t),children:`删除`})]})]},t.id))),!e.length&&(0,U.jsx)(Cl,{children:(0,U.jsx)(J,{colSpan:7,className:`py-10 text-center text-muted-foreground`,children:`还没有事项 —— 小程序的记录页会是空的`})})]})]})})}),(0,U.jsx)(Tf,{open:n,onOpenChange:r,children:(0,U.jsxs)(Ef,{className:`max-w-2xl`,children:[(0,U.jsx)(Df,{children:(0,U.jsx)(Of,{children:i.id?`编辑「${i.label}」`:`新增事项`})}),(0,U.jsxs)(`div`,{className:`grid gap-4`,children:[(0,U.jsxs)(`div`,{className:`grid grid-cols-2 gap-4`,children:[(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`名称`}),(0,U.jsx)(G,{value:i.label,onChange:p(`label`),placeholder:`洗澡`})]}),(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`code(落库的 type,建过记录后不能改)`}),(0,U.jsx)(G,{value:i.code,onChange:p(`code`),placeholder:`bath`,className:`font-mono`,disabled:i.locked})]})]}),(0,U.jsxs)(`div`,{className:`grid grid-cols-2 gap-4`,children:[(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`分组`}),(0,U.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:Hf.map(e=>(0,U.jsx)(W,{type:`button`,variant:i.group===e.key?`default`:`outline`,size:`sm`,onClick:()=>a({...i,group:e.key}),children:e.label},e.key))})]}),(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`图标名(pt-icon)`}),(0,U.jsx)(G,{value:i.icon,onChange:p(`icon`),placeholder:`bath`,className:`font-mono`})]})]}),(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`表单字段(一行一个,留空则只有「时间 + 描述 + 照片」)`}),(0,U.jsx)(`textarea`,{className:`min-h-[120px] w-full rounded-md border border-input bg-card px-3 py-2 font-mono text-sm shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring`,value:i.fields_raw||``,onChange:p(`fields_raw`),placeholder:`number:体重:kg`}),(0,U.jsx)(`pre`,{className:`whitespace-pre-wrap rounded bg-muted p-3 text-xs text-muted-foreground`,children:Uf}),(0,U.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`一个事项里最多一个字段能落 category。多出来的那个末尾加 `,(0,U.jsx)(`code`,{children:`:-`}),`。`]})]}),(0,U.jsxs)(`div`,{className:`flex items-center gap-6`,children:[(0,U.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,U.jsx)(K,{children:`排序`}),(0,U.jsx)(G,{type:`number`,value:i.sort,onChange:e=>a({...i,sort:Number(e.target.value)||0}),className:`w-24`})]}),(0,U.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,U.jsx)(`input`,{id:`rt-enabled`,type:`checkbox`,checked:i.enabled,onChange:e=>a({...i,enabled:e.target.checked})}),(0,U.jsx)(K,{htmlFor:`rt-enabled`,className:`cursor-pointer`,children:`启用`})]})]}),i.locked&&(0,U.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`这是内置事项:统计和分析逻辑依赖它的 code,不能删也不能改 code。想隐藏请改成停用。`}),o&&(0,U.jsx)(`p`,{className:`text-sm text-destructive`,children:o}),(0,U.jsx)(W,{onClick:d,children:`保存`})]})]})})]})}var Gf={id:``,species:`cat`,name:``,initial:``,sort:0,enabled:!0},Kf=[{key:`cat`,label:`猫`},{key:`dog`,label:`狗`}];function qf(){let[e,t]=(0,S.useState)(`cat`),[n,r]=(0,S.useState)([]),[i,a]=(0,S.useState)(!1),[o,s]=(0,S.useState)(Gf),[c,l]=(0,S.useState)(``);function u(){z.breeds(e).then(e=>r(e||[])).catch(()=>r([]))}(0,S.useEffect)(u,[e]);function d(){s({...Gf,species:e}),l(``),a(!0)}function f(e){s({...e}),l(``),a(!0)}async function p(){l(``);try{await z.saveBreed(o),a(!1),u()}catch(e){l(e?.message||`保存失败`)}}async function m(e){if(confirm(`删除「${e.name}」?`))try{await z.deleteBreed(e.id),u()}catch(e){alert(e?.message||`删除失败`)}}let h=e=>t=>s({...o,[e]:t.target.value}),g={};n.forEach(e=>{let t=(e.initial||`#`).toUpperCase();(g[t]=g[t]||[]).push(e)});let _=Object.keys(g).sort();return(0,U.jsxs)(`div`,{children:[(0,U.jsxs)(`div`,{className:`mb-6 flex items-center justify-between`,children:[(0,U.jsxs)(`div`,{children:[(0,U.jsx)(`h1`,{className:`text-2xl font-bold`,children:`品种管理`}),(0,U.jsx)(`p`,{className:`mt-1 text-sm text-muted-foreground`,children:`建档第二步的品种选择器读这里。首字母要手填 —— 多音字(藏獒、柴犬)自动转拼音常出错。`})]}),(0,U.jsx)(W,{onClick:d,children:`新增品种`})]}),(0,U.jsxs)(`div`,{className:`mb-4 flex gap-2`,children:[Kf.map(n=>(0,U.jsx)(W,{variant:e===n.key?`default`:`outline`,size:`sm`,onClick:()=>t(n.key),children:n.label},n.key)),(0,U.jsxs)(`span`,{className:`ml-2 self-center text-sm text-muted-foreground`,children:[`共 `,n.length,` 种,`,_.length,` 个首字母`]})]}),(0,U.jsx)(pl,{children:(0,U.jsx)(gl,{className:`pt-6`,children:(0,U.jsxs)(bl,{children:[(0,U.jsx)(xl,{children:(0,U.jsxs)(Cl,{children:[(0,U.jsx)(q,{className:`w-16`,children:`首字母`}),(0,U.jsx)(q,{children:`品种`}),(0,U.jsx)(q,{className:`w-20`,children:`排序`}),(0,U.jsx)(q,{className:`w-20`,children:`状态`}),(0,U.jsx)(q,{className:`w-32 text-right`,children:`操作`})]})}),(0,U.jsxs)(Sl,{children:[_.map(e=>g[e].map((t,n)=>(0,U.jsxs)(Cl,{children:[(0,U.jsx)(J,{className:`font-mono text-muted-foreground`,children:n===0?e:``}),(0,U.jsx)(J,{className:`font-medium`,children:t.name}),(0,U.jsx)(J,{className:`text-muted-foreground`,children:t.sort}),(0,U.jsx)(J,{children:t.enabled?(0,U.jsx)(Tl,{children:`启用`}):(0,U.jsx)(Tl,{variant:`secondary`,children:`停用`})}),(0,U.jsxs)(J,{className:`text-right`,children:[(0,U.jsx)(W,{variant:`ghost`,size:`sm`,onClick:()=>f(t),children:`编辑`}),(0,U.jsx)(W,{variant:`ghost`,size:`sm`,onClick:()=>m(t),children:`删除`})]})]},t.id))),!n.length&&(0,U.jsx)(Cl,{children:(0,U.jsx)(J,{colSpan:5,className:`py-10 text-center text-muted-foreground`,children:`还没有品种`})})]})]})})}),(0,U.jsx)(Tf,{open:i,onOpenChange:a,children:(0,U.jsxs)(Ef,{children:[(0,U.jsx)(Df,{children:(0,U.jsx)(Of,{children:o.id?`编辑品种`:`新增品种`})}),(0,U.jsxs)(`div`,{className:`grid gap-4`,children:[(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`物种`}),(0,U.jsx)(`div`,{className:`flex gap-2`,children:Kf.map(e=>(0,U.jsx)(W,{type:`button`,variant:o.species===e.key?`default`:`outline`,size:`sm`,onClick:()=>s({...o,species:e.key}),children:e.label},e.key))})]}),(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`品种名`}),(0,U.jsx)(G,{value:o.name,onChange:h(`name`),placeholder:`例如:布偶猫`})]}),(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`首字母(A-Z,一位)`}),(0,U.jsx)(G,{value:o.initial,maxLength:1,onChange:e=>s({...o,initial:e.target.value.toUpperCase()}),placeholder:`B`,className:`w-20 font-mono`}),(0,U.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`按国内常用读法填。多音字自己定:藏獒填 Z,柴犬填 C。`})]}),(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`排序(同首字母内,小的在前)`}),(0,U.jsx)(G,{type:`number`,value:o.sort,onChange:e=>s({...o,sort:Number(e.target.value)||0}),className:`w-28`})]}),(0,U.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,U.jsx)(`input`,{id:`bd-enabled`,type:`checkbox`,checked:o.enabled,onChange:e=>s({...o,enabled:e.target.checked})}),(0,U.jsx)(K,{htmlFor:`bd-enabled`,className:`cursor-pointer`,children:`启用(停用后建档时选不到,已填这个品种的档案不受影响)`})]}),c&&(0,U.jsx)(`p`,{className:`text-sm text-destructive`,children:c}),(0,U.jsx)(W,{onClick:p,children:`保存`})]})]})})]})}function Jf(){let[e,t]=(0,S.useState)({enabled:!0,daily_count:3,start_hour:9,end_hour:21}),[n,r]=(0,S.useState)(!0),[i,a]=(0,S.useState)(!1),[o,s]=(0,S.useState)(5),[c,l]=(0,S.useState)(!1),[u,d]=(0,S.useState)(``),[f,p]=(0,S.useState)({enabled:!0,daily_chat:20,daily_symptom:10,daily_plan:5}),[m,h]=(0,S.useState)(!1),[g,_]=(0,S.useState)(``);(0,S.useEffect)(()=>{z.communityBot().then(e=>{t(e),r(!1)}),z.aiQuota().then(p).catch(()=>{})},[]);let v=e=>t=>{let n=Number(t.target.value);(Number.isNaN(n)||n<0)&&(n=0),p({...f,[e]:Math.min(999,n)})};async function y(){h(!0),_(``);try{p(await z.saveAIQuota(f)),_(`已保存,立即生效`)}catch(e){_(e.message||`保存失败`)}finally{h(!1)}}let b=(n,r,i)=>a=>{let o=Number(a.target.value);Number.isNaN(o)&&(o=r),o=Math.max(r,Math.min(i,o)),t({...e,[n]:o})};async function x(){a(!0),d(``);try{let n=await z.saveCommunityBot(e);t(n),d(`已保存`)}catch(e){d(e?.message||`保存失败`)}finally{a(!1)}}async function C(){l(!0),d(``);try{let{made:e}=await z.genCommunityPosts(o);d(`已生成 ${e} 条并发布到宠友圈`)}catch(e){d(e?.message||`生成失败`)}finally{l(!1)}}return(0,U.jsxs)(`div`,{className:`max-w-2xl`,children:[(0,U.jsxs)(`div`,{className:`mb-4`,children:[(0,U.jsx)(`h1`,{className:`text-2xl font-bold`,children:`社区运营`}),(0,U.jsx)(`p`,{className:`text-sm text-muted-foreground mt-1`,children:`AI 以虚拟宠友账号自动生成养宠动态丰富社区,每条都会带「AI」标签,可在「帖子审核」里删除或隐藏。`})]}),u&&(0,U.jsxs)(`div`,{className:`mb-4 flex items-center gap-2 rounded-md bg-primary/10 px-3 py-2 text-sm text-primary`,children:[(0,U.jsx)(Yo,{className:`h-4 w-4`}),` `,u]}),n?(0,U.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`加载中…`}):(0,U.jsxs)(`div`,{className:`space-y-4`,children:[(0,U.jsx)(pl,{children:(0,U.jsxs)(gl,{className:`pt-5 pb-5 space-y-4`,children:[(0,U.jsxs)(`div`,{className:`flex items-center gap-2 font-medium`,children:[(0,U.jsx)(as,{className:`h-4 w-4 text-primary`}),` 每日自动生成`]}),(0,U.jsxs)(`div`,{className:`grid grid-cols-2 gap-4`,children:[(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`自动生成`}),(0,U.jsxs)(`select`,{className:`flex h-9 w-full rounded-md border border-input bg-card px-3 text-sm`,value:e.enabled?`1`:`0`,onChange:n=>t({...e,enabled:n.target.value===`1`}),children:[(0,U.jsx)(`option`,{value:`1`,children:`开启`}),(0,U.jsx)(`option`,{value:`0`,children:`关闭`})]})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`每天条数`}),(0,U.jsx)(G,{type:`number`,value:e.daily_count,onChange:b(`daily_count`,0,50)})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`投放起始时段(点)`}),(0,U.jsx)(G,{type:`number`,value:e.start_hour,onChange:b(`start_hour`,0,23)})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`投放结束时段(点)`}),(0,U.jsx)(G,{type:`number`,value:e.end_hour,onChange:b(`end_hour`,1,24)})]})]}),(0,U.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`当前设置:`,e.enabled?`开启`:`关闭`,`,每天 `,e.daily_count,` 条, 在 `,e.start_hour,`:00 – `,e.end_hour,`:00 之间随机时间发布。`]}),(0,U.jsx)(`div`,{children:(0,U.jsxs)(W,{onClick:x,disabled:i,children:[(0,U.jsx)(is,{className:`h-4 w-4`}),` `,i?`保存中…`:`保存设置`]})})]})}),(0,U.jsx)(pl,{children:(0,U.jsxs)(gl,{className:`pt-5 pb-5 space-y-4`,children:[(0,U.jsxs)(`div`,{className:`flex items-center gap-2 font-medium`,children:[(0,U.jsx)(cs,{className:`h-4 w-4 text-primary`}),` 立即生成一批`]}),(0,U.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`社区太空时可一次性铺一批。会立刻调用 AI 生成并发布,最多 30 条。`}),(0,U.jsxs)(`div`,{className:`flex items-end gap-3`,children:[(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`条数`}),(0,U.jsx)(G,{type:`number`,className:`w-28`,value:o,onChange:e=>s(Math.max(1,Math.min(30,Number(e.target.value)||1)))})]}),(0,U.jsxs)(W,{variant:`outline`,onClick:C,disabled:c,children:[(0,U.jsx)(cs,{className:`h-4 w-4`}),` `,c?`生成中…`:`立即生成 ${o} 条`]})]})]})})]}),(0,U.jsx)(pl,{className:`mt-4`,children:(0,U.jsxs)(gl,{className:`pt-6 space-y-4`,children:[(0,U.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,U.jsx)(as,{className:`h-4 w-4`}),(0,U.jsx)(`span`,{className:`font-medium`,children:`AI 每日次数上限`})]}),(0,U.jsxs)(`p`,{className:`text-sm text-muted-foreground flex gap-2`,children:[(0,U.jsx)(Yo,{className:`h-4 w-4 shrink-0 mt-0.5`}),(0,U.jsx)(`span`,{children:`按「每个用户 / 每个自然日」计,改完立即生效。填 0 表示该功能不限次。 总开关关掉则全部不限——AI 调用是真金白银,关之前想清楚。`})]}),(0,U.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,U.jsx)(`input`,{id:`q-enabled`,type:`checkbox`,checked:f.enabled,onChange:e=>p({...f,enabled:e.target.checked})}),(0,U.jsx)(K,{htmlFor:`q-enabled`,children:`启用次数限制`})]}),(0,U.jsxs)(`div`,{className:`grid grid-cols-3 gap-4 max-w-lg`,children:[(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`问问 AI`}),(0,U.jsx)(G,{type:`number`,value:f.daily_chat,onChange:v(`daily_chat`)})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`异常评估`}),(0,U.jsx)(G,{type:`number`,value:f.daily_symptom,onChange:v(`daily_symptom`)})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`AI 生成计划`}),(0,U.jsx)(G,{type:`number`,value:f.daily_plan,onChange:v(`daily_plan`)})]})]}),(0,U.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,U.jsxs)(W,{onClick:y,disabled:m,children:[(0,U.jsx)(is,{className:`h-4 w-4`}),` `,m?`保存中…`:`保存额度`]}),g&&(0,U.jsx)(`span`,{className:`text-sm text-muted-foreground`,children:g})]})]})})]})}function Yf(){let{page:e,setPage:t,data:n,totalPages:r,reload:i}=yl(z.feedback);async function a(e){await z.setFeedbackHandled(e.id,!e.handled),i()}return(0,U.jsxs)(`div`,{children:[(0,U.jsxs)(`div`,{className:`mb-6`,children:[(0,U.jsx)(`h1`,{className:`text-2xl font-bold`,children:`意见反馈`}),(0,U.jsx)(`p`,{className:`text-sm text-muted-foreground mt-1`,children:`来自小程序「我的 → 意见反馈」的用户留言。`})]}),(0,U.jsx)(pl,{children:(0,U.jsxs)(gl,{className:`pt-6`,children:[(0,U.jsxs)(bl,{children:[(0,U.jsx)(xl,{children:(0,U.jsxs)(Cl,{children:[(0,U.jsx)(q,{children:`时间`}),(0,U.jsx)(q,{children:`用户`}),(0,U.jsx)(q,{children:`内容`}),(0,U.jsx)(q,{children:`联系方式`}),(0,U.jsx)(q,{children:`状态`}),(0,U.jsx)(q,{className:`text-right`,children:`操作`})]})}),(0,U.jsxs)(Sl,{children:[n?.list?.map(e=>(0,U.jsxs)(Cl,{children:[(0,U.jsx)(J,{className:`whitespace-nowrap text-muted-foreground`,children:String(e.created_at).slice(0,16).replace(`T`,` `)}),(0,U.jsx)(J,{children:e.nickname||`—`}),(0,U.jsx)(J,{className:`max-w-md whitespace-pre-wrap`,children:e.content}),(0,U.jsx)(J,{children:e.contact||`—`}),(0,U.jsx)(J,{children:e.handled?(0,U.jsx)(Tl,{variant:`success`,children:`已处理`}):(0,U.jsx)(Tl,{variant:`muted`,children:`待处理`})}),(0,U.jsx)(J,{className:`text-right`,children:(0,U.jsx)(W,{variant:`outline`,size:`sm`,onClick:()=>a(e),children:e.handled?`标为待处理`:`标为已处理`})})]},e.id)),!n?.list?.length&&(0,U.jsx)(Cl,{children:(0,U.jsx)(J,{colSpan:6,className:`text-center text-muted-foreground py-8`,children:`还没有反馈`})})]})]}),(0,U.jsx)(El,{page:e,totalPages:r,total:n?.total??0,onChange:t})]})})]})}function Xf(){let{page:e,setPage:t,data:n,totalPages:r}=yl(z.memberships);return(0,U.jsxs)(`div`,{children:[(0,U.jsx)(`h1`,{className:`text-2xl font-bold mb-6`,children:`会员管理`}),(0,U.jsx)(pl,{children:(0,U.jsxs)(gl,{className:`pt-6`,children:[(0,U.jsxs)(bl,{children:[(0,U.jsx)(xl,{children:(0,U.jsxs)(Cl,{children:[(0,U.jsx)(q,{children:`ID`}),(0,U.jsx)(q,{children:`用户ID`}),(0,U.jsx)(q,{children:`状态`}),(0,U.jsx)(q,{children:`类型`}),(0,U.jsx)(q,{children:`价格`}),(0,U.jsx)(q,{children:`到期`})]})}),(0,U.jsx)(Sl,{children:n?.list?.map(e=>(0,U.jsxs)(Cl,{children:[(0,U.jsx)(J,{children:e.id}),(0,U.jsx)(J,{children:e.user_id}),(0,U.jsx)(J,{children:e.status===`active`?(0,U.jsx)(Tl,{variant:`success`,children:`生效中`}):(0,U.jsx)(Tl,{variant:`muted`,children:e.status})}),(0,U.jsx)(J,{children:e.plan_type||`—`}),(0,U.jsxs)(J,{children:[`¥`,e.price]}),(0,U.jsx)(J,{children:e.end_date?String(e.end_date).slice(0,10):`—`})]},e.id))})]}),(0,U.jsx)(El,{page:e,totalPages:r,total:n?.total??0,onChange:t})]})})]})}function Zf({children:e}){return wo()?e:(0,U.jsx)(Vt,{to:`/login`,replace:!0})}function Qf(){return(0,U.jsxs)(Gt,{children:[(0,U.jsx)(Ut,{path:`/login`,element:(0,U.jsx)(_l,{})}),(0,U.jsxs)(Ut,{path:`/`,element:(0,U.jsx)(Zf,{children:(0,U.jsx)(ol,{})}),children:[(0,U.jsx)(Ut,{index:!0,element:(0,U.jsx)(vl,{})}),(0,U.jsx)(Ut,{path:`users`,element:(0,U.jsx)(Dl,{})}),(0,U.jsx)(Ut,{path:`pets`,element:(0,U.jsx)(Ol,{})}),(0,U.jsx)(Ut,{path:`posts`,element:(0,U.jsx)(jl,{})}),(0,U.jsx)(Ut,{path:`comments`,element:(0,U.jsx)(Ml,{})}),(0,U.jsx)(Ut,{path:`articles`,element:(0,U.jsx)(Af,{})}),(0,U.jsx)(Ut,{path:`care-templates`,element:(0,U.jsx)(Bf,{})}),(0,U.jsx)(Ut,{path:`record-types`,element:(0,U.jsx)(Wf,{})}),(0,U.jsx)(Ut,{path:`breeds`,element:(0,U.jsx)(qf,{})}),(0,U.jsx)(Ut,{path:`community-bot`,element:(0,U.jsx)(Jf,{})}),(0,U.jsx)(Ut,{path:`feedback`,element:(0,U.jsx)(Yf,{})}),(0,U.jsx)(Ut,{path:`members`,element:(0,U.jsx)(Xf,{})})]}),(0,U.jsx)(Ut,{path:`*`,element:(0,U.jsx)(Vt,{to:`/`,replace:!0})})]})}(0,$n.createRoot)(document.getElementById(`root`)).render((0,U.jsx)(S.StrictMode,{children:(0,U.jsx)(Nn,{basename:`/admin`,children:(0,U.jsx)(Qf,{})})})); \ No newline at end of file +(留空) 只要「时间 + 描述 + 照片」`;function Gf(){let[e,t]=(0,S.useState)([]),[n,r]=(0,S.useState)(!1),[i,a]=(0,S.useState)(Hf),[o,s]=(0,S.useState)(``);function c(){z.recordTypes().then(e=>t(e||[])).catch(()=>t([]))}(0,S.useEffect)(c,[]);function l(){a({...Hf}),s(``),r(!0)}function u(e){a({...e}),s(``),r(!0)}async function d(){s(``);try{await z.saveRecordType(i),r(!1),c()}catch(e){s(e?.message||`保存失败`)}}async function f(e){if(confirm(`删除「${e.label}」?`))try{await z.deleteRecordType(e.id),c()}catch(e){alert(e?.message||`删除失败`)}}let p=e=>t=>a({...i,[e]:t.target.value});function m(e){return e.fields?.length?(0,U.jsx)(`span`,{className:`space-x-2`,children:e.fields.map((e,t)=>(0,U.jsxs)(`span`,{className:`whitespace-nowrap text-xs`,children:[e.label,e.kind===`number`&&`·数值${e.unit||``}`,e.kind===`text`&&`·文本`,e.kind===`options`&&`·单选${e.to_category?`★`:``}`]},t))}):(0,U.jsx)(`span`,{className:`text-muted-foreground`,children:`时间 + 描述 + 照片`})}let h={};return e.forEach(e=>(h[e.group]=h[e.group]||[]).push(e)),(0,U.jsxs)(`div`,{children:[(0,U.jsxs)(`div`,{className:`mb-6 flex items-center justify-between`,children:[(0,U.jsxs)(`div`,{children:[(0,U.jsx)(`h1`,{className:`text-2xl font-bold`,children:`记录事项`}),(0,U.jsx)(`p`,{className:`mt-1 text-sm text-muted-foreground`,children:`小程序「记一笔」的事项和它们的表单字段。★ 标记的单选会落到 category —— 周报的高风险数、账单的分类统计都读这一列。`})]}),(0,U.jsx)(W,{onClick:l,children:`新增事项`})]}),(0,U.jsx)(pl,{children:(0,U.jsx)(gl,{className:`pt-6`,children:(0,U.jsxs)(bl,{children:[(0,U.jsx)(xl,{children:(0,U.jsxs)(Cl,{children:[(0,U.jsx)(q,{className:`w-20`,children:`分组`}),(0,U.jsx)(q,{className:`w-28`,children:`名称`}),(0,U.jsx)(q,{className:`w-28`,children:`code`}),(0,U.jsx)(q,{children:`表单字段`}),(0,U.jsx)(q,{className:`w-16`,children:`排序`}),(0,U.jsx)(q,{className:`w-24`,children:`状态`}),(0,U.jsx)(q,{className:`w-32 text-right`,children:`操作`})]})}),(0,U.jsxs)(Sl,{children:[Uf.map(e=>(h[e.key]||[]).map((t,n)=>(0,U.jsxs)(Cl,{children:[(0,U.jsx)(J,{className:`text-muted-foreground`,children:n===0?e.label:``}),(0,U.jsx)(J,{className:`font-medium`,children:t.label}),(0,U.jsx)(J,{className:`font-mono text-xs text-muted-foreground`,children:t.code}),(0,U.jsx)(J,{children:m(t)}),(0,U.jsx)(J,{className:`text-muted-foreground`,children:t.sort}),(0,U.jsxs)(J,{children:[t.enabled?(0,U.jsx)(Tl,{children:`启用`}):(0,U.jsx)(Tl,{variant:`secondary`,children:`停用`}),t.locked&&(0,U.jsx)(Tl,{variant:`outline`,className:`ml-1`,children:`内置`})]}),(0,U.jsxs)(J,{className:`text-right`,children:[(0,U.jsx)(W,{variant:`ghost`,size:`sm`,onClick:()=>u(t),children:`编辑`}),!t.locked&&(0,U.jsx)(W,{variant:`ghost`,size:`sm`,onClick:()=>f(t),children:`删除`})]})]},t.id))),!e.length&&(0,U.jsx)(Cl,{children:(0,U.jsx)(J,{colSpan:7,className:`py-10 text-center text-muted-foreground`,children:`还没有事项 —— 小程序的记录页会是空的`})})]})]})})}),(0,U.jsx)(Tf,{open:n,onOpenChange:r,children:(0,U.jsxs)(Ef,{className:`max-w-2xl`,children:[(0,U.jsx)(Df,{children:(0,U.jsx)(Of,{children:i.id?`编辑「${i.label}」`:`新增事项`})}),(0,U.jsxs)(`div`,{className:`grid gap-4`,children:[(0,U.jsxs)(`div`,{className:`grid grid-cols-2 gap-4`,children:[(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`名称`}),(0,U.jsx)(G,{value:i.label,onChange:p(`label`),placeholder:`洗澡`})]}),(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`code(落库的 type,建过记录后不能改)`}),(0,U.jsx)(G,{value:i.code,onChange:p(`code`),placeholder:`bath`,className:`font-mono`,disabled:i.locked})]})]}),(0,U.jsxs)(`div`,{className:`grid grid-cols-2 gap-4`,children:[(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`分组`}),(0,U.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:Uf.map(e=>(0,U.jsx)(W,{type:`button`,variant:i.group===e.key?`default`:`outline`,size:`sm`,onClick:()=>a({...i,group:e.key}),children:e.label},e.key))})]}),(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`图标名(pt-icon)`}),(0,U.jsx)(G,{value:i.icon,onChange:p(`icon`),placeholder:`bath`,className:`font-mono`})]})]}),(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`表单字段(一行一个,留空则只有「时间 + 描述 + 照片」)`}),(0,U.jsx)(`textarea`,{className:`min-h-[120px] w-full rounded-md border border-input bg-card px-3 py-2 font-mono text-sm shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring`,value:i.fields_raw||``,onChange:p(`fields_raw`),placeholder:`number:体重:kg`}),(0,U.jsx)(`pre`,{className:`whitespace-pre-wrap rounded bg-muted p-3 text-xs text-muted-foreground`,children:Wf}),(0,U.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`一个事项里最多一个字段能落 category。多出来的那个末尾加 `,(0,U.jsx)(`code`,{children:`:-`}),`。`]})]}),(0,U.jsxs)(`div`,{className:`flex items-center gap-6`,children:[(0,U.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,U.jsx)(K,{children:`排序`}),(0,U.jsx)(G,{type:`number`,value:i.sort,onChange:e=>a({...i,sort:Number(e.target.value)||0}),className:`w-24`})]}),(0,U.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,U.jsx)(`input`,{id:`rt-enabled`,type:`checkbox`,checked:i.enabled,onChange:e=>a({...i,enabled:e.target.checked})}),(0,U.jsx)(K,{htmlFor:`rt-enabled`,className:`cursor-pointer`,children:`启用`})]})]}),i.locked&&(0,U.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`这是内置事项:统计和分析逻辑依赖它的 code,不能删也不能改 code。想隐藏请改成停用。`}),o&&(0,U.jsx)(`p`,{className:`text-sm text-destructive`,children:o}),(0,U.jsx)(W,{onClick:d,children:`保存`})]})]})})]})}var Kf={id:``,species:`cat`,name:``,initial:``,sort:0,enabled:!0},qf=[{key:`cat`,label:`猫`},{key:`dog`,label:`狗`}];function Jf(){let[e,t]=(0,S.useState)(`cat`),[n,r]=(0,S.useState)([]),[i,a]=(0,S.useState)(!1),[o,s]=(0,S.useState)(Kf),[c,l]=(0,S.useState)(``);function u(){z.breeds(e).then(e=>r(e||[])).catch(()=>r([]))}(0,S.useEffect)(u,[e]);function d(){s({...Kf,species:e}),l(``),a(!0)}function f(e){s({...e}),l(``),a(!0)}async function p(){l(``);try{await z.saveBreed(o),a(!1),u()}catch(e){l(e?.message||`保存失败`)}}async function m(e){if(confirm(`删除「${e.name}」?`))try{await z.deleteBreed(e.id),u()}catch(e){alert(e?.message||`删除失败`)}}let h=e=>t=>s({...o,[e]:t.target.value}),g={};n.forEach(e=>{let t=(e.initial||`#`).toUpperCase();(g[t]=g[t]||[]).push(e)});let _=Object.keys(g).sort();return(0,U.jsxs)(`div`,{children:[(0,U.jsxs)(`div`,{className:`mb-6 flex items-center justify-between`,children:[(0,U.jsxs)(`div`,{children:[(0,U.jsx)(`h1`,{className:`text-2xl font-bold`,children:`品种管理`}),(0,U.jsx)(`p`,{className:`mt-1 text-sm text-muted-foreground`,children:`建档第二步的品种选择器读这里。首字母要手填 —— 多音字(藏獒、柴犬)自动转拼音常出错。`})]}),(0,U.jsx)(W,{onClick:d,children:`新增品种`})]}),(0,U.jsxs)(`div`,{className:`mb-4 flex gap-2`,children:[qf.map(n=>(0,U.jsx)(W,{variant:e===n.key?`default`:`outline`,size:`sm`,onClick:()=>t(n.key),children:n.label},n.key)),(0,U.jsxs)(`span`,{className:`ml-2 self-center text-sm text-muted-foreground`,children:[`共 `,n.length,` 种,`,_.length,` 个首字母`]})]}),(0,U.jsx)(pl,{children:(0,U.jsx)(gl,{className:`pt-6`,children:(0,U.jsxs)(bl,{children:[(0,U.jsx)(xl,{children:(0,U.jsxs)(Cl,{children:[(0,U.jsx)(q,{className:`w-16`,children:`首字母`}),(0,U.jsx)(q,{children:`品种`}),(0,U.jsx)(q,{className:`w-20`,children:`排序`}),(0,U.jsx)(q,{className:`w-20`,children:`状态`}),(0,U.jsx)(q,{className:`w-32 text-right`,children:`操作`})]})}),(0,U.jsxs)(Sl,{children:[_.map(e=>g[e].map((t,n)=>(0,U.jsxs)(Cl,{children:[(0,U.jsx)(J,{className:`font-mono text-muted-foreground`,children:n===0?e:``}),(0,U.jsx)(J,{className:`font-medium`,children:t.name}),(0,U.jsx)(J,{className:`text-muted-foreground`,children:t.sort}),(0,U.jsx)(J,{children:t.enabled?(0,U.jsx)(Tl,{children:`启用`}):(0,U.jsx)(Tl,{variant:`secondary`,children:`停用`})}),(0,U.jsxs)(J,{className:`text-right`,children:[(0,U.jsx)(W,{variant:`ghost`,size:`sm`,onClick:()=>f(t),children:`编辑`}),(0,U.jsx)(W,{variant:`ghost`,size:`sm`,onClick:()=>m(t),children:`删除`})]})]},t.id))),!n.length&&(0,U.jsx)(Cl,{children:(0,U.jsx)(J,{colSpan:5,className:`py-10 text-center text-muted-foreground`,children:`还没有品种`})})]})]})})}),(0,U.jsx)(Tf,{open:i,onOpenChange:a,children:(0,U.jsxs)(Ef,{children:[(0,U.jsx)(Df,{children:(0,U.jsx)(Of,{children:o.id?`编辑品种`:`新增品种`})}),(0,U.jsxs)(`div`,{className:`grid gap-4`,children:[(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`物种`}),(0,U.jsx)(`div`,{className:`flex gap-2`,children:qf.map(e=>(0,U.jsx)(W,{type:`button`,variant:o.species===e.key?`default`:`outline`,size:`sm`,onClick:()=>s({...o,species:e.key}),children:e.label},e.key))})]}),(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`品种名`}),(0,U.jsx)(G,{value:o.name,onChange:h(`name`),placeholder:`例如:布偶猫`})]}),(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`首字母(A-Z,一位)`}),(0,U.jsx)(G,{value:o.initial,maxLength:1,onChange:e=>s({...o,initial:e.target.value.toUpperCase()}),placeholder:`B`,className:`w-20 font-mono`}),(0,U.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`按国内常用读法填。多音字自己定:藏獒填 Z,柴犬填 C。`})]}),(0,U.jsxs)(`div`,{className:`grid gap-2`,children:[(0,U.jsx)(K,{children:`排序(同首字母内,小的在前)`}),(0,U.jsx)(G,{type:`number`,value:o.sort,onChange:e=>s({...o,sort:Number(e.target.value)||0}),className:`w-28`})]}),(0,U.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,U.jsx)(`input`,{id:`bd-enabled`,type:`checkbox`,checked:o.enabled,onChange:e=>s({...o,enabled:e.target.checked})}),(0,U.jsx)(K,{htmlFor:`bd-enabled`,className:`cursor-pointer`,children:`启用(停用后建档时选不到,已填这个品种的档案不受影响)`})]}),c&&(0,U.jsx)(`p`,{className:`text-sm text-destructive`,children:c}),(0,U.jsx)(W,{onClick:p,children:`保存`})]})]})})]})}function Yf(){let[e,t]=(0,S.useState)({enabled:!0,daily_count:3,start_hour:9,end_hour:21}),[n,r]=(0,S.useState)(!0),[i,a]=(0,S.useState)(!1),[o,s]=(0,S.useState)(5),[c,l]=(0,S.useState)(!1),[u,d]=(0,S.useState)(``),[f,p]=(0,S.useState)({enabled:!0,daily_chat:20,daily_symptom:10,daily_plan:5}),[m,h]=(0,S.useState)(!1),[g,_]=(0,S.useState)(``);(0,S.useEffect)(()=>{z.communityBot().then(e=>{t(e),r(!1)}),z.aiQuota().then(p).catch(()=>{})},[]);let v=e=>t=>{let n=Number(t.target.value);(Number.isNaN(n)||n<0)&&(n=0),p({...f,[e]:Math.min(999,n)})};async function y(){h(!0),_(``);try{p(await z.saveAIQuota(f)),_(`已保存,立即生效`)}catch(e){_(e.message||`保存失败`)}finally{h(!1)}}let b=(n,r,i)=>a=>{let o=Number(a.target.value);Number.isNaN(o)&&(o=r),o=Math.max(r,Math.min(i,o)),t({...e,[n]:o})};async function x(){a(!0),d(``);try{let n=await z.saveCommunityBot(e);t(n),d(`已保存`)}catch(e){d(e?.message||`保存失败`)}finally{a(!1)}}async function C(){l(!0),d(``);try{let{made:e}=await z.genCommunityPosts(o);d(`已生成 ${e} 条并发布到宠友圈`)}catch(e){d(e?.message||`生成失败`)}finally{l(!1)}}return(0,U.jsxs)(`div`,{className:`max-w-2xl`,children:[(0,U.jsxs)(`div`,{className:`mb-4`,children:[(0,U.jsx)(`h1`,{className:`text-2xl font-bold`,children:`社区运营`}),(0,U.jsx)(`p`,{className:`text-sm text-muted-foreground mt-1`,children:`AI 以虚拟宠友账号自动生成养宠动态丰富社区,每条都会带「AI」标签,可在「帖子审核」里删除或隐藏。`})]}),u&&(0,U.jsxs)(`div`,{className:`mb-4 flex items-center gap-2 rounded-md bg-primary/10 px-3 py-2 text-sm text-primary`,children:[(0,U.jsx)(Yo,{className:`h-4 w-4`}),` `,u]}),n?(0,U.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`加载中…`}):(0,U.jsxs)(`div`,{className:`space-y-4`,children:[(0,U.jsx)(pl,{children:(0,U.jsxs)(gl,{className:`pt-5 pb-5 space-y-4`,children:[(0,U.jsxs)(`div`,{className:`flex items-center gap-2 font-medium`,children:[(0,U.jsx)(as,{className:`h-4 w-4 text-primary`}),` 每日自动生成`]}),(0,U.jsxs)(`div`,{className:`grid grid-cols-2 gap-4`,children:[(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`自动生成`}),(0,U.jsxs)(`select`,{className:`flex h-9 w-full rounded-md border border-input bg-card px-3 text-sm`,value:e.enabled?`1`:`0`,onChange:n=>t({...e,enabled:n.target.value===`1`}),children:[(0,U.jsx)(`option`,{value:`1`,children:`开启`}),(0,U.jsx)(`option`,{value:`0`,children:`关闭`})]})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`每天条数`}),(0,U.jsx)(G,{type:`number`,value:e.daily_count,onChange:b(`daily_count`,0,50)})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`投放起始时段(点)`}),(0,U.jsx)(G,{type:`number`,value:e.start_hour,onChange:b(`start_hour`,0,23)})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`投放结束时段(点)`}),(0,U.jsx)(G,{type:`number`,value:e.end_hour,onChange:b(`end_hour`,1,24)})]})]}),(0,U.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`当前设置:`,e.enabled?`开启`:`关闭`,`,每天 `,e.daily_count,` 条, 在 `,e.start_hour,`:00 – `,e.end_hour,`:00 之间随机时间发布。`]}),(0,U.jsx)(`div`,{children:(0,U.jsxs)(W,{onClick:x,disabled:i,children:[(0,U.jsx)(is,{className:`h-4 w-4`}),` `,i?`保存中…`:`保存设置`]})})]})}),(0,U.jsx)(pl,{children:(0,U.jsxs)(gl,{className:`pt-5 pb-5 space-y-4`,children:[(0,U.jsxs)(`div`,{className:`flex items-center gap-2 font-medium`,children:[(0,U.jsx)(cs,{className:`h-4 w-4 text-primary`}),` 立即生成一批`]}),(0,U.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`社区太空时可一次性铺一批。会立刻调用 AI 生成并发布,最多 30 条。`}),(0,U.jsxs)(`div`,{className:`flex items-end gap-3`,children:[(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`条数`}),(0,U.jsx)(G,{type:`number`,className:`w-28`,value:o,onChange:e=>s(Math.max(1,Math.min(30,Number(e.target.value)||1)))})]}),(0,U.jsxs)(W,{variant:`outline`,onClick:C,disabled:c,children:[(0,U.jsx)(cs,{className:`h-4 w-4`}),` `,c?`生成中…`:`立即生成 ${o} 条`]})]})]})})]}),(0,U.jsx)(pl,{className:`mt-4`,children:(0,U.jsxs)(gl,{className:`pt-6 space-y-4`,children:[(0,U.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,U.jsx)(as,{className:`h-4 w-4`}),(0,U.jsx)(`span`,{className:`font-medium`,children:`AI 每日次数上限`})]}),(0,U.jsxs)(`p`,{className:`text-sm text-muted-foreground flex gap-2`,children:[(0,U.jsx)(Yo,{className:`h-4 w-4 shrink-0 mt-0.5`}),(0,U.jsx)(`span`,{children:`按「每个用户 / 每个自然日」计,改完立即生效。填 0 表示该功能不限次。 总开关关掉则全部不限——AI 调用是真金白银,关之前想清楚。`})]}),(0,U.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,U.jsx)(`input`,{id:`q-enabled`,type:`checkbox`,checked:f.enabled,onChange:e=>p({...f,enabled:e.target.checked})}),(0,U.jsx)(K,{htmlFor:`q-enabled`,children:`启用次数限制`})]}),(0,U.jsxs)(`div`,{className:`grid grid-cols-3 gap-4 max-w-lg`,children:[(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`问问 AI`}),(0,U.jsx)(G,{type:`number`,value:f.daily_chat,onChange:v(`daily_chat`)})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`异常评估`}),(0,U.jsx)(G,{type:`number`,value:f.daily_symptom,onChange:v(`daily_symptom`)})]}),(0,U.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,U.jsx)(K,{children:`AI 生成计划`}),(0,U.jsx)(G,{type:`number`,value:f.daily_plan,onChange:v(`daily_plan`)})]})]}),(0,U.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,U.jsxs)(W,{onClick:y,disabled:m,children:[(0,U.jsx)(is,{className:`h-4 w-4`}),` `,m?`保存中…`:`保存额度`]}),g&&(0,U.jsx)(`span`,{className:`text-sm text-muted-foreground`,children:g})]})]})})]})}function Xf(){let{page:e,setPage:t,data:n,totalPages:r,reload:i}=yl(z.feedback);async function a(e){await z.setFeedbackHandled(e.id,!e.handled),i()}return(0,U.jsxs)(`div`,{children:[(0,U.jsxs)(`div`,{className:`mb-6`,children:[(0,U.jsx)(`h1`,{className:`text-2xl font-bold`,children:`意见反馈`}),(0,U.jsx)(`p`,{className:`text-sm text-muted-foreground mt-1`,children:`来自小程序「我的 → 意见反馈」的用户留言。`})]}),(0,U.jsx)(pl,{children:(0,U.jsxs)(gl,{className:`pt-6`,children:[(0,U.jsxs)(bl,{children:[(0,U.jsx)(xl,{children:(0,U.jsxs)(Cl,{children:[(0,U.jsx)(q,{children:`时间`}),(0,U.jsx)(q,{children:`用户`}),(0,U.jsx)(q,{children:`内容`}),(0,U.jsx)(q,{children:`联系方式`}),(0,U.jsx)(q,{children:`状态`}),(0,U.jsx)(q,{className:`text-right`,children:`操作`})]})}),(0,U.jsxs)(Sl,{children:[n?.list?.map(e=>(0,U.jsxs)(Cl,{children:[(0,U.jsx)(J,{className:`whitespace-nowrap text-muted-foreground`,children:String(e.created_at).slice(0,16).replace(`T`,` `)}),(0,U.jsx)(J,{children:e.nickname||`—`}),(0,U.jsx)(J,{className:`max-w-md whitespace-pre-wrap`,children:e.content}),(0,U.jsx)(J,{children:e.contact||`—`}),(0,U.jsx)(J,{children:e.handled?(0,U.jsx)(Tl,{variant:`success`,children:`已处理`}):(0,U.jsx)(Tl,{variant:`muted`,children:`待处理`})}),(0,U.jsx)(J,{className:`text-right`,children:(0,U.jsx)(W,{variant:`outline`,size:`sm`,onClick:()=>a(e),children:e.handled?`标为待处理`:`标为已处理`})})]},e.id)),!n?.list?.length&&(0,U.jsx)(Cl,{children:(0,U.jsx)(J,{colSpan:6,className:`text-center text-muted-foreground py-8`,children:`还没有反馈`})})]})]}),(0,U.jsx)(El,{page:e,totalPages:r,total:n?.total??0,onChange:t})]})})]})}function Zf(){let{page:e,setPage:t,data:n,totalPages:r}=yl(z.memberships);return(0,U.jsxs)(`div`,{children:[(0,U.jsx)(`h1`,{className:`text-2xl font-bold mb-6`,children:`会员管理`}),(0,U.jsx)(pl,{children:(0,U.jsxs)(gl,{className:`pt-6`,children:[(0,U.jsxs)(bl,{children:[(0,U.jsx)(xl,{children:(0,U.jsxs)(Cl,{children:[(0,U.jsx)(q,{children:`ID`}),(0,U.jsx)(q,{children:`用户ID`}),(0,U.jsx)(q,{children:`状态`}),(0,U.jsx)(q,{children:`类型`}),(0,U.jsx)(q,{children:`价格`}),(0,U.jsx)(q,{children:`到期`})]})}),(0,U.jsx)(Sl,{children:n?.list?.map(e=>(0,U.jsxs)(Cl,{children:[(0,U.jsx)(J,{children:e.id}),(0,U.jsx)(J,{children:e.user_id}),(0,U.jsx)(J,{children:e.status===`active`?(0,U.jsx)(Tl,{variant:`success`,children:`生效中`}):(0,U.jsx)(Tl,{variant:`muted`,children:e.status})}),(0,U.jsx)(J,{children:e.plan_type||`—`}),(0,U.jsxs)(J,{children:[`¥`,e.price]}),(0,U.jsx)(J,{children:e.end_date?String(e.end_date).slice(0,10):`—`})]},e.id))})]}),(0,U.jsx)(El,{page:e,totalPages:r,total:n?.total??0,onChange:t})]})})]})}function Qf({children:e}){return wo()?e:(0,U.jsx)(Vt,{to:`/login`,replace:!0})}function $f(){return(0,U.jsxs)(Gt,{children:[(0,U.jsx)(Ut,{path:`/login`,element:(0,U.jsx)(_l,{})}),(0,U.jsxs)(Ut,{path:`/`,element:(0,U.jsx)(Qf,{children:(0,U.jsx)(ol,{})}),children:[(0,U.jsx)(Ut,{index:!0,element:(0,U.jsx)(vl,{})}),(0,U.jsx)(Ut,{path:`users`,element:(0,U.jsx)(Dl,{})}),(0,U.jsx)(Ut,{path:`pets`,element:(0,U.jsx)(Ol,{})}),(0,U.jsx)(Ut,{path:`posts`,element:(0,U.jsx)(jl,{})}),(0,U.jsx)(Ut,{path:`comments`,element:(0,U.jsx)(Ml,{})}),(0,U.jsx)(Ut,{path:`articles`,element:(0,U.jsx)(Af,{})}),(0,U.jsx)(Ut,{path:`care-templates`,element:(0,U.jsx)(Vf,{})}),(0,U.jsx)(Ut,{path:`record-types`,element:(0,U.jsx)(Gf,{})}),(0,U.jsx)(Ut,{path:`breeds`,element:(0,U.jsx)(Jf,{})}),(0,U.jsx)(Ut,{path:`community-bot`,element:(0,U.jsx)(Yf,{})}),(0,U.jsx)(Ut,{path:`feedback`,element:(0,U.jsx)(Xf,{})}),(0,U.jsx)(Ut,{path:`members`,element:(0,U.jsx)(Zf,{})})]}),(0,U.jsx)(Ut,{path:`*`,element:(0,U.jsx)(Vt,{to:`/`,replace:!0})})]})}(0,$n.createRoot)(document.getElementById(`root`)).render((0,U.jsx)(S.StrictMode,{children:(0,U.jsx)(Nn,{basename:`/admin`,children:(0,U.jsx)($f,{})})})); \ No newline at end of file diff --git a/pets-be/internal/admin/dist/index.html b/pets-be/internal/admin/dist/index.html index 30b5db0..75eaab5 100644 --- a/pets-be/internal/admin/dist/index.html +++ b/pets-be/internal/admin/dist/index.html @@ -5,7 +5,7 @@ admin - + diff --git a/pets-be/web/admin/src/pages/CareTemplates.tsx b/pets-be/web/admin/src/pages/CareTemplates.tsx index ce0cc20..91ea8e4 100644 --- a/pets-be/web/admin/src/pages/CareTemplates.tsx +++ b/pets-be/web/admin/src/pages/CareTemplates.tsx @@ -26,6 +26,10 @@ const REPEATS = [ { key: 'once', label: '一次性' }, ] const WEEKDAYS = ['一', '二', '三', '四', '五', '六', '日'] +// 阶段的展示顺序。后端 CareStages 就是这个顺序,但列表里要用它排序, +// 单独列一份免得依赖接口返回的时序 +const STAGE_ORDER = ['刚到家 0-30 天', '幼年期', '青年期', '成年期', '中年期', '老年期'] + const selectCls = 'h-9 rounded-md border border-input bg-card px-2 text-sm shrink-0' type Item = { @@ -78,6 +82,7 @@ function blank(kind: Item['kind']): Item { export default function CareTemplates() { const [list, setList] = useState([]) + const [tab, setTab] = useState('cat') const [types, setTypes] = useState([]) const [stages, setStages] = useState([]) const [open, setOpen] = useState(false) @@ -106,7 +111,8 @@ export default function CareTemplates() { }, []) function create() { - setTpl({ id: '', species: 'cat', stage: '成年期', name: '', summary: '', sort: 0, enabled: true }) + // 默认跟当前 tab 的物种,省一步点击 + setTpl({ id: '', species: tab, stage: '成年期', name: '', summary: '', sort: 0, enabled: true }) setItems([]) setErr('') setOpen(true) @@ -159,6 +165,13 @@ export default function CareTemplates() { upd(it._k, 'weekdays', next.join(',')) } + // 按 tab 过滤,并按阶段顺序排(数据库按 sort 排,但 sort 是全局的, + // 分物种看时会跳号) + const order = STAGE_ORDER + const shown = list + .filter((t) => t.species === tab) + .sort((a, b) => order.indexOf(a.stage) - order.indexOf(b.stage)) + const plans = items.filter((i) => i.kind === 'plan') const reminders = items.filter((i) => i.kind === 'reminder') @@ -191,12 +204,30 @@ export default function CareTemplates() { + {/* 猫狗分开看。混在一起 10 套要上下找,而且阶段名一样(幼年期/青年期…), + 扫一眼分不清哪套是猫的 */} +
+ {SPECIES.map((s) => { + const n = list.filter((t) => t.species === s.key).length + return ( + + ) + })} +
+ - 物种/阶段 + 阶段 方案名 内容 状态 @@ -204,13 +235,11 @@ export default function CareTemplates() { - {list.map((t) => { + {shown.map((t) => { const c = spread(t) return ( - - {t.species === 'dog' ? '狗' : '猫'} · {t.stage} - + {t.stage}
{t.name || '(未命名)'}
{t.summary}
@@ -232,10 +261,10 @@ export default function CareTemplates() {
) })} - {!list.length && ( + {!shown.length && ( - 还没有方案 —— 用户建档后计划页会是空的,只能自己排 + 这个物种还没有方案 —— 用户建档后计划页会是空的,只能自己排 )}