表格与页面样式调整
This commit is contained in:
@@ -14,6 +14,7 @@ import {
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog"
|
||||
import {
|
||||
Field,
|
||||
@@ -72,16 +73,11 @@ const addUserSchema = z
|
||||
export type AddUserFormValues = z.infer<typeof addUserSchema>
|
||||
|
||||
interface AddUserDialogProps {
|
||||
open: boolean
|
||||
onOpenChange: (open: boolean) => void
|
||||
onSuccess?: () => void
|
||||
}
|
||||
|
||||
export function AddUserDialog({
|
||||
open,
|
||||
onOpenChange,
|
||||
onSuccess,
|
||||
}: AddUserDialogProps) {
|
||||
export function AddUserDialog({ onSuccess }: AddUserDialogProps) {
|
||||
const [open, setOpen] = useState(false)
|
||||
const [isAdding, setIsAdding] = useState(false)
|
||||
const [discountList, setDiscountList] = useState<ProductDiscount[]>([])
|
||||
const [isLoadingDiscount, setIsLoadingDiscount] = useState(false)
|
||||
@@ -176,7 +172,7 @@ export function AddUserDialog({
|
||||
const result = await createCust(payload)
|
||||
if (result?.success) {
|
||||
toast.success("添加用户成功")
|
||||
onOpenChange(false)
|
||||
setOpen(false)
|
||||
resetAddForm()
|
||||
onSuccess?.()
|
||||
} else {
|
||||
@@ -194,11 +190,14 @@ export function AddUserDialog({
|
||||
if (!open) {
|
||||
resetAddForm()
|
||||
}
|
||||
onOpenChange(open)
|
||||
setOpen(open)
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={handleOpenChange}>
|
||||
<DialogTrigger asChild>
|
||||
<Button type="button">添加用户</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-w-3xl max-h-[90vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>添加用户</DialogTitle>
|
||||
@@ -396,7 +395,7 @@ export function AddUserDialog({
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
onClick={() => onOpenChange(false)}
|
||||
onClick={() => setOpen(false)}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog"
|
||||
import { Field, FieldError, FieldLabel } from "@/components/ui/field"
|
||||
import { Input } from "@/components/ui/input"
|
||||
@@ -30,18 +31,15 @@ const Schema = z.object({
|
||||
type FormValues = z.infer<typeof Schema>
|
||||
|
||||
interface UpdateDeductionDialogProps {
|
||||
open: boolean
|
||||
onOpenChange: (open: boolean) => void
|
||||
currentUser: User | null
|
||||
user: User
|
||||
onSuccess: () => void
|
||||
}
|
||||
|
||||
export function DeductionDialog({
|
||||
open,
|
||||
onOpenChange,
|
||||
currentUser,
|
||||
user,
|
||||
onSuccess,
|
||||
}: UpdateDeductionDialogProps) {
|
||||
const [open, setOpen] = useState(false)
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
|
||||
const {
|
||||
@@ -58,17 +56,16 @@ export function DeductionDialog({
|
||||
})
|
||||
|
||||
const onSubmit = async (data: FormValues) => {
|
||||
if (!currentUser) return
|
||||
setIsLoading(true)
|
||||
try {
|
||||
const result = await getDeduction({
|
||||
user_id: currentUser.id,
|
||||
user_id: user.id,
|
||||
amount: data.deduction,
|
||||
})
|
||||
|
||||
if (result.success) {
|
||||
toast.success("扣款成功")
|
||||
onOpenChange(false)
|
||||
setOpen(false)
|
||||
reset()
|
||||
onSuccess()
|
||||
} else {
|
||||
@@ -86,16 +83,19 @@ export function DeductionDialog({
|
||||
if (!open) {
|
||||
reset()
|
||||
}
|
||||
onOpenChange(open)
|
||||
setOpen(open)
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={handleOpenChange}>
|
||||
<DialogTrigger asChild>
|
||||
<Button size="sm">扣款</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>扣款</DialogTitle>
|
||||
<DialogDescription>
|
||||
扣减用户 {currentUser?.name || currentUser?.username} 的余额
|
||||
扣减用户 {user.name || user.username} 的余额
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog"
|
||||
import { Field, FieldError, FieldLabel } from "@/components/ui/field"
|
||||
import { Input } from "@/components/ui/input"
|
||||
@@ -30,18 +31,12 @@ const Schema = z.object({
|
||||
type FormValues = z.infer<typeof Schema>
|
||||
|
||||
interface UpdateDepositDialogProps {
|
||||
open: boolean
|
||||
onOpenChange: (open: boolean) => void
|
||||
currentUser: User | null
|
||||
user: User
|
||||
onSuccess: () => void
|
||||
}
|
||||
|
||||
export function DepositDialog({
|
||||
open,
|
||||
onOpenChange,
|
||||
currentUser,
|
||||
onSuccess,
|
||||
}: UpdateDepositDialogProps) {
|
||||
export function DepositDialog({ user, onSuccess }: UpdateDepositDialogProps) {
|
||||
const [open, setOpen] = useState(false)
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
|
||||
const {
|
||||
@@ -58,17 +53,16 @@ export function DepositDialog({
|
||||
})
|
||||
|
||||
const onSubmit = async (data: FormValues) => {
|
||||
if (!currentUser) return
|
||||
setIsLoading(true)
|
||||
try {
|
||||
const result = await getDeposit({
|
||||
user_id: currentUser.id,
|
||||
user_id: user.id,
|
||||
amount: data.deposit,
|
||||
})
|
||||
|
||||
if (result.success) {
|
||||
toast.success("充值成功")
|
||||
onOpenChange(false)
|
||||
setOpen(false)
|
||||
reset()
|
||||
onSuccess()
|
||||
} else {
|
||||
@@ -86,16 +80,19 @@ export function DepositDialog({
|
||||
if (!open) {
|
||||
reset()
|
||||
}
|
||||
onOpenChange(open)
|
||||
setOpen(open)
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={handleOpenChange}>
|
||||
<DialogTrigger asChild>
|
||||
<Button size="sm">充值</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>充值</DialogTitle>
|
||||
<DialogDescription>
|
||||
充值用户 {currentUser?.name || currentUser?.username} 的余额
|
||||
充值用户 {user?.name || user?.username} 的余额
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import { z } from "zod"
|
||||
import { getPageCusts } from "@/actions/cust"
|
||||
import { Auth } from "@/components/auth"
|
||||
import { DataTable, useDataTable } from "@/components/data-table"
|
||||
import { Page } from "@/components/page"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import {
|
||||
@@ -86,14 +87,7 @@ type FormValues = z.infer<typeof filterSchema>
|
||||
|
||||
export default function CustPage() {
|
||||
const [filters, setFilters] = useState<FilterValues>({})
|
||||
const [isAddDialogOpen, setIsAddDialogOpen] = useState(false)
|
||||
const [isEditDialogOpen, setIsEditDialogOpen] = useState(false)
|
||||
const [currentEditUser, setCurrentEditUser] = useState<User | null>(null)
|
||||
const [depositDialog, setDepositDialog] = useState(false)
|
||||
const [deposit, setDeposit] = useState<User | null>(null)
|
||||
const router = useRouter()
|
||||
const [deductionDialog, setDeductionDialog] = useState(false)
|
||||
const [deduction, setDeduction] = useState<User | null>(null)
|
||||
const { control, handleSubmit, reset } = useForm<FormValues>({
|
||||
resolver: zodResolver(filterSchema),
|
||||
defaultValues: {
|
||||
@@ -130,8 +124,8 @@ export default function CustPage() {
|
||||
}, [table])
|
||||
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<form onSubmit={onFilter} className="bg-white p-4">
|
||||
<Page>
|
||||
<form onSubmit={onFilter} className="bg-card p-4 rounded-lg">
|
||||
<div className="flex flex-wrap items-end gap-4">
|
||||
<Controller
|
||||
name="account"
|
||||
@@ -204,6 +198,7 @@ export default function CustPage() {
|
||||
</Field>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
name="created_at_start"
|
||||
control={control}
|
||||
@@ -237,9 +232,7 @@ export default function CustPage() {
|
||||
|
||||
<FieldGroup className="flex-row justify-start mt-4 gap-2">
|
||||
<Auth scope={ScopeUserWrite}>
|
||||
<Button type="button" onClick={() => setIsAddDialogOpen(true)}>
|
||||
添加用户
|
||||
</Button>
|
||||
<AddUserDialog onSuccess={refreshTable} />
|
||||
</Auth>
|
||||
<Button
|
||||
type="button"
|
||||
@@ -259,6 +252,7 @@ export default function CustPage() {
|
||||
<Suspense>
|
||||
<DataTable<User>
|
||||
{...table}
|
||||
classNames={{ root: "flex-auto overflow-hidden" }}
|
||||
columns={[
|
||||
{ header: "手机", accessorKey: "phone" },
|
||||
{
|
||||
@@ -371,39 +365,24 @@ export default function CustPage() {
|
||||
return (
|
||||
<div className="flex gap-2">
|
||||
<Auth scope={ScopeUserWriteBalanceInc}>
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setDeposit(user)
|
||||
setDepositDialog(true)
|
||||
}}
|
||||
>
|
||||
充值
|
||||
</Button>
|
||||
<DepositDialog
|
||||
user={row.original}
|
||||
onSuccess={refreshTable}
|
||||
/>
|
||||
</Auth>
|
||||
|
||||
<Auth scope={ScopeUserWriteBalanceDec}>
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setDeduction(user)
|
||||
setDeductionDialog(true)
|
||||
}}
|
||||
>
|
||||
扣款
|
||||
</Button>
|
||||
<DeductionDialog
|
||||
user={row.original}
|
||||
onSuccess={refreshTable}
|
||||
/>
|
||||
</Auth>
|
||||
|
||||
<Auth scope={ScopeUserWriteBalance}>
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setCurrentEditUser(user)
|
||||
setIsEditDialogOpen(true)
|
||||
}}
|
||||
>
|
||||
修改
|
||||
</Button>
|
||||
<UpdateDialog
|
||||
user={row.original}
|
||||
onSuccess={refreshTable}
|
||||
/>
|
||||
</Auth>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
@@ -492,32 +471,6 @@ export default function CustPage() {
|
||||
]}
|
||||
/>
|
||||
</Suspense>
|
||||
|
||||
<AddUserDialog
|
||||
open={isAddDialogOpen}
|
||||
onOpenChange={setIsAddDialogOpen}
|
||||
onSuccess={refreshTable}
|
||||
/>
|
||||
|
||||
<UpdateDialog
|
||||
open={isEditDialogOpen}
|
||||
onOpenChange={setIsEditDialogOpen}
|
||||
currentUser={currentEditUser}
|
||||
onSuccess={refreshTable}
|
||||
/>
|
||||
|
||||
<DepositDialog
|
||||
open={depositDialog}
|
||||
onOpenChange={setDepositDialog}
|
||||
currentUser={deposit}
|
||||
onSuccess={refreshTable}
|
||||
/>
|
||||
<DeductionDialog
|
||||
open={deductionDialog}
|
||||
onOpenChange={setDeductionDialog}
|
||||
currentUser={deduction}
|
||||
onSuccess={refreshTable}
|
||||
/>
|
||||
</div>
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog"
|
||||
import {
|
||||
Field,
|
||||
@@ -30,8 +31,8 @@ import {
|
||||
SelectValue,
|
||||
} from "@/components/ui/select"
|
||||
import type { Admin } from "@/models/admin"
|
||||
import type { User } from "@/models/user"
|
||||
import type { ProductDiscount } from "@/models/product_discount"
|
||||
import type { User } from "@/models/user"
|
||||
|
||||
// 表单验证规则
|
||||
const editUserSchema = z
|
||||
@@ -67,18 +68,12 @@ const editUserSchema = z
|
||||
export type EditUserFormValues = z.infer<typeof editUserSchema>
|
||||
|
||||
interface EditUserDialogProps {
|
||||
open: boolean
|
||||
onOpenChange: (open: boolean) => void
|
||||
currentUser: User | null
|
||||
user: User
|
||||
onSuccess: () => void
|
||||
}
|
||||
|
||||
export function UpdateDialog({
|
||||
open,
|
||||
onOpenChange,
|
||||
currentUser,
|
||||
onSuccess,
|
||||
}: EditUserDialogProps) {
|
||||
export function UpdateDialog({ user, onSuccess }: EditUserDialogProps) {
|
||||
const [open, setOpen] = useState(false)
|
||||
const [admins, setAdmins] = useState<Admin[]>([])
|
||||
const [discounts, setDiscounts] = useState<ProductDiscount[]>([])
|
||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||
@@ -133,24 +128,21 @@ export function UpdateDialog({
|
||||
}, [open])
|
||||
|
||||
useEffect(() => {
|
||||
if (currentUser) {
|
||||
if (open) {
|
||||
reset({
|
||||
id: currentUser.id,
|
||||
username: currentUser.username,
|
||||
email: currentUser.email || "",
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
email: user.email || "",
|
||||
password: "",
|
||||
confirmPassword: "",
|
||||
admin_id: currentUser.admin_id ? String(currentUser.admin_id) : "",
|
||||
discount_id: currentUser.discount_id
|
||||
? String(currentUser.discount_id)
|
||||
: "",
|
||||
status:
|
||||
currentUser.status !== undefined ? String(currentUser.status) : "",
|
||||
contact_qq: currentUser.contact_qq || "",
|
||||
contact_wechat: currentUser.contact_wechat || "",
|
||||
admin_id: user.admin_id ? String(user.admin_id) : "",
|
||||
discount_id: user.discount_id ? String(user.discount_id) : "",
|
||||
status: user.status !== undefined ? String(user.status) : "",
|
||||
contact_qq: user.contact_qq || "",
|
||||
contact_wechat: user.contact_wechat || "",
|
||||
})
|
||||
}
|
||||
}, [currentUser, reset])
|
||||
}, [open, user, reset])
|
||||
|
||||
const onSubmit = async (data: EditUserFormValues) => {
|
||||
setIsSubmitting(true)
|
||||
@@ -194,7 +186,7 @@ export function UpdateDialog({
|
||||
const result = await updateCust(updateData)
|
||||
if (result?.success) {
|
||||
toast.success("修改成功")
|
||||
onOpenChange(false)
|
||||
setOpen(false)
|
||||
onSuccess()
|
||||
} else {
|
||||
toast.error(result?.message || "修改失败")
|
||||
@@ -213,11 +205,14 @@ export function UpdateDialog({
|
||||
if (!open) {
|
||||
reset()
|
||||
}
|
||||
onOpenChange(open)
|
||||
setOpen(open)
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={handleOpenChange}>
|
||||
<DialogTrigger asChild>
|
||||
<Button size="sm">修改</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>修改用户</DialogTitle>
|
||||
|
||||
Reference in New Issue
Block a user