修改客户认领和客户管理页面的查询和操作功能并且包含按钮权限 & 产品管理添加启动/禁用和最低价格字段
This commit is contained in:
@@ -45,6 +45,14 @@ const schema = z.object({
|
||||
"请输入有效的正数单价",
|
||||
),
|
||||
discount_id: z.string().optional(),
|
||||
price_min: z
|
||||
.string()
|
||||
.optional()
|
||||
.or(z.literal(""))
|
||||
.refine(
|
||||
v => !v || (!Number.isNaN(Number(v)) && Number(v) > 0),
|
||||
"请输入有效的正数价格",
|
||||
),
|
||||
})
|
||||
|
||||
export function CreateProductSku(props: {
|
||||
@@ -61,6 +69,7 @@ export function CreateProductSku(props: {
|
||||
name: "",
|
||||
price: "",
|
||||
discount_id: "",
|
||||
price_min: "",
|
||||
},
|
||||
})
|
||||
|
||||
@@ -89,7 +98,22 @@ export function CreateProductSku(props: {
|
||||
data.discount_id && data.discount_id !== ""
|
||||
? Number(data.discount_id)
|
||||
: undefined,
|
||||
price_min: data.price_min,
|
||||
})
|
||||
console.log({
|
||||
product_id: props.productId,
|
||||
code: data.code,
|
||||
name: data.name,
|
||||
price: data.price,
|
||||
discount_id:
|
||||
data.discount_id && data.discount_id !== ""
|
||||
? Number(data.discount_id)
|
||||
: undefined,
|
||||
price_min: data.price_min,
|
||||
})
|
||||
|
||||
console.log(resp, "resp")
|
||||
|
||||
if (resp.success) {
|
||||
form.reset()
|
||||
toast.success("套餐创建成功")
|
||||
@@ -162,6 +186,25 @@ export function CreateProductSku(props: {
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
control={form.control}
|
||||
name="price_min"
|
||||
render={({ field, fieldState }) => (
|
||||
<Field>
|
||||
<FieldLabel htmlFor="sku-create-price">最低价格</FieldLabel>
|
||||
<Input
|
||||
id="sku-create-price"
|
||||
placeholder="请输入单价"
|
||||
{...field}
|
||||
aria-invalid={fieldState.invalid}
|
||||
/>
|
||||
{fieldState.invalid && (
|
||||
<FieldError errors={[fieldState.error]} />
|
||||
)}
|
||||
</Field>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
control={form.control}
|
||||
name="discount_id"
|
||||
|
||||
@@ -1,26 +1,16 @@
|
||||
"use client"
|
||||
|
||||
import { format } from "date-fns"
|
||||
import { Loader2 } from "lucide-react"
|
||||
import { Suspense, useCallback, useEffect, useMemo, useState } from "react"
|
||||
import { toast } from "sonner"
|
||||
import {
|
||||
deleteProductSku,
|
||||
activeProductSku,
|
||||
getAllProduct,
|
||||
getPageProductSku,
|
||||
} from "@/actions/product"
|
||||
import { DataTable, useDataTable } from "@/components/data-table"
|
||||
import { SkuCodeBadge } from "@/components/products/format"
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/components/ui/alert-dialog"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import type { ProductCode } from "@/lib/base"
|
||||
@@ -108,6 +98,7 @@ function ProductSkus(props: {
|
||||
)
|
||||
|
||||
const table = useDataTable(action)
|
||||
console.log(table, "table")
|
||||
|
||||
return (
|
||||
<div className="flex-auto overflow-hidden flex flex-col items-stretch gap-3">
|
||||
@@ -149,6 +140,7 @@ function ProductSkus(props: {
|
||||
return Number(value.toFixed(2))
|
||||
},
|
||||
},
|
||||
{ header: "最低价格", accessorKey: "price_min" },
|
||||
{
|
||||
header: "创建时间",
|
||||
accessorFn: row => format(row.created_at, "yyyy-MM-dd HH:mm"),
|
||||
@@ -167,7 +159,7 @@ function ProductSkus(props: {
|
||||
sku={row.original}
|
||||
onSuccess={table.refresh}
|
||||
/>
|
||||
<DeleteButton sku={row.original} onSuccess={table.refresh} />
|
||||
<ActiveButton sku={row.original} onSuccess={table.refresh} />
|
||||
</div>
|
||||
),
|
||||
},
|
||||
@@ -178,18 +170,22 @@ function ProductSkus(props: {
|
||||
)
|
||||
}
|
||||
|
||||
function DeleteButton(props: { sku: ProductSku; onSuccess?: () => void }) {
|
||||
function ActiveButton(props: { sku: ProductSku; onSuccess?: () => void }) {
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
const handleConfirm = async () => {
|
||||
setLoading(true)
|
||||
try {
|
||||
const resp = await deleteProductSku(props.sku.id)
|
||||
const newStatus = props.sku.status === 1 ? 0 : 1
|
||||
const resp = await activeProductSku({
|
||||
id: props.sku.id,
|
||||
status: newStatus,
|
||||
})
|
||||
if (resp.success) {
|
||||
toast.success("删除成功")
|
||||
toast.success(newStatus === 1 ? "已启用" : "已禁用")
|
||||
props.onSuccess?.()
|
||||
} else {
|
||||
toast.error(resp.message ?? "删除失败")
|
||||
toast.error(resp.message ?? "操作失败")
|
||||
}
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : error
|
||||
@@ -200,26 +196,17 @@ function DeleteButton(props: { sku: ProductSku; onSuccess?: () => void }) {
|
||||
}
|
||||
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button size="sm" variant="destructive" disabled={loading}>
|
||||
删除
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent size="sm">
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>确认删除</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
确定要删除套餐「{props.sku.name}」吗?此操作不可撤销。
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>取消</AlertDialogCancel>
|
||||
<AlertDialogAction variant="destructive" onClick={handleConfirm}>
|
||||
删除
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
<Button
|
||||
size="sm"
|
||||
variant={props.sku?.status === 1 ? "outline" : "default"}
|
||||
onClick={handleConfirm}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? (
|
||||
<Loader2 className="h-4 w-4 animate-spin" />
|
||||
) : (
|
||||
<>{props.sku?.status === 1 ? "禁用" : "启用"}</>
|
||||
)}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -45,6 +45,13 @@ const schema = z.object({
|
||||
"请输入有效的正数单价",
|
||||
),
|
||||
discount_id: z.string().optional(),
|
||||
price_min: z
|
||||
.string()
|
||||
.min(1, "请输入最低价格")
|
||||
.refine(
|
||||
v => !Number.isNaN(Number(v)) && Number(v) > 0,
|
||||
"请输入有效的正数价格",
|
||||
),
|
||||
})
|
||||
|
||||
export function UpdateProductSku(props: {
|
||||
@@ -61,6 +68,7 @@ export function UpdateProductSku(props: {
|
||||
name: props.sku.name,
|
||||
price: props.sku.price,
|
||||
discount_id: props.sku.discount ? String(props.sku.discount.id) : "",
|
||||
price_min: props.sku.price_min ?? "",
|
||||
},
|
||||
})
|
||||
|
||||
@@ -75,6 +83,8 @@ export function UpdateProductSku(props: {
|
||||
}, [open])
|
||||
|
||||
const onSubmit = async (data: z.infer<typeof schema>) => {
|
||||
console.log(data, "data")
|
||||
|
||||
try {
|
||||
const resp = await updateProductSku({
|
||||
id: props.sku.id,
|
||||
@@ -85,7 +95,22 @@ export function UpdateProductSku(props: {
|
||||
data.discount_id && data.discount_id !== ""
|
||||
? Number(data.discount_id)
|
||||
: null,
|
||||
price_min: data.price_min,
|
||||
})
|
||||
console.log({
|
||||
id: props.sku.id,
|
||||
code: data.code,
|
||||
name: data.name,
|
||||
price: data.price,
|
||||
discount_id:
|
||||
data.discount_id && data.discount_id !== ""
|
||||
? Number(data.discount_id)
|
||||
: null,
|
||||
price_min: data.price_min,
|
||||
})
|
||||
|
||||
console.log(resp, "resp")
|
||||
|
||||
if (resp.success) {
|
||||
toast.success("套餐修改成功")
|
||||
props.onSuccess?.()
|
||||
@@ -106,6 +131,7 @@ export function UpdateProductSku(props: {
|
||||
name: props.sku.name,
|
||||
price: props.sku.price,
|
||||
discount_id: props.sku.discount ? String(props.sku.discount.id) : "",
|
||||
price_min: props.sku.price_min ?? "",
|
||||
})
|
||||
}
|
||||
setOpen(value)
|
||||
@@ -163,7 +189,24 @@ export function UpdateProductSku(props: {
|
||||
</Field>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
control={form.control}
|
||||
name="price_min"
|
||||
render={({ field, fieldState }) => (
|
||||
<Field>
|
||||
<FieldLabel htmlFor="sku-create-price">最低价格</FieldLabel>
|
||||
<Input
|
||||
id="sku-create-price"
|
||||
placeholder="请输入最低价格"
|
||||
{...field}
|
||||
aria-invalid={fieldState.invalid}
|
||||
/>
|
||||
{fieldState.invalid && (
|
||||
<FieldError errors={[fieldState.error]} />
|
||||
)}
|
||||
</Field>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
control={form.control}
|
||||
name="discount_id"
|
||||
|
||||
Reference in New Issue
Block a user