表格与页面样式调整

This commit is contained in:
2026-04-11 17:12:16 +08:00
parent 4307efae98
commit 04426ba36d
33 changed files with 239 additions and 1460 deletions

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>
)
}

View File

@@ -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>