This commit is contained in:
sion
2026-04-05 19:43:31 +08:00
parent 5b9a80e3fe
commit 2fbc47117c
94 changed files with 1032 additions and 882 deletions

View File

@@ -1 +0,0 @@
import{I as e,v as t,x as n,xt as r,yt as i,z as a}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{J as o}from"./index-BpHHjIYv.js";import{r as s}from"./button-BTKRNUhQ.js";var c=n({__name:`AlertDescription`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(n){let s=n;return(n,c)=>(e(),t(`div`,{"data-slot":`alert-description`,class:r(i(o)(`text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed`,s.class))},[a(n.$slots,`default`)],2))}}),l=n({__name:`AlertTitle`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(n){let s=n;return(n,c)=>(e(),t(`div`,{"data-slot":`alert-title`,class:r(i(o)(`col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight`,s.class))},[a(n.$slots,`default`)],2))}}),u=s(`relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current`,{variants:{variant:{default:`bg-card text-card-foreground`,destructive:`text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90`}},defaultVariants:{variant:`default`}}),d=n({__name:`Alert`,props:{class:{type:[Boolean,null,String,Object,Array]},variant:{}},setup(n){let s=n;return(c,l)=>(e(),t(`div`,{"data-slot":`alert`,class:r(i(o)(i(u)({variant:n.variant}),s.class)),role:`alert`},[a(c.$slots,`default`)],2))}});export{l as n,c as r,d as t};

View File

@@ -1 +0,0 @@
import{A as e,I as t,Q as n,Y as r,_ as i,g as a,ut as o,x as s,yt as c,z as l}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{b as u,v as d}from"./dist-3yfE1dPa.js";import{J as f}from"./index-BpHHjIYv.js";import{i as p}from"./button-BTKRNUhQ.js";import{t as m}from"./useForwardExpose-CNhbE6SX.js";import{r as h}from"./AvatarImage-Ct5I9mHM.js";var g=s({__name:`AvatarFallback`,props:{delayMs:{type:Number,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`span`}},setup(e){let s=e,u=h();m();let f=o(s.delayMs===void 0);return r(e=>{if(s.delayMs&&d){let t=window.setTimeout(()=>{f.value=!0},s.delayMs);e(()=>{window.clearTimeout(t)})}}),(e,r)=>f.value&&c(u).imageLoadingStatus.value!==`loaded`?(t(),a(c(p),{key:0,"as-child":e.asChild,as:e.as},{default:n(()=>[l(e.$slots,`default`)]),_:3},8,[`as-child`,`as`])):i(`v-if`,!0)}}),_=s({__name:`AvatarFallback`,props:{delayMs:{},asChild:{type:Boolean},as:{},class:{type:[Boolean,null,String,Object,Array]}},setup(r){let i=r,o=u(i,`class`);return(r,s)=>(t(),a(c(g),e({"data-slot":`avatar-fallback`},c(o),{class:c(f)(`bg-muted flex size-full items-center justify-center rounded-full`,i.class)}),{default:n(()=>[l(r.$slots,`default`)]),_:3},16,[`class`]))}});export{_ as t};

View File

@@ -1 +0,0 @@
import{$ as e,A as t,I as n,J as r,N as i,P as a,Q as o,Y as s,a as c,g as l,gt as u,m as d,ut as f,x as p,xt as m,yt as h,z as g}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{v as _}from"./dist-3yfE1dPa.js";import{J as v}from"./index-BpHHjIYv.js";import{O as y}from"./Teleport-qOjHMYM8.js";import{i as b}from"./button-BTKRNUhQ.js";import{t as x}from"./useForwardExpose-CNhbE6SX.js";var[S,C]=y(`AvatarRoot`),w=p({__name:`AvatarRoot`,props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`span`}},setup(e){return x(),C({imageLoadingStatus:f(`idle`)}),(e,t)=>(n(),l(h(b),{"as-child":e.asChild,as:e.as},{default:o(()=>[g(e.$slots,`default`)]),_:3},8,[`as-child`,`as`]))}});function T(e,t){return e?t?(e.src!==t&&(e.src=t),e.complete&&e.naturalWidth>0?`loaded`:`loading`):`error`:`idle`}function E(e,{referrerPolicy:t,crossOrigin:n}={}){let r=f(!1),o=f(null),c=d(()=>r.value?(!o.value&&_&&(o.value=new window.Image),o.value):null),l=f(T(c.value,e.value)),u=e=>()=>{r.value&&(l.value=e)};return i(()=>{r.value=!0,s(r=>{let i=c.value;if(!i)return;l.value=T(i,e.value);let a=u(`loaded`),o=u(`error`);i.addEventListener(`load`,a),i.addEventListener(`error`,o),t?.value&&(i.referrerPolicy=t.value),typeof n?.value==`string`&&(i.crossOrigin=n.value),r(()=>{i.removeEventListener(`load`,a),i.removeEventListener(`error`,o)})})}),a(()=>{r.value=!1}),l}var D=p({__name:`AvatarImage`,props:{src:{type:String,required:!0},referrerPolicy:{type:null,required:!1},crossOrigin:{type:null,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`img`}},emits:[`loadingStatusChange`],setup(t,{emit:i}){let a=t,s=i,{src:d,referrerPolicy:f,crossOrigin:p}=u(a);x();let m=S(),_=E(d,{referrerPolicy:f,crossOrigin:p});return r(_,e=>{s(`loadingStatusChange`,e),e!==`idle`&&(m.imageLoadingStatus.value=e)},{immediate:!0}),(t,r)=>e((n(),l(h(b),{role:`img`,"as-child":t.asChild,as:t.as,src:h(d),referrerpolicy:h(f),crossorigin:h(p)},{default:o(()=>[g(t.$slots,`default`)]),_:3},8,[`as-child`,`as`,`src`,`referrerpolicy`,`crossorigin`])),[[c,h(_)===`loaded`]])}}),O=p({__name:`Avatar`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(e){let t=e;return(e,r)=>(n(),l(h(w),{"data-slot":`avatar`,class:m(h(v)(`relative flex size-8 shrink-0 overflow-hidden rounded-full`,t.class))},{default:o(()=>[g(e.$slots,`default`)]),_:3},8,[`class`]))}}),k=p({__name:`AvatarImage`,props:{src:{},referrerPolicy:{},crossOrigin:{},asChild:{type:Boolean},as:{}},setup(e){let r=e;return(e,i)=>(n(),l(h(D),t({"data-slot":`avatar-image`},r,{class:`aspect-square size-full`}),{default:o(()=>[g(e.$slots,`default`)]),_:3},16))}});export{O as n,S as r,k as t};

View File

@@ -1 +0,0 @@
import{A as e,I as t,Q as n,g as r,x as i,yt as a,z as o}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{b as s}from"./dist-3yfE1dPa.js";import{J as c}from"./index-BpHHjIYv.js";import{i as l,r as u}from"./button-BTKRNUhQ.js";var d=u(`inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden`,{variants:{variant:{default:`border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90`,secondary:`border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90`,destructive:`border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60`,outline:`text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground`}},defaultVariants:{variant:`default`}}),f=i({__name:`Badge`,props:{asChild:{type:Boolean},as:{},variant:{},class:{type:[Boolean,null,String,Object,Array]}},setup(i){let u=i,f=s(u,`class`);return(s,p)=>(t(),r(a(l),e({"data-slot":`badge`,class:a(c)(a(d)({variant:i.variant}),u.class)},a(f)),{default:n(()=>[o(s.$slots,`default`)]),_:3},16,[`class`]))}});export{f as t};

View File

@@ -1 +0,0 @@
import{I as e,v as t,x as n,xt as r,yt as i,z as a}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{J as o}from"./index-BpHHjIYv.js";var s=n({__name:`Card`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(n){let s=n;return(n,c)=>(e(),t(`div`,{"data-slot":`card`,class:r(i(o)(`bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm`,s.class))},[a(n.$slots,`default`)],2))}});export{s as t};

View File

@@ -1 +0,0 @@
import{I as e,v as t,x as n,xt as r,yt as i,z as a}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{J as o}from"./index-BpHHjIYv.js";var s=n({__name:`CardContent`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(n){let s=n;return(n,c)=>(e(),t(`div`,{"data-slot":`card-content`,class:r(i(o)(`px-6`,s.class))},[a(n.$slots,`default`)],2))}});export{s as t};

View File

@@ -1 +0,0 @@
import{I as e,v as t,x as n,xt as r,yt as i,z as a}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{J as o}from"./index-BpHHjIYv.js";var s=n({__name:`CardHeader`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(n){let s=n;return(n,c)=>(e(),t(`div`,{"data-slot":`card-header`,class:r(i(o)(`@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6`,s.class))},[a(n.$slots,`default`)],2))}}),c=n({__name:`CardDescription`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(n){let s=n;return(n,c)=>(e(),t(`p`,{"data-slot":`card-description`,class:r(i(o)(`text-muted-foreground text-sm`,s.class))},[a(n.$slots,`default`)],2))}}),l=n({__name:`CardTitle`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(n){let s=n;return(n,c)=>(e(),t(`h3`,{"data-slot":`card-title`,class:r(i(o)(`leading-none font-semibold`,s.class))},[a(n.$slots,`default`)],2))}});export{c as n,s as r,l as t};

View File

@@ -1 +0,0 @@
import{A as e,C as t,I as n,Q as r,St as i,V as a,_ as o,b as s,g as c,m as l,o as u,s as d,x as f,yt as p,z as m}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{b as h,p as g}from"./dist-3yfE1dPa.js";import{o as _}from"./SelectValue-By3tfEiu.js";import{J as v}from"./index-BpHHjIYv.js";import{n as y,r as b}from"./VisuallyHidden-_sQ0xQ9O.js";import{O as x,T as S,g as C,y as w}from"./Teleport-qOjHMYM8.js";import{i as T}from"./button-BTKRNUhQ.js";import{t as E}from"./useForwardExpose-CNhbE6SX.js";import{t as D}from"./VisuallyHiddenInput-CE3zkTxY.js";import{t as O}from"./RovingFocusItem-BInhij-V.js";function k(e,t){return S(e)?!1:Array.isArray(e)?e.some(e=>b(e,t)):b(e,t)}var[A,j]=x(`CheckboxGroupRoot`);function M(e){return e===`indeterminate`}function N(e){return M(e)?`indeterminate`:e?`checked`:`unchecked`}var[P,F]=x(`CheckboxRoot`),I=f({inheritAttrs:!1,__name:`CheckboxRoot`,props:{defaultValue:{type:null,required:!1},modelValue:{type:null,required:!1,default:void 0},disabled:{type:Boolean,required:!1},value:{type:null,required:!1,default:`on`},id:{type:String,required:!1},trueValue:{type:null,required:!1,default:()=>!0},falseValue:{type:null,required:!1,default:()=>!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`button`},name:{type:String,required:!1},required:{type:Boolean,required:!1}},emits:[`update:modelValue`],setup(t,{emit:i}){let s=t,f=i,{forwardRef:h,currentElement:_}=E(),v=A(null),x=g(s,`modelValue`,f,{defaultValue:s.defaultValue??s.falseValue,passive:s.modelValue===void 0}),C=l(()=>v?.disabled.value||s.disabled),w=l(()=>b(x.value,s.trueValue)),j=l(()=>S(v?.modelValue.value)?x.value===`indeterminate`?`indeterminate`:w.value:k(v.modelValue.value,s.value));function P(){if(S(v?.modelValue.value))x.value===`indeterminate`?x.value=s.trueValue:x.value=w.value?s.falseValue:s.trueValue;else{let e=[...v.modelValue.value||[]];if(k(e,s.value)){let t=e.findIndex(e=>b(e,s.value));e.splice(t,1)}else e.push(s.value);v.modelValue.value=e}}let I=y(_),L=l(()=>s.id&&_.value?document.querySelector(`[for="${s.id}"]`)?.innerText:void 0);return F({disabled:C,state:j}),(t,i)=>(n(),c(a(p(v)?.rovingFocus.value?p(O):p(T)),e(t.$attrs,{id:t.id,ref:p(h),role:`checkbox`,"as-child":t.asChild,as:t.as,type:t.as===`button`?`button`:void 0,"aria-checked":p(M)(j.value)?`mixed`:j.value,"aria-required":t.required,"aria-label":t.$attrs[`aria-label`]||L.value,"data-state":p(N)(j.value),"data-disabled":C.value?``:void 0,disabled:C.value,focusable:p(v)?.rovingFocus.value?!C.value:void 0,onKeydown:u(d(()=>{},[`prevent`]),[`enter`]),onClick:P}),{default:r(()=>[m(t.$slots,`default`,{modelValue:p(x),state:j.value}),p(I)&&t.name&&!p(v)?(n(),c(p(D),{key:0,type:`checkbox`,checked:!!j.value,name:t.name,value:t.value,disabled:C.value,required:t.required},null,8,[`checked`,`name`,`value`,`disabled`,`required`])):o(`v-if`,!0)]),_:3},16,[`id`,`as-child`,`as`,`type`,`aria-checked`,`aria-required`,`aria-label`,`data-state`,`data-disabled`,`disabled`,`focusable`,`onKeydown`]))}}),L=f({__name:`CheckboxIndicator`,props:{forceMount:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`span`}},setup(t){let{forwardRef:i}=E(),a=P();return(t,o)=>(n(),c(p(C),{present:t.forceMount||p(M)(p(a).state.value)||p(a).state.value===!0},{default:r(()=>[s(p(T),e({ref:p(i),"data-state":p(N)(p(a).state.value),"data-disabled":p(a).disabled.value?``:void 0,style:{pointerEvents:`none`},"as-child":t.asChild,as:t.as},t.$attrs),{default:r(()=>[m(t.$slots,`default`)]),_:3},16,[`data-state`,`data-disabled`,`as-child`,`as`])]),_:3},8,[`present`]))}}),R=f({__name:`Checkbox`,props:{defaultValue:{},modelValue:{},disabled:{type:Boolean},value:{},id:{},trueValue:{},falseValue:{},asChild:{type:Boolean},as:{},name:{},required:{type:Boolean},class:{type:[Boolean,null,String,Object,Array]}},emits:[`update:modelValue`],setup(a,{emit:o}){let l=a,u=o,d=w(h(l,`class`),u);return(a,o)=>(n(),c(p(I),e({"data-slot":`checkbox`},p(d),{class:p(v)(`peer border-input data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50`,l.class)}),{default:r(e=>[s(p(L),{"data-slot":`checkbox-indicator`,class:`grid place-content-center text-current transition-none`},{default:r(()=>[m(a.$slots,`default`,i(t(e)),()=>[s(p(_),{class:`size-3.5`})])]),_:2},1024)]),_:3},16,[`class`]))}});export{R as t};

View File

@@ -1 +0,0 @@
import{A as e,I as t,Q as n,g as r,x as i,yt as a,z as o}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{b as s}from"./dist-3yfE1dPa.js";import{J as c}from"./index-BpHHjIYv.js";import{b as l}from"./Teleport-qOjHMYM8.js";import{i as u}from"./button-BTKRNUhQ.js";import{t as d}from"./useForwardExpose-CNhbE6SX.js";import{d as f}from"./DialogTitle-Do1F-aV6.js";var p=i({__name:`DialogDescription`,props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`p`}},setup(i){let s=i;d();let c=f();return(i,l)=>(t(),r(a(u),e(s,{id:a(c).descriptionId}),{default:n(()=>[o(i.$slots,`default`)]),_:3},16,[`id`]))}}),m=i({__name:`DialogDescription`,props:{asChild:{type:Boolean},as:{},class:{type:[Boolean,null,String,Object,Array]}},setup(i){let u=i,d=l(s(u,`class`));return(i,s)=>(t(),r(a(p),e({"data-slot":`dialog-description`},a(d),{class:a(c)(`text-muted-foreground text-sm`,u.class)}),{default:n(()=>[o(i.$slots,`default`)]),_:3},16,[`class`]))}});export{p as n,m as t};

View File

@@ -1 +0,0 @@
import{I as e,v as t,x as n,xt as r,yt as i,z as a}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{J as o}from"./index-BpHHjIYv.js";var s=n({__name:`DialogFooter`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(n){let s=n;return(n,c)=>(e(),t(`div`,{"data-slot":`dialog-footer`,class:r(i(o)(`flex flex-col-reverse gap-2 sm:flex-row sm:justify-end`,s.class))},[a(n.$slots,`default`)],2))}});export{s as t};

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
import{A as e,C as t,I as n,Q as r,St as i,b as a,g as o,ut as s,x as c,yt as l,z as u}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{b as d}from"./dist-3yfE1dPa.js";import{J as f}from"./index-BpHHjIYv.js";import{O as p,_ as m,b as h,d as g,g as _,l as v}from"./Teleport-qOjHMYM8.js";import{i as y}from"./button-BTKRNUhQ.js";import{t as b}from"./useForwardExpose-CNhbE6SX.js";var[x,S]=p([`MenuCheckboxItem`,`MenuRadioItem`],`MenuItemIndicatorContext`),C=c({__name:`MenuItemIndicator`,props:{forceMount:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`span`}},setup(e){let t=x({modelValue:s(!1)});return(e,i)=>(n(),o(l(_),{present:e.forceMount||l(g)(l(t).modelValue.value)||l(t).modelValue.value===!0},{default:r(()=>[a(l(y),{as:e.as,"as-child":e.asChild,"data-state":l(v)(l(t).modelValue.value)},{default:r(()=>[u(e.$slots,`default`)]),_:3},8,[`as`,`as-child`,`data-state`])]),_:3},8,[`present`]))}}),[w,T]=p(`MenuGroup`),E=c({__name:`MenuGroup`,props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(t){let i=t,a=m(void 0,`reka-menu-group`);return T({id:a}),(t,s)=>(n(),o(l(y),e({role:`group`},i,{"aria-labelledby":l(a)}),{default:r(()=>[u(t.$slots,`default`)]),_:3},16,[`aria-labelledby`]))}}),D=c({__name:`MenuLabel`,props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`div`}},setup(t){let i=t,a=w({id:``});return(t,s)=>(n(),o(l(y),e(i,{id:l(a).id||void 0}),{default:r(()=>[u(t.$slots,`default`)]),_:3},16,[`id`]))}}),O=c({__name:`MenuSeparator`,props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(t){let i=t;return(t,a)=>(n(),o(l(y),e(i,{role:`separator`,"aria-orientation":`horizontal`}),{default:r(()=>[u(t.$slots,`default`)]),_:3},16))}}),k=c({__name:`DropdownMenuItemIndicator`,props:{forceMount:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(e){let a=e;return b(),(e,s)=>(n(),o(l(C),i(t(a)),{default:r(()=>[u(e.$slots,`default`)]),_:3},16))}}),A=c({__name:`DropdownMenuLabel`,props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(e){let a=e;return b(),(e,s)=>(n(),o(l(D),i(t(a)),{default:r(()=>[u(e.$slots,`default`)]),_:3},16))}}),j=c({__name:`DropdownMenuSeparator`,props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(e){let a=e;return b(),(e,s)=>(n(),o(l(O),i(t(a)),{default:r(()=>[u(e.$slots,`default`)]),_:3},16))}}),M=c({__name:`DropdownMenuSeparator`,props:{asChild:{type:Boolean},as:{},class:{type:[Boolean,null,String,Object,Array]}},setup(t){let r=t,i=d(r,`class`);return(t,a)=>(n(),o(l(j),e({"data-slot":`dropdown-menu-separator`},l(i),{class:l(f)(`bg-border -mx-1 my-1 h-px`,r.class)}),null,16,[`class`]))}}),N=c({__name:`DropdownMenuLabel`,props:{asChild:{type:Boolean},as:{},class:{type:[Boolean,null,String,Object,Array]},inset:{type:Boolean}},setup(t){let i=t,a=h(d(i,`class`,`inset`));return(s,c)=>(n(),o(l(A),e({"data-slot":`dropdown-menu-label`,"data-inset":t.inset?``:void 0},l(a),{class:l(f)(`px-2 py-1.5 text-sm font-medium data-[inset]:pl-8`,i.class)}),{default:r(()=>[u(s.$slots,`default`)]),_:3},16,[`data-inset`,`class`]))}});export{S as a,E as i,M as n,k as r,N as t};

View File

@@ -1 +0,0 @@
import{A as e,C as t,I as n,Q as r,St as i,b as a,g as o,gt as s,h as c,m as l,x as u,yt as d,z as f}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{b as p,p as m}from"./dist-3yfE1dPa.js";import{t as h}from"./circle-Cc5GzalR.js";import{J as g}from"./index-BpHHjIYv.js";import{O as _,b as v,l as y,x as b,y as x}from"./Teleport-qOjHMYM8.js";import{a as S}from"./DropdownMenuTrigger-Dmk4lbKz.js";import{t as C}from"./useForwardExpose-CNhbE6SX.js";import{a as w,i as T,r as E}from"./DropdownMenuLabel-Bls_J4kr.js";var[D,O]=_(`MenuRadioGroup`),k=u({__name:`MenuRadioGroup`,props:{modelValue:{type:null,required:!1,default:``},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},emits:[`update:modelValue`],setup(e,{emit:a}){let s=e,c=a,l=v(p(s,[`modelValue`])),u=m(s,`modelValue`,c);return O({modelValue:u,onValueChange:e=>{u.value=e}}),(e,a)=>(n(),o(T,i(t(d(l))),{default:r(()=>[f(e.$slots,`default`,{modelValue:d(u)})]),_:3},16))}}),A=u({__name:`MenuRadioItem`,props:{value:{type:null,required:!0},disabled:{type:Boolean,required:!1},textValue:{type:String,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},emits:[`select`],setup(t,{emit:i}){let a=t,c=i,u=v(p(a,[`value`])),{value:m}=s(a),h=D(),g=l(()=>h.modelValue.value===m?.value);return w({modelValue:g}),(t,i)=>(n(),o(S,e({role:`menuitemradio`},d(u),{"aria-checked":g.value,"data-state":d(y)(g.value),onSelect:i[0]||=async e=>{c(`select`,e),d(h).onValueChange(d(m))}}),{default:r(()=>[f(t.$slots,`default`)]),_:3},16,[`aria-checked`,`data-state`]))}}),j=u({__name:`DropdownMenuRadioGroup`,props:{modelValue:{type:null,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},emits:[`update:modelValue`],setup(e,{emit:a}){let s=e,c=b(a);return C(),(e,a)=>(n(),o(d(k),i(t({...s,...d(c)})),{default:r(()=>[f(e.$slots,`default`)]),_:3},16))}}),M=u({__name:`DropdownMenuRadioItem`,props:{value:{type:null,required:!0},disabled:{type:Boolean,required:!1},textValue:{type:String,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},emits:[`select`],setup(e,{emit:a}){let s=x(e,a);return C(),(e,a)=>(n(),o(d(A),i(t(d(s))),{default:r(()=>[f(e.$slots,`default`)]),_:3},16))}}),N=u({__name:`DropdownMenuRadioGroup`,props:{modelValue:{},asChild:{type:Boolean},as:{}},emits:[`update:modelValue`],setup(t,{emit:i}){let a=x(t,i);return(t,i)=>(n(),o(d(j),e({"data-slot":`dropdown-menu-radio-group`},d(a)),{default:r(()=>[f(t.$slots,`default`)]),_:3},16))}}),P={class:`pointer-events-none absolute left-2 flex size-3.5 items-center justify-center`},F=u({__name:`DropdownMenuRadioItem`,props:{value:{},disabled:{type:Boolean},textValue:{},asChild:{type:Boolean},as:{},class:{type:[Boolean,null,String,Object,Array]}},emits:[`select`],setup(t,{emit:i}){let s=t,l=i,u=x(p(s,`class`),l);return(t,i)=>(n(),o(d(M),e({"data-slot":`dropdown-menu-radio-item`},d(u),{class:d(g)(`focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4`,s.class)}),{default:r(()=>[c(`span`,P,[a(d(E),null,{default:r(()=>[f(t.$slots,`indicator-icon`,{},()=>[a(d(h),{class:`size-2 fill-current`})])]),_:3})]),f(t.$slots,`default`)]),_:3},16,[`class`]))}});export{N as n,F as t};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
import{$ as e,I as t,at as n,i as r,v as i,x as a,xt as o,yt as s}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{p as c}from"./dist-3yfE1dPa.js";import{J as l}from"./index-BpHHjIYv.js";var u=a({__name:`Input`,props:{defaultValue:{},modelValue:{},class:{type:[Boolean,null,String,Object,Array]}},emits:[`update:modelValue`],setup(a,{emit:u}){let d=a,f=c(d,`modelValue`,u,{passive:!0,defaultValue:d.defaultValue});return(a,c)=>e((t(),i(`input`,{"onUpdate:modelValue":c[0]||=e=>n(f)?f.value=e:null,"data-slot":`input`,class:o(s(l)(`file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm`,`focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]`,`aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive`,d.class))},null,2)),[[r,s(f)]])}});export{u as t};

View File

@@ -1 +0,0 @@
import{A as e,I as t,Q as n,g as r,x as i,yt as a,z as o}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{b as s}from"./dist-3yfE1dPa.js";import{J as c}from"./index-BpHHjIYv.js";import{i as l}from"./button-BTKRNUhQ.js";import{t as u}from"./useForwardExpose-CNhbE6SX.js";var d=i({__name:`Label`,props:{for:{type:String,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`label`}},setup(i){let s=i;return u(),(i,c)=>(t(),r(a(l),e(s,{onMousedown:c[0]||=e=>{!e.defaultPrevented&&e.detail>1&&e.preventDefault()}}),{default:n(()=>[o(i.$slots,`default`)]),_:3},16))}}),f=i({__name:`Label`,props:{for:{},asChild:{type:Boolean},as:{},class:{type:[Boolean,null,String,Object,Array]}},setup(i){let l=i,u=s(l,`class`);return(i,s)=>(t(),r(a(d),e({"data-slot":`label`},a(u),{class:a(c)(`flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50`,l.class)}),{default:n(()=>[o(i.$slots,`default`)]),_:3},16,[`class`]))}});export{f as t};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
import{I as e,Q as t,b as n,g as r,gt as i,ut as a,x as o,yt as s,z as c}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{p as l}from"./dist-3yfE1dPa.js";import{D as u,O as d}from"./Teleport-qOjHMYM8.js";import{i as f}from"./button-BTKRNUhQ.js";import{o as p,u as m}from"./PopperContent-oFiuPLDs.js";var h=`rovingFocusGroup.onEntryFocus`,g={bubbles:!1,cancelable:!0},_={ArrowLeft:`prev`,ArrowUp:`prev`,ArrowRight:`next`,ArrowDown:`next`,PageUp:`first`,Home:`first`,PageDown:`last`,End:`last`};function v(e,t){return t===`rtl`?e===`ArrowLeft`?`ArrowRight`:e===`ArrowRight`?`ArrowLeft`:e:e}function y(e,t,n){let r=v(e.key,n);if(!(t===`vertical`&&[`ArrowLeft`,`ArrowRight`].includes(r))&&!(t===`horizontal`&&[`ArrowUp`,`ArrowDown`].includes(r)))return _[r]}function b(e,t=!1){let n=u();for(let r of e)if(r===n||(r.focus({preventScroll:t}),u()!==n))return}function x(e,t){return e.map((n,r)=>e[(t+r)%e.length])}var[S,C]=d(`RovingFocusGroup`),w=o({__name:`RovingFocusGroup`,props:{orientation:{type:String,required:!1,default:void 0},dir:{type:String,required:!1},loop:{type:Boolean,required:!1,default:!1},currentTabStopId:{type:[String,null],required:!1},defaultCurrentTabStopId:{type:String,required:!1},preventScrollOnEntryFocus:{type:Boolean,required:!1,default:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},emits:[`entryFocus`,`update:currentTabStopId`],setup(o,{expose:u,emit:d}){let _=o,v=d,{loop:y,orientation:x,dir:S}=i(_),w=m(S),T=l(_,`currentTabStopId`,v,{defaultValue:_.defaultCurrentTabStopId,passive:_.currentTabStopId===void 0}),E=a(!1),D=a(!1),O=a(0),{getItems:k,CollectionSlot:A}=p({isProvider:!0});function j(e){let t=!D.value;if(e.currentTarget&&e.target===e.currentTarget&&t&&!E.value){let t=new CustomEvent(h,g);if(e.currentTarget.dispatchEvent(t),v(`entryFocus`,t),!t.defaultPrevented){let e=k().map(e=>e.ref).filter(e=>e.dataset.disabled!==``);b([e.find(e=>e.getAttribute(`data-active`)===``),e.find(e=>e.getAttribute(`data-highlighted`)===``),e.find(e=>e.id===T.value),...e].filter(Boolean),_.preventScrollOnEntryFocus)}}D.value=!1}function M(){setTimeout(()=>{D.value=!1},1)}return u({getItems:k}),C({loop:y,dir:w,orientation:x,currentTabStopId:T,onItemFocus:e=>{T.value=e},onItemShiftTab:()=>{E.value=!0},onFocusableItemAdd:()=>{O.value++},onFocusableItemRemove:()=>{O.value--}}),(i,a)=>(e(),r(s(A),null,{default:t(()=>[n(s(f),{tabindex:E.value||O.value===0?-1:0,"data-orientation":s(x),as:i.as,"as-child":i.asChild,dir:s(w),style:{outline:`none`},onMousedown:a[0]||=e=>D.value=!0,onMouseup:M,onFocus:j,onBlur:a[1]||=e=>E.value=!1},{default:t(()=>[c(i.$slots,`default`)]),_:3},8,[`tabindex`,`data-orientation`,`as`,`as-child`,`dir`])]),_:3}))}});export{x as a,y as i,S as n,b as r,w as t};

View File

@@ -1 +0,0 @@
import{I as e,N as t,P as n,Q as r,b as i,g as a,j as o,m as s,x as c,yt as l,z as u}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{_ as d}from"./Teleport-qOjHMYM8.js";import{i as f}from"./button-BTKRNUhQ.js";import{o as p}from"./PopperContent-oFiuPLDs.js";import{a as m,i as h,n as g,r as _}from"./RovingFocusGroup--sGcMhFA.js";var v=c({__name:`RovingFocusItem`,props:{tabStopId:{type:String,required:!1},focusable:{type:Boolean,required:!1,default:!0},active:{type:Boolean,required:!1},allowShiftKey:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`span`}},setup(c){let v=c,y=g(),b=d(),x=s(()=>v.tabStopId||b),S=s(()=>y.currentTabStopId.value===x.value),{getItems:C,CollectionItem:w}=p();t(()=>{v.focusable&&y.onFocusableItemAdd()}),n(()=>{v.focusable&&y.onFocusableItemRemove()});function T(e){if(e.key===`Tab`&&e.shiftKey){y.onItemShiftTab();return}if(e.target!==e.currentTarget)return;let t=h(e,y.orientation.value,y.dir.value);if(t!==void 0){if(e.metaKey||e.ctrlKey||e.altKey||!v.allowShiftKey&&e.shiftKey)return;e.preventDefault();let n=[...C().map(e=>e.ref).filter(e=>e.dataset.disabled!==``)];if(t===`last`)n.reverse();else if(t===`prev`||t===`next`){t===`prev`&&n.reverse();let r=n.indexOf(e.currentTarget);n=y.loop.value?m(n,r+1):n.slice(r+1)}o(()=>_(n))}}return(t,n)=>(e(),a(l(w),null,{default:r(()=>[i(l(f),{tabindex:S.value?0:-1,"data-orientation":l(y).orientation.value,"data-active":t.active?``:void 0,"data-disabled":t.focusable?void 0:``,as:t.as,"as-child":t.asChild,onMousedown:n[0]||=e=>{t.focusable?l(y).onItemFocus(x.value):e.preventDefault()},onFocus:n[1]||=e=>l(y).onItemFocus(x.value),onKeydown:T},{default:r(()=>[u(t.$slots,`default`)]),_:3},8,[`tabindex`,`data-orientation`,`data-active`,`data-disabled`,`as`,`as-child`])]),_:3}))}});export{v as t};

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
import{A as e,C as t,I as n,Q as r,St as i,g as a,m as o,x as s,yt as c,z as l}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{b as u}from"./dist-3yfE1dPa.js";import{J as d}from"./index-BpHHjIYv.js";import{i as f}from"./button-BTKRNUhQ.js";var p=s({__name:`BaseSeparator`,props:{orientation:{type:String,required:!1,default:`horizontal`},decorative:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(t){let i=t,s=[`horizontal`,`vertical`];function u(e){return s.includes(e)}let d=o(()=>u(i.orientation)?i.orientation:`horizontal`),p=o(()=>d.value===`vertical`?i.orientation:void 0),m=o(()=>i.decorative?{role:`none`}:{"aria-orientation":p.value,role:`separator`});return(t,i)=>(n(),a(c(f),e({as:t.as,"as-child":t.asChild,"data-orientation":d.value},m.value),{default:r(()=>[l(t.$slots,`default`)]),_:3},16,[`as`,`as-child`,`data-orientation`]))}}),m=s({__name:`Separator`,props:{orientation:{type:String,required:!1,default:`horizontal`},decorative:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(e){let o=e;return(e,s)=>(n(),a(p,i(t(o)),{default:r(()=>[l(e.$slots,`default`)]),_:3},16))}}),h=s({__name:`Separator`,props:{orientation:{default:`horizontal`},decorative:{type:Boolean,default:!0},asChild:{type:Boolean},as:{},class:{type:[Boolean,null,String,Object,Array]}},setup(t){let r=t,i=u(r,`class`);return(t,o)=>(n(),a(c(m),e({"data-slot":`separator`},c(i),{class:c(d)(`bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px`,r.class)}),null,16,[`class`]))}});export{m as n,h as t};

View File

@@ -1 +0,0 @@
import{I as e,h as t,v as n,x as r,xt as i,yt as a,z as o}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{J as s}from"./index-BpHHjIYv.js";var c={"data-slot":`table-container`,class:`relative w-full overflow-auto`},l=r({__name:`Table`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(r){let l=r;return(r,u)=>(e(),n(`div`,c,[t(`table`,{"data-slot":`table`,class:i(a(s)(`w-full caption-bottom text-sm`,l.class))},[o(r.$slots,`default`)],2)]))}}),u=r({__name:`TableBody`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(t){let r=t;return(t,c)=>(e(),n(`tbody`,{"data-slot":`table-body`,class:i(a(s)(`[&_tr:last-child]:border-0`,r.class))},[o(t.$slots,`default`)],2))}}),d=r({__name:`TableCell`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(t){let r=t;return(t,c)=>(e(),n(`td`,{"data-slot":`table-cell`,class:i(a(s)(`p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]`,r.class))},[o(t.$slots,`default`)],2))}}),f=r({__name:`TableHeader`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(t){let r=t;return(t,c)=>(e(),n(`thead`,{"data-slot":`table-header`,class:i(a(s)(`[&_tr]:border-b`,r.class))},[o(t.$slots,`default`)],2))}}),p=r({__name:`TableRow`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(t){let r=t;return(t,c)=>(e(),n(`tr`,{"data-slot":`table-row`,class:i(a(s)(`hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors`,r.class))},[o(t.$slots,`default`)],2))}}),m=r({__name:`TableHead`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(t){let r=t;return(t,c)=>(e(),n(`th`,{"data-slot":`table-head`,class:i(a(s)(`text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]`,r.class))},[o(t.$slots,`default`)],2))}});export{u as a,d as i,p as n,l as o,f as r,m as t};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
import{I as e,Q as t,_t as n,g as r,m as i,x as a,yt as o,z as s}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{i as c}from"./dist-3yfE1dPa.js";import{i as l}from"./button-BTKRNUhQ.js";function u(e){return typeof e==`string`?`'${e}'`:new d().serialize(e)}var d=function(){class e{#e=new Map;compare(e,t){let n=typeof e,r=typeof t;return n===`string`&&r===`string`?e.localeCompare(t):n===`number`&&r===`number`?e-t:String.prototype.localeCompare.call(this.serialize(e,!0),this.serialize(t,!0))}serialize(e,t){if(e===null)return`null`;switch(typeof e){case`string`:return t?e:`'${e}'`;case`bigint`:return`${e}n`;case`object`:return this.$object(e);case`function`:return this.$function(e)}return String(e)}serializeObject(e){let t=Object.prototype.toString.call(e);if(t!==`[object Object]`)return this.serializeBuiltInType(t.length<10?`unknown:${t}`:t.slice(8,-1),e);let n=e.constructor,r=n===Object||n===void 0?``:n.name;if(r!==``&&globalThis[r]===n)return this.serializeBuiltInType(r,e);if(typeof e.toJSON==`function`){let t=e.toJSON();return r+(typeof t==`object`&&t?this.$object(t):`(${this.serialize(t)})`)}return this.serializeObjectEntries(r,Object.entries(e))}serializeBuiltInType(e,t){let n=this[`$`+e];if(n)return n.call(this,t);if(typeof t?.entries==`function`)return this.serializeObjectEntries(e,t.entries());throw Error(`Cannot serialize ${e}`)}serializeObjectEntries(e,t){let n=Array.from(t).sort((e,t)=>this.compare(e[0],t[0])),r=`${e}{`;for(let e=0;e<n.length;e++){let[t,i]=n[e];r+=`${this.serialize(t,!0)}:${this.serialize(i)}`,e<n.length-1&&(r+=`,`)}return r+`}`}$object(e){let t=this.#e.get(e);return t===void 0&&(this.#e.set(e,`#${this.#e.size}`),t=this.serializeObject(e),this.#e.set(e,t)),t}$function(e){let t=Function.prototype.toString.call(e);return t.slice(-15)===`[native code] }`?`${e.name||``}()[native]`:`${e.name}(${e.length})${t.replace(/\s*\n\s*/g,``)}`}$Array(e){let t=`[`;for(let n=0;n<e.length;n++)t+=this.serialize(e[n]),n<e.length-1&&(t+=`,`);return t+`]`}$Date(e){try{return`Date(${e.toISOString()})`}catch{return`Date(null)`}}$ArrayBuffer(e){return`ArrayBuffer[${new Uint8Array(e).join(`,`)}]`}$Set(e){return`Set${this.$Array(Array.from(e).sort((e,t)=>this.compare(e,t)))}`}$Map(e){return this.serializeObjectEntries(`Map`,e.entries())}}for(let t of[`Error`,`RegExp`,`URL`])e.prototype[`$`+t]=function(e){return`${t}(${e})`};for(let t of[`Int8Array`,`Uint8Array`,`Uint8ClampedArray`,`Int16Array`,`Uint16Array`,`Int32Array`,`Uint32Array`,`Float32Array`,`Float64Array`])e.prototype[`$`+t]=function(e){return`${t}[${e.join(`,`)}]`};for(let t of[`BigInt64Array`,`BigUint64Array`])e.prototype[`$`+t]=function(e){return`${t}[${e.join(`n,`)}${e.length>0?`n`:``}]`};return e}();function f(e,t){return e===t||u(e)===u(t)}function p(e){return i(()=>n(e)?!!c(e)?.closest(`form`):!0)}var m=a({__name:`VisuallyHidden`,props:{feature:{type:String,required:!1,default:`focusable`},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`span`}},setup(n){return(n,i)=>(e(),r(o(l),{as:n.as,"as-child":n.asChild,"aria-hidden":n.feature===`focusable`?`true`:void 0,"data-hidden":n.feature===`fully-hidden`?``:void 0,tabindex:n.feature===`fully-hidden`?`-1`:void 0,style:{position:`absolute`,border:0,width:`1px`,height:`1px`,padding:0,margin:`-1px`,overflow:`hidden`,clip:`rect(0, 0, 0, 0)`,clipPath:`inset(50%)`,whiteSpace:`nowrap`,wordWrap:`normal`,top:`-1px`,left:`-1px`}},{default:t(()=>[s(n.$slots,`default`)]),_:3},8,[`as`,`as-child`,`aria-hidden`,`data-hidden`,`tabindex`]))}});export{p as n,f as r,m as t};

View File

@@ -1 +0,0 @@
import{A as e,I as t,J as n,R as r,_ as i,g as a,l as o,m as s,v as c,x as l}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{t as u}from"./VisuallyHidden-_sQ0xQ9O.js";import{s as d}from"./PopperContent-oFiuPLDs.js";var f=l({inheritAttrs:!1,__name:`VisuallyHiddenInputBubble`,props:{name:{type:String,required:!0},value:{type:null,required:!0},checked:{type:Boolean,required:!1,default:void 0},required:{type:Boolean,required:!1},disabled:{type:Boolean,required:!1},feature:{type:String,required:!1,default:`fully-hidden`}},setup(r){let i=r,{primitiveElement:o,currentElement:c}=d();return n(s(()=>i.checked??i.value),(e,t)=>{if(!c.value)return;let n=c.value,r=window.HTMLInputElement.prototype,i=Object.getOwnPropertyDescriptor(r,`value`).set;if(i&&e!==t){let t=new Event(`input`,{bubbles:!0}),r=new Event(`change`,{bubbles:!0});i.call(n,e),n.dispatchEvent(t),n.dispatchEvent(r)}}),(n,r)=>(t(),a(u,e({ref_key:`primitiveElement`,ref:o},{...i,...n.$attrs},{as:`input`}),null,16))}}),p=l({inheritAttrs:!1,__name:`VisuallyHiddenInput`,props:{name:{type:String,required:!0},value:{type:null,required:!0},checked:{type:Boolean,required:!1,default:void 0},required:{type:Boolean,required:!1},disabled:{type:Boolean,required:!1},feature:{type:String,required:!1,default:`fully-hidden`}},setup(n){let l=n,u=s(()=>typeof l.value==`object`&&Array.isArray(l.value)&&l.value.length===0&&l.required),d=s(()=>typeof l.value==`string`||typeof l.value==`number`||typeof l.value==`boolean`||l.value===null||l.value===void 0?[{name:l.name,value:l.value}]:typeof l.value==`object`&&Array.isArray(l.value)?l.value.flatMap((e,t)=>typeof e==`object`?Object.entries(e).map(([e,n])=>({name:`${l.name}[${t}][${e}]`,value:n})):{name:`${l.name}[${t}]`,value:e}):l.value!==null&&typeof l.value==`object`&&!Array.isArray(l.value)?Object.entries(l.value).map(([e,t])=>({name:`${l.name}[${e}]`,value:t})):[]);return(n,s)=>(t(),c(o,null,[i(` We render single input if it's required `),u.value?(t(),a(f,e({key:n.name},{...l,...n.$attrs},{name:n.name,value:n.value}),null,16,[`name`,`value`])):(t(!0),c(o,{key:1},r(d.value,r=>(t(),a(f,e({key:r.name},{ref_for:!0},{...l,...n.$attrs},{name:r.name,value:r.value}),null,16,[`name`,`value`]))),128))],2112))}});export{p as t};

View File

@@ -1 +0,0 @@
import{I as e,Q as t,b as n,h as r,v as i,wt as a,x as o,y as s,z as c}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{n as l}from"./button-BTKRNUhQ.js";import{t as u}from"./route-block-BCBU0UBp.js";var d={class:`max-w-2xl mx-auto text-center`},f={class:`font-bold text-8xl`},p={class:`mt-4 text-2xl font-bold`},m={class:`text-stone-400`},h={class:`mt-8`},g={class:`flex justify-center gap-2`},_=o({__name:`custom-error`,props:{code:{},subtitle:{},error:{}},setup(o){return(u,_)=>{let v=l;return e(),i(`div`,d,[r(`h1`,f,a(o.code),1),r(`h2`,p,a(o.subtitle),1),r(`p`,m,a(o.error),1),r(`footer`,h,[c(u.$slots,`default`,{},()=>[r(`div`,g,[n(v,{variant:`outline`,onClick:_[0]||=e=>u.$router.back()},{default:t(()=>[..._[2]||=[s(` Go Back `,-1)]]),_:1}),n(v,{onClick:_[1]||=e=>u.$router.push(`/`)},{default:t(()=>[..._[3]||=[s(` Back to Home `,-1)]]),_:1})])])])])}}}),v={class:`flex items-center justify-center h-screen`},y=o({__name:`[...path]`,setup(t){return(t,r)=>(e(),i(`div`,v,[n(_,{code:404,subtitle:`Page Not Found`,error:`The page you are looking for might have been removed, had its name changed, or is temporarily unavailable.`})]))}});typeof u==`function`&&u(y);var b=y;export{b as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
import{B as e,I as t,g as n}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{K as r}from"./index-BpHHjIYv.js";import{t as i}from"./route-block-BCBU0UBp.js";var a={};function o(r,i){let a=e(`router-view`);return t(),n(a)}typeof i==`function`&&i(a);var s=r(a,[[`render`,o]]);export{s as default};

View File

@@ -1 +0,0 @@
import{B as e,I as t,g as n}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{K as r}from"./index-BpHHjIYv.js";var i={};function a(r,i){let a=e(`router-view`);return t(),n(a)}var o=r(i,[[`render`,a]]);export{o as default};

View File

@@ -1 +0,0 @@
import{A as e,I as t,Q as n,c as r,g as i,l as a,p as o,w as s,x as c,xt as l,yt as u,z as d}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{J as f,X as p}from"./index-BpHHjIYv.js";function m(e){return e?e.flatMap(e=>e.type===a?m(e.children):[e]):[]}var h=c({name:`PrimitiveSlot`,inheritAttrs:!1,setup(t,{attrs:n,slots:i}){return()=>{if(!i.default)return null;let t=m(i.default()),a=t.findIndex(e=>e.type!==r);if(a===-1)return t;let s=t[a];delete s.props?.ref;let c=s.props?e(n,s.props):n,l=o({...s,props:{}},c);return t.length===1?l:(t[a]=l,t)}}}),g=[`area`,`img`,`input`],_=c({name:`Primitive`,inheritAttrs:!1,props:{asChild:{type:Boolean,default:!1},as:{type:[String,Object],default:`div`}},setup(e,{attrs:t,slots:n}){let r=e.asChild?`template`:e.as;return typeof r==`string`&&g.includes(r)?()=>s(r,t):r===`template`?()=>s(h,t,{default:n.default}):()=>s(e.as,t,{default:n.default})}}),v=e=>typeof e==`boolean`?`${e}`:e===0?`0`:e,y=p,b=(e,t)=>n=>{if(t?.variants==null)return y(e,n?.class,n?.className);let{variants:r,defaultVariants:i}=t,a=Object.keys(r).map(e=>{let t=n?.[e],a=i?.[e];if(t===null)return null;let o=v(t)||v(a);return r[e][o]}),o=n&&Object.entries(n).reduce((e,t)=>{let[n,r]=t;return r===void 0||(e[n]=r),e},{});return y(e,a,t?.compoundVariants?.reduce((e,t)=>{let{class:n,className:r,...a}=t;return Object.entries(a).every(e=>{let[t,n]=e;return Array.isArray(n)?n.includes({...i,...o}[t]):{...i,...o}[t]===n})?[...e,n,r]:e},[]),n?.class,n?.className)},x=c({__name:`Button`,props:{variant:{},size:{},class:{type:[Boolean,null,String,Object,Array]},asChild:{type:Boolean},as:{default:`button`}},setup(e){let r=e;return(a,o)=>(t(),i(u(_),{"data-slot":`button`,as:e.as,"as-child":e.asChild,class:l(u(f)(u(S)({variant:e.variant,size:e.size}),r.class))},{default:n(()=>[d(a.$slots,`default`)]),_:3},8,[`as`,`as-child`,`class`]))}}),S=b(`inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive`,{variants:{variant:{default:`bg-primary text-primary-foreground hover:bg-primary/90`,destructive:`bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60`,outline:`border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50`,secondary:`bg-secondary text-secondary-foreground hover:bg-secondary/80`,ghost:`hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50`,link:`text-primary underline-offset-4 hover:underline`},size:{default:`h-9 px-4 py-2 has-[>svg]:px-3`,sm:`h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5`,lg:`h-10 rounded-md px-6 has-[>svg]:px-4`,icon:`size-9`,"icon-sm":`size-8`,"icon-lg":`size-10`}},defaultVariants:{variant:`default`,size:`default`}});export{h as a,_ as i,x as n,m as o,b as r,S as t};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
import{B as e,I as t,Q as n,R as r,V as i,_ as a,b as o,g as s,h as c,l,m as u,v as d,wt as f,x as p,xt as m,y as h,yt as g,z as _}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{t as v}from"./chevrons-up-down-Bbw1im9J.js";import{J as y,N as b}from"./index-BpHHjIYv.js";import{n as x}from"./button-BTKRNUhQ.js";import{i as S,n as C,r as w,t as T}from"./DropdownMenuTrigger-Dmk4lbKz.js";var E={class:`text-2xl font-bold`},D={key:0,class:`text-muted-foreground`},O={class:`flex items-center gap-2 flex-wrap`},k=p({__name:`basic-header`,props:{title:{},description:{},sticky:{type:Boolean}},setup(e){return(n,r)=>(t(),d(`header`,{class:m(g(y)(`flex flex-col md:flex-row gap-2 justify-between py-2`,e.sticky?`sticky top-0 z-40 bg-background`:``))},[c(`main`,null,[c(`h1`,E,f(e.title),1),e.description?(t(),d(`p`,D,f(e.description),1)):a(``,!0)]),c(`aside`,O,[_(n.$slots,`actions`)])],2))}}),A={class:`py-4`},j=p({__name:`basic-page`,props:{title:{},description:{},sticky:{type:Boolean}},setup(e){return(r,i)=>(t(),d(`main`,null,[o(k,{title:e.title,description:e.description,sticky:e.sticky},{actions:n(()=>[_(r.$slots,`actions`)]),_:3},8,[`title`,`description`,`sticky`]),c(`main`,A,[_(r.$slots,`default`)])]))}}),M={class:`flex flex-col gap-2`},N=`text-primary font-semibold bg-primary/5`,P=p({__name:`two-col-aside`,props:{nav:{}},setup(a){let p=a,_=b(),y=u(()=>_.path),E=u(()=>p.nav.find(e=>e.url===y.value));return(a,u)=>{let _=e(`router-link`),b=x,D=T,O=C,k=w,A=S;return t(),d(`nav`,M,[(t(!0),d(l,null,r(p.nav,e=>(t(),s(_,{key:e.url,to:e.url,class:m([`items-center hidden px-2 py-1 rounded-md lg:flex hover:bg-primary/5`,e.url===g(y)?N:``])},{default:n(()=>[(t(),s(i(e.icon),{class:`size-4 mr-1`})),c(`span`,null,f(e.title),1)]),_:2},1032,[`to`,`class`]))),128)),o(A,{class:`lg:hidden`},{default:n(()=>[o(D,{"as-child":``},{default:n(()=>[o(b,{variant:`outline`,class:`w-48 lg:hidden`},{default:n(()=>[(t(),s(i(g(E)?.icon),{class:`size-4 mr-1`})),c(`span`,null,f(g(E)?.title),1),o(g(v),{class:`size-4 ml-auto`})]),_:1})]),_:1}),o(k,{class:`w-48`,align:`start`},{default:n(()=>[(t(!0),d(l,null,r(p.nav,e=>(t(),s(O,{key:e.url,onClick:t=>a.$router.push(e.url)},{default:n(()=>[(t(),s(i(e.icon),{class:`size-4 mr-1`})),h(` `+f(e.title),1)]),_:2},1032,[`onClick`]))),128))]),_:1})]),_:1})])}}}),F=p({__name:`two-col`,setup(e){return(e,n)=>(t(),d(`div`,{class:m(g(y)(`grid grid-cols-1 lg:grid-cols-[200px_1fr] gap-4 w-full`))},[c(`aside`,null,[_(e.$slots,`aside`)]),c(`section`,null,[_(e.$slots,`default`)])],2))}});export{P as n,j as r,F as t};

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
import{B as e,I as t,Q as n,R as r,b as i,g as a,h as o,l as s,v as c,wt as l,x as u,y as d,yt as f}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{o as p}from"./dist-3yfE1dPa.js";import{n as m,t as h}from"./toggle-theme-9ZMsSjs2.js";import{$ as g,K as _}from"./index-BpHHjIYv.js";import"./Teleport-qOjHMYM8.js";import{n as v}from"./button-BTKRNUhQ.js";import{n as y,t as b}from"./AvatarImage-Ct5I9mHM.js";var x={class:`min-h-18 flex items-center justify-between`},S={class:`flex items-center gap-2`},C=u({__name:`the-footer`,setup(e){let a=p(),l=[{name:`bluesky`,icon:`simple-icons:bluesky`,url:`https://bsky.app/profile/bitmc.bsky.social`},{name:`github`,icon:`simple-icons:github`,url:`https://www.github.com/whbbit1999/shadcn-vue-admin`},{name:`bilibili`,icon:`simple-icons:bilibili`,url:`https://space.bilibili.com/104376935`}];return(e,u)=>{let d=b,p=y,m=v;return t(),c(`footer`,x,[i(p,null,{default:n(()=>[i(d,{src:`${f(a)===`dark`?`/logo.svg`:`/logo-black.svg`}`,alt:`Logo`},null,8,[`src`])]),_:1}),u[0]||=o(`div`,null,`© 2025 Whbbit1999`,-1),o(`div`,S,[(t(),c(s,null,r(l,e=>i(m,{key:e.name,variant:`outline`,size:`icon`,as:`a`,href:e.url,target:`_blank`},{default:n(()=>[i(f(g),{icon:e.icon},null,8,[`icon`])]),_:2},1032,[`href`])),64))])])}}}),w={};function T(e,r){let i=v;return t(),a(i,{as:`a`,href:`/auth/sign-in`},{default:n(()=>[d(l(e.$t(`login`)),1)]),_:1})}var E=_(w,[[`render`,T]]),D={};function O(e,r){let i=v;return t(),a(i,{as:`a`,href:`/auth/sign-up`,variant:`outline`},{default:n(()=>[d(l(e.$t(`register`)),1)]),_:1})}var k=_(D,[[`render`,O]]),A={class:`h-14 flex items-center marketing-header sticky top-0 z-99`},j={class:`mr-2 hidden lg:flex lg:gap-2`},M={class:`flex gap-2`},N=_(u({__name:`the-header`,setup(r){let a=p();return(r,s)=>{let l=b,u=y,d=e(`router-link`);return t(),c(`header`,A,[i(d,{to:`/`,class:`flex items-center gap-2`},{default:n(()=>[i(u,null,{default:n(()=>[i(l,{src:`${f(a)===`dark`?`/logo.svg`:`/logo-black.svg`}`,alt:`Logo`},null,8,[`src`])]),_:1}),s[0]||=o(`span`,{class:`text-base font-bold`},`Shadcn Vue Admin`,-1)]),_:1}),s[1]||=o(`div`,{class:`flex-1`},null,-1),o(`div`,j,[i(E),i(k)]),o(`div`,M,[i(m),i(h)])])}}}),[[`__scopeId`,`data-v-8a713a75`]]),P={class:`container mx-auto`},F={class:`mx-2 lg:p-0`},I=u({__name:`marketing`,setup(n){return(n,r)=>{let a=e(`router-view`);return t(),c(`div`,P,[o(`div`,F,[i(N),o(`main`,null,[i(a)]),i(C)])])}}});export{I as default};

View File

@@ -1 +0,0 @@
.marketing-header[data-v-8a713a75]{-webkit-backdrop-filter:saturate(50%)blur(4px);backdrop-filter:saturate(50%)blur(4px);background-size:4px 4px}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
import{I as e,v as t,x as n}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{t as r}from"./route-block-BCBU0UBp.js";var i=n({__name:`index`,setup(n){return(n,r)=>(e(),t(`div`))}});typeof r==`function`&&r(i);var a=i;export{a as default};

View File

@@ -1 +0,0 @@
var e={};export{e as t};

View File

@@ -1 +0,0 @@
import{I as e,Q as t,Y as n,_ as r,at as i,b as a,g as o,h as s,s as c,ut as l,v as u,wt as d,x as f,y as p,yt as m}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{T as h}from"./dist-3yfE1dPa.js";import{t as g}from"./eye-off-DDZmXXZv.js";import{P as _,q as v}from"./index-BpHHjIYv.js";import{n as y}from"./button-BTKRNUhQ.js";import{t as b}from"./Label-sjjJXKKd.js";import{t as x}from"./Input-DOTs5aTB.js";import"./monisuo-admin.api-DyXM8BcP.js";import{t as S}from"./use-auth-BEiiAXZl.js";import{t as C}from"./route-block-BCBU0UBp.js";import{t as w}from"./Card-o8MCRg3I.js";import{t as T}from"./CardContent-BXRdn2MY.js";import{r as E,t as D}from"./Alert-ChDGwKFB.js";import{n as O,r as k,t as A}from"./CardTitle-C-tfNzWl.js";var j=h(`eye`,[[`path`,{d:`M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0`,key:`1nclc0`}],[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}]]),M=h(`lock`,[[`rect`,{width:`18`,height:`11`,x:`3`,y:`11`,rx:`2`,ry:`2`,key:`1w4ew1`}],[`path`,{d:`M7 11V7a5 5 0 0 1 10 0v4`,key:`fwvmzm`}]]),N=h(`user`,[[`path`,{d:`M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2`,key:`975kel`}],[`circle`,{cx:`12`,cy:`7`,r:`4`,key:`17ys0d`}]]),P={class:`min-h-screen flex items-center justify-center bg-gradient-to-br from-background to-muted p-4`},F={class:`flex justify-center mb-4`},I={class:`size-12 rounded-xl bg-primary flex items-center justify-center`},L={class:`space-y-2`},R={class:`relative`},z={class:`space-y-2`},B={class:`relative`},V=f({__name:`sign-in`,setup(f){let h=l(``),C=l(``),V=l(!1),{login:H,loading:U,error:W,isLogin:G}=S(),K=_();n(()=>{m(G)&&K.push(`/monisuo/dashboard`)});async function q(){!h.value||!C.value||await H(h.value,C.value)}return(n,l)=>{let f=A,_=O,S=k,H=b,G=x,K=E,J=D,Y=v,X=y,Z=T,Q=w;return e(),u(`div`,P,[a(Q,{class:`w-full max-w-lg`},{default:t(()=>[a(S,{class:`space-y-1 text-center`},{default:t(()=>[s(`div`,F,[s(`div`,I,[a(m(M),{class:`size-6 text-primary-foreground`})])]),a(f,{class:`text-2xl font-bold`},{default:t(()=>[...l[3]||=[p(` Monisuo Admin `,-1)]]),_:1}),a(_,null,{default:t(()=>[...l[4]||=[p(` 管理员登录 `,-1)]]),_:1})]),_:1}),a(Z,null,{default:t(()=>[s(`form`,{onSubmit:c(q,[`prevent`]),class:`space-y-4`},[s(`div`,L,[a(H,{for:`username`},{default:t(()=>[...l[5]||=[p(`用户名`,-1)]]),_:1}),s(`div`,R,[a(m(N),{class:`absolute left-3 top-1/2 -translate-y-1/2 size-4 text-muted-foreground`}),a(G,{id:`username`,modelValue:m(h),"onUpdate:modelValue":l[0]||=e=>i(h)?h.value=e:null,type:`text`,placeholder:`请输入用户名`,class:`pl-9`,disabled:m(U)},null,8,[`modelValue`,`disabled`])])]),s(`div`,z,[a(H,{for:`password`},{default:t(()=>[...l[6]||=[p(`密码`,-1)]]),_:1}),s(`div`,B,[a(m(M),{class:`absolute left-3 top-1/2 -translate-y-1/2 size-4 text-muted-foreground`}),a(G,{id:`password`,modelValue:m(C),"onUpdate:modelValue":l[1]||=e=>i(C)?C.value=e:null,type:m(V)?`text`:`password`,placeholder:`请输入密码`,class:`pl-9 pr-9`,disabled:m(U)},null,8,[`modelValue`,`type`,`disabled`]),s(`button`,{type:`button`,class:`absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground`,onClick:l[2]||=e=>V.value=!m(V)},[m(V)?(e(),o(m(g),{key:1,class:`size-4`})):(e(),o(m(j),{key:0,class:`size-4`}))])])]),m(W)?(e(),o(J,{key:0,variant:`destructive`},{default:t(()=>[a(K,null,{default:t(()=>[p(d(m(W)),1)]),_:1})]),_:1})):r(``,!0),a(X,{type:`submit`,class:`w-full`,disabled:m(U)},{default:t(()=>[m(U)?(e(),o(Y,{key:0,class:`size-4 mr-2`})):r(``,!0),p(` `+d(m(U)?`登录中...`:`登录`),1)]),_:1},8,[`disabled`])],32)]),_:1})]),_:1})])}}});typeof C==`function`&&C(V);var H=V;export{H as default};

View File

@@ -1 +0,0 @@
import{I as e,Q as t,b as n,v as r,w as i,wt as a,x as o,y as s,yt as c}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{n as l}from"./lib-CC9cpJ8Y.js";import"./Teleport-qOjHMYM8.js";import{n as u}from"./button-BTKRNUhQ.js";import{a as d,i as f,n as p,r as m,s as h}from"./modal-DKtIxxgh.js";var g=o({__name:`task-delete`,props:{task:{}},setup(o){let g=o;function _(){l(`The following task has been deleted:`,{description:i(`pre`,{class:`mt-2 w-[340px] rounded-md bg-slate-950 p-4`},i(`code`,{class:`text-white`},JSON.stringify(g.task,null,2)))})}return(i,l)=>{let g=u;return e(),r(`div`,null,[n(c(m),null,{default:t(()=>[n(c(p),null,{default:t(()=>[s(` Delete this task: `+a(o.task.id)+` ? `,1)]),_:1}),n(c(d),null,{default:t(()=>[s(` You are about to delete a task with the ID `+a(o.task.id)+`. This action cannot be undone. `,1)]),_:1})]),_:1}),n(c(f),null,{default:t(()=>[n(c(h),{"as-child":``},{default:t(()=>[n(g,{variant:`outline`},{default:t(()=>[...l[0]||=[s(` Cancel `,-1)]]),_:1})]),_:1}),n(c(h),{"as-child":``},{default:t(()=>[n(g,{variant:`destructive`,onClick:_},{default:t(()=>[...l[1]||=[s(` Delete `,-1)]]),_:1})]),_:1})]),_:1})])}}});export{g as default};

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
import{t as e}from"./task-resource-dialog-8MJRe8qY.js";import"./Teleport-qOjHMYM8.js";import"./button-BTKRNUhQ.js";import"./modal-DKtIxxgh.js";export{e as default};

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
import{I as e,Q as t,at as n,b as r,g as i,h as a,wt as o,x as s,y as c,yt as l}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{T as u,o as d}from"./dist-3yfE1dPa.js";import{$ as f,I as p,L as m,R as h}from"./index-BpHHjIYv.js";import{n as g}from"./button-BTKRNUhQ.js";import{i as _,n as v,r as y,t as b}from"./DropdownMenuTrigger-Dmk4lbKz.js";import{n as x,t as S}from"./DropdownMenuLabel-Bls_J4kr.js";import{n as C,t as w}from"./DropdownMenuRadioItem-QlCzvFJ2.js";var T=u(`moon`,[[`path`,{d:`M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401`,key:`kfwtm`}]]),E=u(`sun-moon`,[[`path`,{d:`M12 2v2`,key:`tus03m`}],[`path`,{d:`M14.837 16.385a6 6 0 1 1-7.223-7.222c.624-.147.97.66.715 1.248a4 4 0 0 0 5.26 5.259c.589-.255 1.396.09 1.248.715`,key:`xlf6rm`}],[`path`,{d:`M16 12a4 4 0 0 0-4-4`,key:`6vsxu`}],[`path`,{d:`m19 5-1.256 1.256`,key:`1yg6a6`}],[`path`,{d:`M20 12h2`,key:`1q8mjw`}]]),D=u(`sun`,[[`circle`,{cx:`12`,cy:`12`,r:`4`,key:`4exip2`}],[`path`,{d:`M12 2v2`,key:`tus03m`}],[`path`,{d:`M12 20v2`,key:`1lh1kg`}],[`path`,{d:`m4.93 4.93 1.41 1.41`,key:`149t6j`}],[`path`,{d:`m17.66 17.66 1.41 1.41`,key:`ptbguv`}],[`path`,{d:`M2 12h2`,key:`1t8f8n`}],[`path`,{d:`M20 12h2`,key:`1q8mjw`}],[`path`,{d:`m6.34 17.66-1.41 1.41`,key:`1m8zz5`}],[`path`,{d:`m19.07 4.93-1.41 1.41`,key:`1shlcs`}]]),O=s({__name:`language-change`,setup(s){let{locale:u}=h();function d(){u.value=`en`,m.value=`en`}function v(e){if(typeof e!=`string`||!p.has(e)){d();return}u.value=e,m.value=e}return(s,d)=>{let p=g,m=b,h=S,T=x,E=w,D=C,O=y,k=_;return e(),i(k,null,{default:t(()=>[r(m,{"as-child":``},{default:t(()=>[r(p,{variant:`outline`},{default:t(()=>[r(l(f),{icon:`mdi:translate`,class:`mr-2`}),c(` `+o(s.$t(`language`)),1)]),_:1})]),_:1}),r(O,null,{default:t(()=>[r(h,null,{default:t(()=>[c(o(s.$t(`changeLanguage`)),1)]),_:1}),r(T),r(D,{modelValue:l(u),"onUpdate:modelValue":[d[0]||=e=>n(u)?u.value=e:null,v]},{default:t(()=>[r(E,{value:`en`},{default:t(()=>[r(l(f),{icon:`flag:us-4x3`}),d[1]||=a(`span`,{class:`ml-2`},`English`,-1)]),_:1}),r(E,{value:`zh`},{default:t(()=>[r(l(f),{icon:`flag:cn-4x3`}),d[2]||=a(`span`,{class:`ml-2`},`中文`,-1)]),_:1})]),_:1},8,[`modelValue`])]),_:1})]),_:1})}}}),k=s({__name:`toggle-theme`,setup(n){let o=d();return(n,s)=>{let u=g,d=b,f=v,p=y,m=_;return e(),i(m,null,{default:t(()=>[r(d,{"as-child":``},{default:t(()=>[r(u,{variant:`outline`,size:`icon`},{default:t(()=>[r(l(T),{class:`rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0`}),r(l(D),{class:`absolute rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100`}),s[3]||=a(`span`,{class:`sr-only`},`Toggle theme`,-1)]),_:1})]),_:1}),r(p,{align:`end`},{default:t(()=>[r(f,{onClick:s[0]||=e=>o.value=`light`},{default:t(()=>[r(l(D)),s[4]||=c(` Light `,-1)]),_:1}),r(f,{onClick:s[1]||=e=>o.value=`dark`},{default:t(()=>[r(l(T)),s[5]||=c(` Dark `,-1)]),_:1}),r(f,{onClick:s[2]||=e=>o.value=`auto`},{default:t(()=>[r(l(E)),s[6]||=c(` System `,-1)]),_:1})]),_:1})]),_:1})}}});export{T as a,E as i,O as n,D as r,k as t};

View File

@@ -1 +0,0 @@
import{ut as e}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{G as t,M as n,P as r}from"./index-BpHHjIYv.js";import{t as i}from"./monisuo-admin.api-DyXM8BcP.js";function a(){let a=r(),o=n(),{isLogin:s,adminInfo:c}=t(o),l=e(!1),u=e(null),d=i();function f(){o.logout(),a.push({path:`/auth/sign-in`})}function p(){a.push({path:`/monisuo/dashboard`})}async function m(e,t){l.value=!0,u.value=null;try{let n=await d.mutateAsync({username:e,password:t});if(console.log(`Login result:`,n),n.code===`0000`&&n.data){console.log(`Setting token and adminInfo...`),o.setToken(n.data.token),o.setAdminInfo(n.data.adminInfo),console.log(`isLogin after setToken:`,o.isLogin);let e=a.currentRoute.value.query.redirect;console.log(`Redirecting to:`,e||`/monisuo/dashboard`),!e||e.startsWith(`//`)?p():a.push(e)}else console.log(`Login failed:`,n.code,n.msg),u.value=n.msg||`登录失败`}catch(e){console.error(`Login error:`,e),u.value=e.response?.data?.msg||`网络错误,请稍后重试`}finally{l.value=!1}}return{loading:l,error:u,isLogin:s,adminInfo:c,logout:f,login:m}}export{a as t};

View File

@@ -1 +0,0 @@
import{ut as e}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{T as t}from"./dist-3yfE1dPa.js";var n=t(`coins`,[[`path`,{d:`M13.744 17.736a6 6 0 1 1-7.48-7.48`,key:`bq4yh3`}],[`path`,{d:`M15 6h1v4`,key:`11y1tn`}],[`path`,{d:`m6.134 14.768.866-.5 2 3.464`,key:`17snzx`}],[`circle`,{cx:`16`,cy:`8`,r:`6`,key:`14bfc9`}]]),r=t(`dollar-sign`,[[`line`,{x1:`12`,x2:`12`,y1:`2`,y2:`22`,key:`7eqyqh`}],[`path`,{d:`M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6`,key:`1b0p4s`}]]),i=t(`palette`,[[`path`,{d:`M12 22a1 1 0 0 1 0-20 10 9 0 0 1 10 9 5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z`,key:`e79jfc`}],[`circle`,{cx:`13.5`,cy:`6.5`,r:`.5`,fill:`currentColor`,key:`1okk4w`}],[`circle`,{cx:`17.5`,cy:`10.5`,r:`.5`,fill:`currentColor`,key:`f64h9f`}],[`circle`,{cx:`6.5`,cy:`12.5`,r:`.5`,fill:`currentColor`,key:`qy21gx`}],[`circle`,{cx:`8.5`,cy:`7.5`,r:`.5`,fill:`currentColor`,key:`fotxhn`}]]),a=t(`receipt`,[[`path`,{d:`M12 17V7`,key:`pyj7ub`}],[`path`,{d:`M16 8h-6a2 2 0 0 0 0 4h4a2 2 0 0 1 0 4H8`,key:`1elt7d`}],[`path`,{d:`M4 3a1 1 0 0 1 1-1 1.3 1.3 0 0 1 .7.2l.933.6a1.3 1.3 0 0 0 1.4 0l.934-.6a1.3 1.3 0 0 1 1.4 0l.933.6a1.3 1.3 0 0 0 1.4 0l.933-.6a1.3 1.3 0 0 1 1.4 0l.934.6a1.3 1.3 0 0 0 1.4 0l.933-.6A1.3 1.3 0 0 1 19 2a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1 1.3 1.3 0 0 1-.7-.2l-.933-.6a1.3 1.3 0 0 0-1.4 0l-.934.6a1.3 1.3 0 0 1-1.4 0l-.933-.6a1.3 1.3 0 0 0-1.4 0l-.933.6a1.3 1.3 0 0 1-1.4 0l-.934-.6a1.3 1.3 0 0 0-1.4 0l-.933.6a1.3 1.3 0 0 1-.7.2 1 1 0 0 1-1-1z`,key:`ycz6yz`}]]),o=t(`settings`,[[`path`,{d:`M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915`,key:`1i5ecw`}],[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}]]),s=t(`trending-up`,[[`path`,{d:`M16 7h6v6`,key:`box55l`}],[`path`,{d:`m22 7-8.5 8.5-5-5L2 17`,key:`1t1m79`}]]),c=t(`users`,[[`path`,{d:`M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2`,key:`1yyitq`}],[`path`,{d:`M16 3.128a4 4 0 0 1 0 7.744`,key:`16gr8j`}],[`path`,{d:`M22 21v-2a4 4 0 0 0-3-3.87`,key:`kshegd`}],[`circle`,{cx:`9`,cy:`7`,r:`4`,key:`nufk8`}]]);function l(){let t=[{title:`外观设置`,url:`/settings/appearance`,icon:i}];return{navData:e([{title:`Monisuo 管理`,items:[{title:`数据看板`,url:`/monisuo/dashboard`,icon:r},{title:`用户管理`,url:`/monisuo/users`,icon:c},{title:`币种管理`,url:`/monisuo/coins`,icon:n},{title:`订单审批`,url:`/monisuo/orders`,icon:a},{title:`业务分析`,url:`/monisuo/analytics`,icon:s}]},{title:`Other`,items:[{title:`Settings`,icon:o,items:t}]}]),otherPages:e([]),settingsNavItems:t}}export{l as t};

View File

@@ -1 +0,0 @@
import{F as e,S as t,m as n,ut as r,vt as i}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{i as a}from"./dist-3yfE1dPa.js";function o(){let o=t(),s=r(),c=n(()=>l());e(()=>{c.value!==l()&&i(s)});function l(){return s.value&&`$el`in s.value&&[`#text`,`#comment`].includes(s.value.$el.nodeName)?s.value.$el.nextElementSibling:a(s)}let u=Object.assign({},o.exposed),d={};for(let e in o.props)Object.defineProperty(d,e,{enumerable:!0,configurable:!0,get:()=>o.props[e]});if(Object.keys(u).length>0)for(let e in u)Object.defineProperty(d,e,{enumerable:!0,configurable:!0,get:()=>u[e]});Object.defineProperty(d,`$el`,{enumerable:!0,configurable:!0,get:()=>o.vnode.el}),o.exposed=d;function f(e){if(s.value=e,e&&(Object.defineProperty(d,`$el`,{enumerable:!0,configurable:!0,get:()=>e instanceof Element?e:e.$el}),!(e instanceof Element)&&!Object.prototype.hasOwnProperty.call(e,`$el`))){let t=e.$.exposed,n=Object.assign({},d);for(let e in t)Object.defineProperty(n,e,{enumerable:!0,configurable:!0,get:()=>t[e]});o.exposed=n}}return{forwardRef:f,currentRef:s,currentElement:c}}export{o as t};

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
import{I as e,Q as t,b as n,v as r,w as i,wt as a,x as o,y as s,yt as c}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{n as l}from"./lib-CC9cpJ8Y.js";import"./Teleport-qOjHMYM8.js";import{n as u}from"./button-BTKRNUhQ.js";import{a as d,i as f,n as p,r as m,s as h}from"./modal-DKtIxxgh.js";var g=o({__name:`user-delete`,props:{user:{}},emits:[`remove`],setup(o,{emit:g}){let _=g;function v(){l(`The following task has been deleted:`,{description:i(`pre`,{class:`mt-2 w-[340px] rounded-md bg-slate-950 p-4`},i(`code`,{class:`text-white`},JSON.stringify(o.user,null,2)))}),_(`remove`)}return(i,l)=>{let g=u;return e(),r(`div`,null,[n(c(m),null,{default:t(()=>[n(c(p),null,{default:t(()=>[s(` Delete this user: `+a(o.user.username)+` ? `,1)]),_:1}),n(c(d),null,{default:t(()=>[s(` You are about to delete a user with the ID `+a(o.user.id)+`. This action cannot be undone. `,1)]),_:1})]),_:1}),n(c(f),null,{default:t(()=>[n(c(h),{"as-child":``},{default:t(()=>[n(g,{variant:`outline`},{default:t(()=>[...l[0]||=[s(` Cancel `,-1)]]),_:1})]),_:1}),n(c(h),{"as-child":``},{default:t(()=>[n(g,{variant:`destructive`,onClick:v},{default:t(()=>[...l[1]||=[s(` Delete `,-1)]]),_:1})]),_:1})]),_:1})])}}});export{g as default};

View File

@@ -1 +0,0 @@
import"./Teleport-qOjHMYM8.js";import"./button-BTKRNUhQ.js";import"./modal-DKtIxxgh.js";import{t as e}from"./user-resource-p1iwSw42.js";export{e as default};

View File

@@ -1 +0,0 @@
import{A as e,C as t,I as n,Q as r,R as i,St as a,b as o,ct as s,h as c,l,m as u,v as d,w as f,wt as p,x as m,y as h,yt as g}from"./vue.runtime.esm-bundler-DS0mm12S.js";import{a as _,i as v,n as y,r as b,t as x}from"./SelectValue-By3tfEiu.js";import{n as S}from"./lib-CC9cpJ8Y.js";import{c as C,d as w,l as T,r as E,s as D,u as O}from"./index-BpHHjIYv.js";import{n as k}from"./button-BTKRNUhQ.js";import{a as A,n as j,r as M}from"./modal-DKtIxxgh.js";import{a as N,c as P,i as F,l as I,n as L,r as R,s as z,t as B}from"./vee-validate-zod-DAPvk_fs.js";import{t as V}from"./Input-DOTs5aTB.js";var H=D([`active`,`inactive`,`invited`,`suspended`]),U=D([`superadmin`,`admin`,`cashier`,`manager`]);C(O({id:w(),firstName:w(),lastName:w(),username:w(),email:w(),phoneNumber:w(),status:H,role:U,createdAt:E(),updatedAt:E()}));var W=O({id:w().optional(),firstName:w().min(1),lastName:w().min(1),username:w().min(1),email:T().min(1),phoneNumber:w().min(1),status:H,role:U}),G={class:`max-h-[500px] overflow-y-auto`},K=m({__name:`user-form`,props:{user:{}},emits:[`close`],setup(u,{emit:m}){let C=m,w=[`superadmin`,`admin`,`cashier`,`manager`],T=[`active`,`inactive`,`invited`,`suspended`],E=s({firstName:u.user?.firstName||``,lastName:u.user?.lastName||``,username:u.user?.username||``,email:u.user?.email||``,phoneNumber:u.user?.phoneNumber||``,status:u.user?.status||`active`,role:u.user?.role||`cashier`}),{handleSubmit:D}=P({validationSchema:B(W),initialValues:E}),O=D(e=>{let t={...e};u.user&&(t.id=u.user.id),S(`You submitted the following values:`,{description:f(`pre`,{class:`mt-2 w-[340px] rounded-md bg-slate-950 p-4`},f(`code`,{class:`text-white`},JSON.stringify(t,null,2)))}),C(`close`)});return(s,u)=>(n(),d(`div`,G,[c(`form`,{class:`space-y-8`,onSubmit:u[0]||=(...e)=>g(O)&&g(O)(...e)},[o(g(z),{name:`firstName`},{default:r(({componentField:t})=>[o(g(F),null,{default:r(()=>[o(g(R),null,{default:r(()=>[...u[1]||=[h(`First Name`,-1)]]),_:1}),o(g(N),null,{default:r(()=>[o(g(V),e({type:`text`},t),null,16)]),_:2},1024),o(g(L))]),_:2},1024)]),_:1}),o(g(z),{name:`lastName`},{default:r(({componentField:t})=>[o(g(F),null,{default:r(()=>[o(g(R),null,{default:r(()=>[...u[2]||=[h(`Last Name`,-1)]]),_:1}),o(g(N),null,{default:r(()=>[o(g(V),e({type:`text`},t),null,16)]),_:2},1024),o(g(L))]),_:2},1024)]),_:1}),o(g(z),{name:`username`},{default:r(({componentField:t})=>[o(g(F),null,{default:r(()=>[o(g(R),null,{default:r(()=>[...u[3]||=[h(`User Name`,-1)]]),_:1}),o(g(N),null,{default:r(()=>[o(g(V),e({type:`text`},t),null,16)]),_:2},1024),o(g(L))]),_:2},1024)]),_:1}),o(g(z),{name:`email`},{default:r(({componentField:t})=>[o(g(F),null,{default:r(()=>[o(g(R),null,{default:r(()=>[...u[4]||=[h(`Email address`,-1)]]),_:1}),o(g(N),null,{default:r(()=>[o(g(V),e({type:`text`},t),null,16)]),_:2},1024),o(g(L))]),_:2},1024)]),_:1}),o(g(z),{name:`phoneNumber`},{default:r(({componentField:t})=>[o(g(F),null,{default:r(()=>[o(g(R),null,{default:r(()=>[...u[5]||=[h(`Phone Number`,-1)]]),_:1}),o(g(N),null,{default:r(()=>[o(g(V),e({type:`text`},t),null,16)]),_:2},1024),o(g(L))]),_:2},1024)]),_:1}),o(g(z),{name:`status`},{default:r(({componentField:e})=>[o(g(F),null,{default:r(()=>[o(g(R),null,{default:r(()=>[...u[6]||=[h(`Status`,-1)]]),_:1}),o(g(N),null,{default:r(()=>[o(g(_),a(t(e)),{default:r(()=>[o(g(N),null,{default:r(()=>[o(g(y),{class:`w-full`},{default:r(()=>[o(g(x),{placeholder:`Select a status`})]),_:1})]),_:1}),o(g(v),null,{default:r(()=>[o(g(I),null,{default:r(()=>[(n(),d(l,null,i(T,e=>o(g(b),{key:e,value:e},{default:r(()=>[h(p(e),1)]),_:2},1032,[`value`])),64))]),_:1})]),_:1})]),_:1},16)]),_:2},1024),o(g(L))]),_:2},1024)]),_:1}),o(g(z),{name:`role`},{default:r(({componentField:e})=>[o(g(F),null,{default:r(()=>[o(g(R),null,{default:r(()=>[...u[7]||=[h(`Role`,-1)]]),_:1}),o(g(N),null,{default:r(()=>[o(g(_),a(t(e)),{default:r(()=>[o(g(N),null,{default:r(()=>[o(g(y),{class:`w-full`},{default:r(()=>[o(g(x),{placeholder:`Select a role`})]),_:1})]),_:1}),o(g(v),null,{default:r(()=>[o(g(I),null,{default:r(()=>[(n(),d(l,null,i(w,e=>o(g(b),{key:e,value:e},{default:r(()=>[h(p(e),1)]),_:2},1032,[`value`])),64))]),_:1})]),_:1})]),_:1},16)]),_:2},1024),o(g(L))]),_:2},1024)]),_:1}),o(g(k),{type:`submit`,class:`w-full`},{default:r(()=>[...u[8]||=[h(` SaveChanges `,-1)]]),_:1})],32)]))}}),q=m({__name:`user-resource`,props:{user:{}},emits:[`close`],setup(e){let t=e,i=u(()=>t.user),a=u(()=>i.value?.id?`Edit User`:`New User`),s=u(()=>i.value?.id?`Edit user ${i.value.username}`:`Create new user`);return(e,t)=>(n(),d(`div`,null,[o(g(M),null,{default:r(()=>[o(g(j),null,{default:r(()=>[h(p(g(a)),1)]),_:1}),o(g(A),null,{default:r(()=>[h(p(g(s)),1)]),_:1})]),_:1}),o(K,{user:g(i),onClose:t[0]||=t=>e.$emit(`close`)},null,8,[`user`])]))}});export{q as t};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,26 +1,27 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" media="(prefers-color-scheme: dark)" href="/logo.svg" />
<link rel="icon" type="image/svg+xml" media="(prefers-color-scheme: light)" href="/logo-black.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>shadcn-vue-admin</title>
<meta
name="description"
content="Admin Dashboard UI crafted with Shadcn-vue, Vue3 and Vite. Built with responsiveness and accessibility in mind."
/>
<meta
name="keywords"
content="vue,vue-router,vite,typescript,tailwindcss,shadcn-vue,tanstack-vue-query,tanstack-table,eslint,pinia,pnpm"
/>
<script type="module" crossorigin src="/assets/index-BpHHjIYv.js"></script>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" media="(prefers-color-scheme: dark)" href="/logo.svg" />
<link rel="icon" type="image/svg+xml" media="(prefers-color-scheme: light)" href="/logo-black.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>shadcn-vue-admin</title>
<meta
name="description"
content="Admin Dashboard UI crafted with Shadcn-vue, Vue3 and Vite. Built with responsiveness and accessibility in mind."
/>
<meta
name="keywords"
content="vue,vue-router,vite,typescript,tailwindcss,shadcn-vue,tanstack-vue-query,tanstack-table,eslint,pinia,pnpm"
/>
<script type="module" crossorigin src="/assets/index-axPHP3AB.js"></script>
<link rel="modulepreload" crossorigin href="/assets/vue.runtime.esm-bundler-DS0mm12S.js">
<link rel="modulepreload" crossorigin href="/assets/dist-3yfE1dPa.js">
<link rel="modulepreload" crossorigin href="/assets/lib-CC9cpJ8Y.js">
<link rel="modulepreload" crossorigin href="/assets/zod-B9xT8GrA.js">
<link rel="stylesheet" crossorigin href="/assets/index-DzGkD_L8.css">
</head>
<body>
<div id="app"></div>
</body>
</html>
</head>
<body>
<div id="app"></div>
</body>

View File

@@ -1,10 +1,14 @@
<script setup lang="ts">
import {
ChevronsUpDown,
KeyRound,
LogOut,
UserRoundCog,
} from 'lucide-vue-next'
import { toast } from 'vue-sonner'
import { useChangePasswordMutation } from '@/services/api/monisuo-admin.api'
import { useSidebar } from '@/components/ui/sidebar'
import type { User } from './types'
@@ -15,6 +19,40 @@ const { user } = defineProps<
const { logout } = useAuth()
const { isMobile, open } = useSidebar()
const changePasswordMutation = useChangePasswordMutation()
const showPasswordDialog = ref(false)
const passwordForm = ref({ oldPassword: '', newPassword: '', confirmPassword: '' })
function openPasswordDialog() {
passwordForm.value = { oldPassword: '', newPassword: '', confirmPassword: '' }
showPasswordDialog.value = true
}
async function handleChangePassword() {
const { oldPassword, newPassword, confirmPassword } = passwordForm.value
if (!oldPassword || !newPassword) {
toast.error('请填写完整')
return
}
if (newPassword.length < 4) {
toast.error('新密码至少4位')
return
}
if (newPassword !== confirmPassword) {
toast.error('两次密码不一致')
return
}
try {
await changePasswordMutation.mutateAsync({ oldPassword, newPassword })
toast.success('密码修改成功,请重新登录')
showPasswordDialog.value = false
logout()
}
catch (e: any) {
toast.error(e.message || e.response?.data?.msg || '修改失败')
}
}
</script>
<template>
@@ -66,6 +104,10 @@ const { isMobile, open } = useSidebar()
<UserRoundCog />
设置
</UiDropdownMenuItem>
<UiDropdownMenuItem @click="openPasswordDialog">
<KeyRound />
修改密码
</UiDropdownMenuItem>
</UiDropdownMenuGroup>
<UiDropdownMenuSeparator />
@@ -77,4 +119,36 @@ const { isMobile, open } = useSidebar()
</UiDropdownMenu>
</UiSidebarMenuItem>
</UiSidebarMenu>
<!-- 修改密码弹窗 -->
<UiDialog v-model:open="showPasswordDialog">
<UiDialogContent class="max-w-md">
<UiDialogHeader>
<UiDialogTitle>修改密码</UiDialogTitle>
</UiDialogHeader>
<div class="grid gap-4 py-4">
<div class="grid gap-2">
<UiLabel>旧密码</UiLabel>
<UiInput v-model="passwordForm.oldPassword" type="password" placeholder="请输入旧密码" />
</div>
<div class="grid gap-2">
<UiLabel>新密码</UiLabel>
<UiInput v-model="passwordForm.newPassword" type="password" placeholder="至少4位" />
</div>
<div class="grid gap-2">
<UiLabel>确认新密码</UiLabel>
<UiInput v-model="passwordForm.confirmPassword" type="password" placeholder="再次输入新密码" @keyup.enter="handleChangePassword" />
</div>
</div>
<UiDialogFooter>
<UiButton variant="outline" @click="showPasswordDialog = false">
取消
</UiButton>
<UiButton :disabled="changePasswordMutation.isPending.value" @click="handleChangePassword">
<UiSpinner v-if="changePasswordMutation.isPending.value" class="mr-2" />
确认修改
</UiButton>
</UiDialogFooter>
</UiDialogContent>
</UiDialog>
</template>

View File

@@ -1,10 +1,13 @@
import { storeToRefs } from 'pinia'
import { useQueryClient } from '@tanstack/vue-query'
import { useAdminLoginMutation } from '@/services/api/monisuo-admin.api'
import { useAuthStore } from '@/stores/auth'
export function useAuth() {
const router = useRouter()
const queryClient = useQueryClient()
const authStore = useAuthStore()
const { isLogin, adminInfo } = storeToRefs(authStore)
@@ -15,6 +18,7 @@ export function useAuth() {
function logout() {
authStore.logout()
queryClient.clear()
router.push({ path: '/auth/sign-in' })
}
@@ -52,7 +56,7 @@ export function useAuth() {
}
catch (e: any) {
console.error('Login error:', e)
error.value = e.response?.data?.msg || '网络错误,请稍后重试'
error.value = e.message || e.response?.data?.msg || '网络错误,请稍后重试'
}
finally {
loading.value = false

View File

@@ -22,6 +22,10 @@ export function useAxios() {
})
axiosInstance.interceptors.response.use((response) => {
const data = response.data as any
if (data && data.code && data.code !== '0000') {
return Promise.reject(new Error(data.msg || '请求失败'))
}
return response
}, (error: AxiosError) => {
if (error.response?.status === 401) {

View File

@@ -1,21 +1,28 @@
import { Coins, DollarSign, Palette, Receipt, Settings, TrendingUp, Users } from 'lucide-vue-next'
import { CircleDollarSign, Coins, DollarSign, Palette, Receipt, Settings, ShieldCheck, TrendingUp, Users } from 'lucide-vue-next'
import type { NavGroup } from '@/components/app-sidebar/types'
import { useAuthStore } from '@/stores/auth'
export function useSidebar() {
const authStore = useAuthStore()
const role = computed(() => authStore.adminInfo?.role ?? 2)
const isSuperAdmin = computed(() => role.value === 1)
const settingsNavItems = [
{ title: '外观设置', url: '/settings/appearance', icon: Palette },
]
const navData = ref<NavGroup[]>([
const allNavItems: NavGroup[] = [
{
title: 'Monisuo 管理',
items: [
{ title: '数据看板', url: '/monisuo/dashboard', icon: DollarSign },
{ title: '用户管理', url: '/monisuo/users', icon: Users },
{ title: '币种管理', url: '/monisuo/coins', icon: Coins },
{ title: '订单审批', url: '/monisuo/orders', icon: Receipt },
{ title: '业务分析', url: '/monisuo/analytics', icon: TrendingUp },
{ title: '数据看板', url: '/monisuo/dashboard', icon: DollarSign, roles: [1] },
{ title: '用户管理', url: '/monisuo/users', icon: Users, roles: [1] },
{ title: '币种管理', url: '/monisuo/coins', icon: Coins, roles: [1] },
{ title: '订单审批', url: '/monisuo/orders', icon: Receipt, roles: [1, 2] },
{ title: '财务审批', url: '/monisuo/finance-orders', icon: CircleDollarSign, roles: [1, 3] },
{ title: '业务分析', url: '/monisuo/analytics', icon: TrendingUp, roles: [1] },
{ title: '管理员管理', url: '/monisuo/admins', icon: ShieldCheck, roles: [1] },
],
},
{
@@ -24,7 +31,19 @@ export function useSidebar() {
{ title: 'Settings', icon: Settings, items: settingsNavItems },
],
},
])
]
const navData = computed<NavGroup[]>(() => {
return allNavItems.map(group => ({
title: group.title,
items: group.items.filter((item) => {
const roles = (item as any).roles as number[] | undefined
if (!roles)
return true
return roles.includes(role.value)
}),
})).filter(group => group.items.length > 0)
})
const otherPages = ref<NavGroup[]>([])
@@ -32,5 +51,6 @@ export function useSidebar() {
navData,
otherPages,
settingsNavItems,
isSuperAdmin,
}
}

View File

@@ -19,6 +19,8 @@ const showEditDialog = ref(false)
const showPriceDialog = ref(false)
const priceInput = ref<number>(0)
const editingCode = ref('')
const editingInitialPrice = ref<number | null>(null)
const editingCurrentPrice = ref<number>(0)
// 表单验证
const formErrors = ref<{ code?: string, name?: string }>({})
@@ -60,12 +62,14 @@ async function saveCoin() {
refetch()
}
catch (e: any) {
toast.error(e.response?.data?.msg || '操作失败')
toast.error(e.message || e.response?.data?.msg || '操作失败')
}
}
function openPriceDialog(coin: Coin) {
editingCode.value = coin.code
editingInitialPrice.value = coin.initialPrice ?? null
editingCurrentPrice.value = coin.price
priceInput.value = coin.price
showPriceDialog.value = true
}
@@ -83,7 +87,7 @@ async function updatePrice() {
refetch()
}
catch (e: any) {
toast.error(e.response?.data?.msg || '操作失败')
toast.error(e.message || e.response?.data?.msg || '操作失败')
}
}
@@ -96,7 +100,7 @@ async function toggleStatus(coin: Coin) {
toast.success(`${action} ${coin.code}`)
}
catch (e: any) {
toast.error(e.response?.data?.msg || `${action}失败`)
toast.error(e.message || e.response?.data?.msg || `${action}失败`)
}
}
@@ -128,7 +132,10 @@ function formatPrice(price: number): string {
<UiTableHead>代码</UiTableHead>
<UiTableHead>名称</UiTableHead>
<UiTableHead class="text-right">
价格
初始价格
</UiTableHead>
<UiTableHead class="text-right">
当前价格
</UiTableHead>
<UiTableHead>价格类型</UiTableHead>
<UiTableHead>状态</UiTableHead>
@@ -139,12 +146,12 @@ function formatPrice(price: number): string {
</UiTableHeader>
<UiTableBody>
<UiTableRow v-if="isLoading">
<UiTableCell :col-span="7" class="text-center py-8">
<UiTableCell :col-span="8" class="text-center py-8">
<UiSpinner class="mx-auto" />
</UiTableCell>
</UiTableRow>
<UiTableRow v-else-if="coins.length === 0">
<UiTableCell :col-span="7" class="text-center py-8 text-muted-foreground">
<UiTableCell :col-span="8" class="text-center py-8 text-muted-foreground">
暂无数据
</UiTableCell>
</UiTableRow>
@@ -154,7 +161,10 @@ function formatPrice(price: number): string {
{{ coin.code }}
</UiTableCell>
<UiTableCell>{{ coin.name }}</UiTableCell>
<UiTableCell class="text-right font-mono">
<UiTableCell class="text-right font-mono text-muted-foreground">
{{ coin.initialPrice != null ? `$${formatPrice(coin.initialPrice)}` : '--' }}
</UiTableCell>
<UiTableCell class="text-right font-mono font-semibold text-green-600 dark:text-green-400">
${{ formatPrice(coin.price) }}
</UiTableCell>
<UiTableCell>
@@ -224,6 +234,9 @@ function formatPrice(price: number): string {
<div class="text-xl font-mono font-bold text-green-600 dark:text-green-400">
${{ formatPrice(coin.price) }}
</div>
<div v-if="coin.initialPrice != null" class="text-xs text-muted-foreground mt-1">
初始价格: ${{ formatPrice(coin.initialPrice) }}
</div>
</div>
<div class="mt-3 flex gap-2">
<UiButton size="sm" variant="outline" class="flex-1" @click="openEditDialog(coin)">
@@ -268,6 +281,7 @@ function formatPrice(price: number): string {
<UiInput
v-model="editingCoin.code"
placeholder="BTC"
:disabled="!!editingCoin.id"
:class="{ 'border-red-500': formErrors.code }"
@input="formErrors.code = undefined"
/>
@@ -289,7 +303,7 @@ function formatPrice(price: number): string {
</div>
<div class="grid gap-2">
<UiLabel>价格类型</UiLabel>
<UiSelect v-model="editingCoin.priceType">
<UiSelect v-model="editingCoin.priceType" :disabled="!!editingCoin.id">
<UiSelectTrigger>
<UiSelectValue />
</UiSelectTrigger>
@@ -303,10 +317,31 @@ function formatPrice(price: number): string {
</UiSelectContent>
</UiSelect>
</div>
<div v-if="editingCoin.priceType === 2" class="grid gap-2">
<!-- 新增时设置初始价格 -->
<div v-if="editingCoin.priceType === 2 && !editingCoin.id" class="grid gap-2">
<UiLabel>初始价格 ($)</UiLabel>
<UiInput v-model.number="editingCoin.price" type="number" step="0.000001" placeholder="0.00" />
</div>
<!-- 编辑时显示初始价格只读和当前价格只读 -->
<template v-if="editingCoin.priceType === 2 && editingCoin.id">
<div v-if="editingCoin.initialPrice != null" class="grid grid-cols-2 gap-4 text-sm">
<div>
<span class="text-muted-foreground">初始价格</span>
<div class="font-mono mt-1">
${{ formatPrice(editingCoin.initialPrice) }}
</div>
</div>
<div>
<span class="text-muted-foreground">当前价格</span>
<div class="font-mono mt-1 text-green-600 dark:text-green-400">
${{ formatPrice(editingCoin.price) }}
</div>
</div>
</div>
<div v-else class="text-sm text-muted-foreground bg-muted/50 rounded-md p-3">
尚未调价初始价格将在首次调价时锁定
</div>
</template>
</div>
<UiDialogFooter>
<UiButton variant="outline" @click="showEditDialog = false">
@@ -327,6 +362,23 @@ function formatPrice(price: number): string {
<UiDialogTitle>调整价格 - {{ editingCode }}</UiDialogTitle>
</UiDialogHeader>
<div class="grid gap-4 py-4">
<div v-if="editingInitialPrice != null" class="grid grid-cols-2 gap-4 text-sm">
<div>
<span class="text-muted-foreground">初始价格</span>
<div class="font-mono mt-1">
${{ formatPrice(editingInitialPrice) }}
</div>
</div>
<div>
<span class="text-muted-foreground">当前价格</span>
<div class="font-mono mt-1 text-green-600 dark:text-green-400">
${{ formatPrice(editingCurrentPrice) }}
</div>
</div>
</div>
<div v-else class="text-sm text-muted-foreground bg-muted/50 rounded-md p-3">
首次调价后当前价格将被锁定为初始价格之后只能调整当前价格
</div>
<div class="grid gap-2">
<UiLabel>新价格 ($)</UiLabel>
<UiInput

View File

@@ -5,9 +5,12 @@ import { toast } from 'vue-sonner'
import type { OrderFund } from '@/services/api/monisuo-admin.api'
import { BasicPage } from '@/components/global-layout'
import { useAuthStore } from '@/stores/auth'
import { useApproveOrderMutation, useGetAllOrdersQuery, useGetPendingOrdersQuery } from '@/services/api/monisuo-admin.api'
const pageNum = ref(1)
// 分离分页状态
const pendingPage = ref(1)
const allPage = ref(1)
const pageSize = ref(10)
const activeTab = ref('pending')
@@ -15,13 +18,16 @@ const activeTab = ref('pending')
const filterType = ref<number | string>('all')
const filterStatus = ref<number | string>('all')
// 是否已加载过全部订单
const allLoaded = ref(false)
const { data: pendingData, isLoading: pendingLoading, refetch: refetchPending } = useGetPendingOrdersQuery({
pageNum: pageNum.value,
pageNum: pendingPage.value,
pageSize: pageSize.value,
})
const { data: allData, isLoading: allLoading, refetch: refetchAll } = useGetAllOrdersQuery({
pageNum: pageNum.value,
pageNum: allPage.value,
pageSize: pageSize.value,
type: filterType.value === 'all' ? undefined : filterType.value as number,
status: filterStatus.value === 'all' ? undefined : filterStatus.value as number,
@@ -29,13 +35,24 @@ const { data: allData, isLoading: allLoading, refetch: refetchAll } = useGetAllO
const approveMutation = useApproveOrderMutation()
const authStore = useAuthStore()
const adminRole = computed(() => authStore.adminInfo?.role ?? 2)
const pendingOrders = computed(() => pendingData.value?.data?.list || [])
const pendingTotal = computed(() => pendingData.value?.data?.total || 0)
const allOrders = computed(() => allData.value?.data?.list || [])
const allTotal = computed(() => allData.value?.data?.total || 0)
const currentTotal = computed(() => activeTab.value === 'pending' ? pendingTotal.value : allTotal.value)
const totalPages = computed(() => Math.ceil(currentTotal.value / pageSize.value))
const pendingTotalPages = computed(() => Math.ceil(pendingTotal.value / pageSize.value))
const allTotalPages = computed(() => Math.ceil(allTotal.value / pageSize.value))
// 切换 tab 时懒加载全部订单
watch(activeTab, (tab) => {
if (tab === 'all' && !allLoaded.value) {
allLoaded.value = true
refetchAll()
}
})
const showApproveDialog = ref(false)
const showDetailDialog = ref(false)
@@ -74,32 +91,37 @@ async function handleApprove() {
toast.success(`订单已${action}`)
showApproveDialog.value = false
refetchPending()
refetchAll()
if (allLoaded.value) refetchAll()
}
catch (e: any) {
toast.error(e.response?.data?.msg || `${action}失败`)
toast.error(e.message || e.response?.data?.msg || `${action}失败`)
}
}
function handlePageChange(page: number) {
pageNum.value = page
refetchPending()
refetchAll()
if (activeTab.value === 'pending') {
pendingPage.value = page
refetchPending()
} else {
allPage.value = page
refetchAll()
}
}
function handlePageSizeChange(size: unknown) {
if (size === null || size === undefined)
return
pageSize.value = Number(size)
pageNum.value = 1
pendingPage.value = 1
allPage.value = 1
refetchPending()
refetchAll()
if (allLoaded.value) refetchAll()
}
function resetFilters() {
filterType.value = 'all'
filterStatus.value = 'all'
pageNum.value = 1
allPage.value = 1
refetchAll()
}
@@ -123,6 +145,7 @@ function getStatusVariant(order: OrderFund): 'default' | 'secondary' | 'destruct
// 提现
if (status === 1) return 'default' // 待审批
if (status === 2) return 'default' // 已完成
if (status === 5) return 'secondary' // 待财务审核
return 'destructive' // 已驳回/已取消
}
}
@@ -157,12 +180,14 @@ function getStatusText(order: OrderFund): string {
// 充值: 仅待确认(status=2)可审批
// 提现: 仅待审批(status=1)可审批
function canApprove(order: OrderFund): boolean {
const role = adminRole.value
if (order.type === 1) {
return order.status === 2 // 充值待确认
}
else {
return order.status === 1 // 提现待审批
}
if (role === 2) return order.status === 1 // 管理员: 提现待审批
if (role === 3) return order.status === 5 // 财务: 待财务审核
if (role === 1) return order.status === 1 || order.status === 5 // 超管
return false
}
// 复制到剪贴板
@@ -437,6 +462,9 @@ function copyToClipboard(text: string) {
<UiTableHead class="hidden xl:table-cell">
时间
</UiTableHead>
<UiTableHead class="hidden lg:table-cell">
审批人
</UiTableHead>
<UiTableHead class="hidden lg:table-cell">
备注
</UiTableHead>
@@ -447,12 +475,12 @@ function copyToClipboard(text: string) {
</UiTableHeader>
<UiTableBody>
<UiTableRow v-if="allLoading">
<UiTableCell :col-span="9" class="text-center py-8">
<UiTableCell :col-span="10" class="text-center py-8">
<UiSpinner class="mx-auto" />
</UiTableCell>
</UiTableRow>
<UiTableRow v-else-if="allOrders.length === 0">
<UiTableCell :col-span="9" class="text-center py-8 text-muted-foreground">
<UiTableCell :col-span="10" class="text-center py-8 text-muted-foreground">
暂无数据
</UiTableCell>
</UiTableRow>
@@ -488,6 +516,10 @@ function copyToClipboard(text: string) {
完成: {{ order.confirmTime }}
</div>
</UiTableCell>
<UiTableCell class="hidden lg:table-cell text-sm text-muted-foreground">
<div v-if="order.approveAdminName">{{ order.approveAdminName }}</div>
<span v-else>-</span>
</UiTableCell>
<UiTableCell class="hidden lg:table-cell text-sm text-muted-foreground max-w-[120px] truncate">
{{ order.rejectReason || order.adminRemark || '-' }}
</UiTableCell>
@@ -547,6 +579,9 @@ function copyToClipboard(text: string) {
<div v-if="order.confirmTime" class="text-xs text-muted-foreground">
完成: {{ order.confirmTime }}
</div>
<div v-if="order.approveAdminName" class="text-xs text-muted-foreground">
审批人: {{ order.approveAdminName }}
</div>
<div v-if="order.rejectReason || order.adminRemark" class="text-sm text-muted-foreground mt-1">
备注: {{ order.rejectReason || order.adminRemark }}
</div>
@@ -566,9 +601,9 @@ function copyToClipboard(text: string) {
</UiTabs>
<!-- 分页 -->
<div v-if="currentTotal > 0" class="flex flex-col sm:flex-row items-center justify-between gap-4 px-2">
<div v-if="(activeTab === 'pending' ? pendingTotal : allTotal) > 0" class="flex flex-col sm:flex-row items-center justify-between gap-4 px-2">
<div class="text-sm text-muted-foreground">
{{ currentTotal }} 条记录
{{ activeTab === 'pending' ? pendingTotal : allTotal }} 条记录
</div>
<div class="flex items-center gap-4">
<div class="flex items-center gap-2">
@@ -596,20 +631,20 @@ function copyToClipboard(text: string) {
variant="outline"
size="icon"
class="h-8 w-8"
:disabled="pageNum <= 1"
@click="handlePageChange(pageNum - 1)"
:disabled="(activeTab === 'pending' ? pendingPage : allPage) <= 1"
@click="handlePageChange((activeTab === 'pending' ? pendingPage : allPage) - 1)"
>
<Icon icon="lucide:chevron-left" class="size-4" />
</UiButton>
<span class="text-sm min-w-[80px] text-center">
{{ pageNum }} / {{ totalPages }}
{{ activeTab === 'pending' ? pendingPage : allPage }} / {{ activeTab === 'pending' ? pendingTotalPages : allTotalPages }}
</span>
<UiButton
variant="outline"
size="icon"
class="h-8 w-8"
:disabled="pageNum >= totalPages"
@click="handlePageChange(pageNum + 1)"
:disabled="(activeTab === 'pending' ? pendingPage : allPage) >= (activeTab === 'pending' ? pendingTotalPages : allTotalPages)"
@click="handlePageChange((activeTab === 'pending' ? pendingPage : allPage) + 1)"
>
<Icon icon="lucide:chevron-right" class="size-4" />
</UiButton>
@@ -665,6 +700,24 @@ function copyToClipboard(text: string) {
</UiBadge>
</div>
<!-- 手续费信息提现 -->
<template v-if="currentOrder.type === 2 && currentOrder.fee">
<div class="text-muted-foreground">
手续费(10%)
</div>
<div class="col-span-2 font-mono">
-${{ currentOrder.fee }}
</div>
</template>
<template v-if="currentOrder.type === 2 && currentOrder.receivableAmount">
<div class="text-muted-foreground">
应收款项
</div>
<div class="col-span-2 font-mono font-bold text-green-600">
${{ currentOrder.receivableAmount }}
</div>
</template>
<!-- 充值/提现地址 -->
<div class="text-muted-foreground">
{{ currentOrder.type === 1 ? '充值地址' : '提现地址' }}
@@ -704,6 +757,19 @@ function copyToClipboard(text: string) {
</div>
</template>
<!-- 财务审批人 -->
<template v-if="currentOrder.financeAdminName">
<div class="text-muted-foreground">
财务审批人
</div>
<div class="col-span-2">
{{ currentOrder.financeAdminName }}
<span v-if="currentOrder.financeApproveTime" class="text-xs text-muted-foreground ml-2">
{{ currentOrder.financeApproveTime }}
</span>
</div>
</template>
<!-- 管理员确认时间 -->
<template v-if="currentOrder.confirmTime">
<div class="text-muted-foreground">
@@ -714,6 +780,19 @@ function copyToClipboard(text: string) {
</div>
</template>
<!-- 审批人信息 -->
<template v-if="currentOrder.approveAdminName">
<div class="text-muted-foreground">
审批人
</div>
<div class="col-span-2">
{{ currentOrder.approveAdminName }}
<span v-if="currentOrder.approveTime" class="text-xs text-muted-foreground ml-2">
{{ currentOrder.approveTime }}
</span>
</div>
</template>
<template v-if="currentOrder.rejectReason">
<div class="text-muted-foreground text-red-500">
驳回原因

View File

@@ -44,7 +44,7 @@ async function toggleStatus(user: User) {
toast.success(`${action}用户 ${user.username}`)
}
catch (e: any) {
toast.error(e.response?.data?.msg || `${action}失败`)
toast.error(e.message || e.response?.data?.msg || `${action}失败`)
}
}

View File

@@ -76,7 +76,7 @@ async function saveWallet() {
refetch()
}
catch (e: any) {
toast.error(e.response?.data?.msg || '操作失败')
toast.error(e.message || e.response?.data?.msg || '操作失败')
}
}
@@ -89,7 +89,7 @@ async function setDefault(wallet: ColdWallet) {
toast.success(`已将 ${wallet.name} 设为默认`)
}
catch (e: any) {
toast.error(e.response?.data?.msg || '设置失败')
toast.error(e.message || e.response?.data?.msg || '设置失败')
}
}
@@ -99,7 +99,7 @@ async function toggleStatus(wallet: ColdWallet) {
toast.success(wallet.status === 1 ? '已禁用' : '已启用')
}
catch (e: any) {
toast.error(e.response?.data?.msg || '操作失败')
toast.error(e.message || e.response?.data?.msg || '操作失败')
}
}
@@ -112,7 +112,7 @@ async function deleteWallet(wallet: ColdWallet) {
toast.success('钱包已删除')
}
catch (e: any) {
toast.error(e.response?.data?.msg || '删除失败')
toast.error(e.message || e.response?.data?.msg || '删除失败')
}
}
</script>

View File

@@ -1,37 +1,72 @@
import type { Router } from 'vue-router'
import { storeToRefs } from 'pinia'
import pinia from '@/plugins/pinia/setup'
import { useAuthStore } from '@/stores/auth'
// 不需要认证的白名单路由
const WHITE_LIST = ['/auth/sign-in', '/auth/sign-up', '/auth/forgot-password']
export function authGuard(router: Router) {
router.beforeEach((to, _from) => {
// 仅超级管理员可访问的路由前缀
const SUPER_ADMIN_ONLY = ['/monisuo/dashboard', '/monisuo/users', '/monisuo/coins', '/monisuo/analytics', '/monisuo/admins']
export function setupAuthGuard(router: Router) {
router.beforeEach((to) => {
const authStore = useAuthStore(pinia)
const { isLogin } = storeToRefs(authStore)
const { isLogin, adminInfo } = storeToRefs(authStore)
// 检查是否在白名单中
const isInWhiteList = WHITE_LIST.some(path => to.path === path || to.path.startsWith(path + '/'))
console.log('[AuthGuard]', to.path, 'isInWhiteList:', isInWhiteList, 'isLogin:', unref(isLogin))
// 如果已登录且访问登录页,重定向到首页
if (unref(isLogin) && to.path === '/auth/sign-in') {
const role = unref(adminInfo)?.role
if (role === 2) {
return { path: '/monisuo/orders' }
}
if (role === 3) {
return { path: '/monisuo/finance-orders' }
}
return { name: '/monisuo/dashboard' }
}
// 如果未登录且不在白名单中,重定向到登录页
if (!unref(isLogin) && !isInWhiteList) {
console.log('[AuthGuard] Redirecting to login')
return {
name: '/auth/sign-in',
query: { redirect: to.fullPath },
}
}
// 已登录时检查角色权限
if (unref(isLogin) && !isInWhiteList) {
const role = unref(adminInfo)?.role
const isSuperAdmin = role === 1
if (!isSuperAdmin) {
const needsSuperAdmin = SUPER_ADMIN_ONLY.some(prefix => to.path.startsWith(prefix))
if (needsSuperAdmin) {
// 非超管尝试访问超管页面,根据角色重定向
if (role === 3) {
return { path: '/monisuo/finance-orders' }
}
return { path: '/monisuo/orders' }
}
// 财务角色(role=3)只能访问财务审批页面和设置
if (role === 3) {
const allowed = to.path.startsWith('/monisuo/finance-orders') || to.path.startsWith('/settings')
if (!allowed) {
return { path: '/monisuo/finance-orders' }
}
}
// 普通管理员(role=2)不能访问财务审批页面
if (role === 2 && to.path.startsWith('/monisuo/finance-orders')) {
return { path: '/monisuo/orders' }
}
}
}
return true
})
}

View File

@@ -2,11 +2,10 @@ import type { Router } from 'vue-router'
import nprogress from 'nprogress'
import { authGuard } from './auth-guard'
import { setupAuthGuard } from './auth-guard'
/**
* global router guard
* now only used for progress bar
*/
function setupCommonGuard(router: Router) {
router.beforeEach(() => {
@@ -21,5 +20,5 @@ function setupCommonGuard(router: Router) {
export function createRouterGuard(router: Router) {
setupCommonGuard(router)
authGuard(router)
setupAuthGuard(router)
}

View File

@@ -45,6 +45,7 @@ export interface Coin {
code: string
name: string
price: number
initialPrice?: number
priceType: number // 1: 实时 2: 手动
status: number
createTime: string
@@ -57,7 +58,9 @@ export interface OrderFund {
username: string
type: number // 1: 充值 2: 提现
amount: number
status: number // 充值: 1待付款 2待确认 3已完成 4已驳回 5已取消; 提现: 1待审批 2已完成 3已驳回 4已取消
fee?: number // 手续费
receivableAmount?: number // 应收款项
status: number // 充值: 1待付款 2待确认 3已完成 4已驳回 5已取消; 提现: 1待审批 2已完成 3已驳回 4已取消 5待财务审核
walletId?: number
walletAddress?: string
withdrawContact?: string
@@ -66,6 +69,12 @@ export interface OrderFund {
createTime: string
rejectReason?: string
adminRemark?: string
approveAdminId?: number
approveAdminName?: string
approveTime?: string
financeAdminId?: number
financeAdminName?: string
financeApproveTime?: string
}
export interface ColdWallet {
@@ -351,7 +360,91 @@ export function useToggleWalletStatusMutation() {
})
}
// ========== 分析相关 API ==========
// ========== 管理员管理 API ==========
export interface AdminRecord {
id: number
username: string
nickname: string
role: number
permissions?: string
isSystem?: number
status?: number
createTime?: string
}
export function useGetAdminListQuery() {
const { axiosInstance } = useAxios()
return useQuery<ApiResult<AdminRecord[]>, AxiosError>({
queryKey: ['useGetAdminListQuery'],
queryFn: async () => {
const response = await axiosInstance.get('/admin/admin/list')
return response.data
},
})
}
export function useCreateAdminMutation() {
const { axiosInstance } = useAxios()
const queryClient = useQueryClient()
return useMutation<ApiResult<{ id: number, username: string, role: number }>, AxiosError, { username: string, password: string, nickname?: string, role?: number }>({
mutationKey: ['useCreateAdminMutation'],
mutationFn: async (params) => {
const response = await axiosInstance.post('/admin/admin/create', params)
return response.data
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['useGetAdminListQuery'] })
},
})
}
export function useToggleAdminStatusMutation() {
const { axiosInstance } = useAxios()
const queryClient = useQueryClient()
return useMutation<ApiResult<void>, AxiosError, { id: number, status: number }>({
mutationKey: ['useToggleAdminStatusMutation'],
mutationFn: async (params) => {
const response = await axiosInstance.post('/admin/admin/status', params)
return response.data
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['useGetAdminListQuery'] })
},
})
}
export function usePromoteUserToAdminMutation() {
const { axiosInstance } = useAxios()
const queryClient = useQueryClient()
return useMutation<ApiResult<{ id: number, username: string, role: number }>, AxiosError, { username: string, password: string, nickname?: string }>({
mutationKey: ['usePromoteUserToAdminMutation'],
mutationFn: async (params) => {
const response = await axiosInstance.post('/admin/user/promote-admin', params)
return response.data
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['useGetAdminListQuery'] })
queryClient.invalidateQueries({ queryKey: ['useGetUserListQuery'] })
},
})
}
export function useChangePasswordMutation() {
const { axiosInstance } = useAxios()
return useMutation<ApiResult<void>, AxiosError, { oldPassword: string, newPassword: string }>({
mutationKey: ['useChangePasswordMutation'],
mutationFn: async (params) => {
const response = await axiosInstance.post('/admin/change-password', params)
return response.data
},
})
}
// 盈利分析
export function useGetProfitAnalysisQuery(range: string = 'month') {

View File

@@ -61,6 +61,13 @@ declare module 'vue-router/auto-routes' {
Record<never, never>,
| never
>,
'/monisuo/admins': RouteRecordInfo<
'/monisuo/admins',
'/monisuo/admins',
Record<never, never>,
Record<never, never>,
| never
>,
'/monisuo/analytics': RouteRecordInfo<
'/monisuo/analytics',
'/monisuo/analytics',
@@ -82,6 +89,13 @@ declare module 'vue-router/auto-routes' {
Record<never, never>,
| never
>,
'/monisuo/finance-orders': RouteRecordInfo<
'/monisuo/finance-orders',
'/monisuo/finance-orders',
Record<never, never>,
Record<never, never>,
| never
>,
'/monisuo/orders': RouteRecordInfo<
'/monisuo/orders',
'/monisuo/orders',
@@ -168,6 +182,12 @@ declare module 'vue-router/auto-routes' {
views:
| never
}
'src/pages/monisuo/admins.vue': {
routes:
| '/monisuo/admins'
views:
| never
}
'src/pages/monisuo/analytics.vue': {
routes:
| '/monisuo/analytics'
@@ -186,6 +206,12 @@ declare module 'vue-router/auto-routes' {
views:
| never
}
'src/pages/monisuo/finance-orders.vue': {
routes:
| '/monisuo/finance-orders'
views:
| never
}
'src/pages/monisuo/orders.vue': {
routes:
| '/monisuo/orders'