网关取消删除添加启用和停用功能 & 产品页套餐添加sort 排序和 count_min 最低购买数量字段
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "lanhu-admin",
|
||||
"version": "1.4.0",
|
||||
"version": "1.5.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev -H 0.0.0.0 -p 3001 --turbopack",
|
||||
|
||||
@@ -45,6 +45,7 @@ export async function updateProductSku(data: {
|
||||
price?: string
|
||||
discount_id?: number | null
|
||||
price_min?: string
|
||||
count_min?: number | null
|
||||
}) {
|
||||
return callByUser<ProductSku>("/api/admin/product/sku/update", {
|
||||
id: data.id,
|
||||
@@ -53,6 +54,7 @@ export async function updateProductSku(data: {
|
||||
price: data.price,
|
||||
discount_id: data.discount_id,
|
||||
price_min: data.price_min,
|
||||
count_min: data.count_min,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,33 +1,22 @@
|
||||
"use client"
|
||||
|
||||
import { format } from "date-fns"
|
||||
import { Suspense, useState } from "react"
|
||||
import { toast } from "sonner"
|
||||
import { deletegateway, getGatewayPage } from "@/actions/gateway"
|
||||
import { getGatewayPage } from "@/actions/gateway"
|
||||
import { Auth } from "@/components/auth"
|
||||
import { DataTable, useDataTable } from "@/components/data-table"
|
||||
import { Page } from "@/components/page"
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/components/ui/alert-dialog"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { ScopeProxyWrite } from "@/lib/scopes"
|
||||
import type { Gateway } from "@/models/gateway"
|
||||
import CreatePage from "./create"
|
||||
import { format } from "date-fns"
|
||||
import { ScopeProxyWrite } from "@/lib/scopes"
|
||||
import { Auth } from "@/components/auth"
|
||||
|
||||
export default function GatewayPage() {
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
const table = useDataTable((page, size) => getGatewayPage({ page, size }))
|
||||
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<Auth scope={ScopeProxyWrite}>
|
||||
@@ -42,12 +31,11 @@ export default function GatewayPage() {
|
||||
{...table}
|
||||
status={loading ? "load" : "done"}
|
||||
columns={[
|
||||
// { header: "id", accessorKey: "id" },
|
||||
{
|
||||
header: "域名",
|
||||
accessorKey: "host",
|
||||
},
|
||||
{ header: "IP地址", accessorKey: "ip" },
|
||||
{ header: "IP地址", accessorKey: "ip" },
|
||||
{
|
||||
header: "MAC地址",
|
||||
accessorKey: "mac",
|
||||
@@ -74,7 +62,10 @@ export default function GatewayPage() {
|
||||
header: "操作",
|
||||
cell: ({ row }) => (
|
||||
<div className="flex gap-2">
|
||||
<Auth scope={ScopeProxyWrite}><Delete gateway={row.original} onSuccess={table.refresh} /></Auth>
|
||||
<Button className="bg-green-600/60 hover:bg-green-600/60 active:bg-green-600/60">
|
||||
启用
|
||||
</Button>
|
||||
<Button>停用</Button>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
@@ -84,53 +75,3 @@ export default function GatewayPage() {
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
|
||||
function Delete({
|
||||
gateway,
|
||||
onSuccess,
|
||||
}: {
|
||||
gateway: Gateway
|
||||
onSuccess?: () => void
|
||||
}) {
|
||||
const [loading, setLoading] = useState(false)
|
||||
const handleConfirm = async () => {
|
||||
setLoading(true)
|
||||
try {
|
||||
const resp = await deletegateway(gateway.id)
|
||||
if (resp.success) {
|
||||
toast.success("删除成功")
|
||||
onSuccess?.()
|
||||
} else {
|
||||
toast.error(resp.message ?? "删除失败")
|
||||
}
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : error
|
||||
toast.error(`接口请求错误: ${message}`)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
return (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button size="sm" variant="destructive" disabled={loading}>
|
||||
删除
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent size="sm">
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>确认删除</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
确定要删除「{gateway.host || gateway.ip}」吗?此操作不可撤销。
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>取消</AlertDialogCancel>
|
||||
<AlertDialogAction variant="destructive" onClick={handleConfirm}>
|
||||
删除
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ const schema = z
|
||||
"请输入有效的正数单价",
|
||||
),
|
||||
discount_id: z.string().optional(),
|
||||
count_min: z.string().min(1, "请输入最低购买数量"),
|
||||
price_min: z
|
||||
.string()
|
||||
.min(1, "请输入最低价格")
|
||||
@@ -177,19 +178,6 @@ export function CreateProductSku(props: {
|
||||
placeholder="请输入单价"
|
||||
{...field}
|
||||
aria-invalid={fieldState.invalid}
|
||||
// onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
// let value = e.target.value
|
||||
// value = value.replace(/[^\d.]/g, "")
|
||||
// const dotCount = (value.match(/\./g) || []).length
|
||||
// if (dotCount > 1) {
|
||||
// value = value.slice(0, value.lastIndexOf("."))
|
||||
// }
|
||||
// if (value.includes(".")) {
|
||||
// const [int, dec] = value.split(".")
|
||||
// value = `${int}.${dec.slice(0, 2)}`
|
||||
// }
|
||||
// field.onChange(value)
|
||||
// }}
|
||||
/>
|
||||
{fieldState.invalid && (
|
||||
<FieldError errors={[fieldState.error]} />
|
||||
@@ -208,19 +196,6 @@ export function CreateProductSku(props: {
|
||||
placeholder="请输入最低价格"
|
||||
{...field}
|
||||
aria-invalid={fieldState.invalid}
|
||||
// onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
// let value = e.target.value
|
||||
// value = value.replace(/[^\d.]/g, "")
|
||||
// const dotCount = (value.match(/\./g) || []).length
|
||||
// if (dotCount > 1) {
|
||||
// value = value.slice(0, value.lastIndexOf("."))
|
||||
// }
|
||||
// if (value.includes(".")) {
|
||||
// const [int, dec] = value.split(".")
|
||||
// value = `${int}.${dec.slice(0, 2)}`
|
||||
// }
|
||||
// field.onChange(value)
|
||||
// }}
|
||||
/>
|
||||
{fieldState.invalid && (
|
||||
<FieldError errors={[fieldState.error]} />
|
||||
@@ -228,7 +203,26 @@ export function CreateProductSku(props: {
|
||||
</Field>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
control={form.control}
|
||||
name="count_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"
|
||||
|
||||
@@ -141,6 +141,7 @@ function ProductSkus(props: {
|
||||
},
|
||||
},
|
||||
{ header: "最低价格", accessorKey: "price_min" },
|
||||
{ header: "最低购买数量", accessorKey: "count_min" },
|
||||
{
|
||||
header: "创建时间",
|
||||
accessorFn: row => format(row.created_at, "yyyy-MM-dd HH:mm"),
|
||||
|
||||
@@ -46,6 +46,16 @@ const schema = z
|
||||
"请输入有效的正数单价",
|
||||
),
|
||||
discount_id: z.string().optional(),
|
||||
count_min: z
|
||||
.string()
|
||||
.min(1, "请输入最低购买数量")
|
||||
.refine(
|
||||
v =>
|
||||
!Number.isNaN(Number(v)) &&
|
||||
Number.isInteger(Number(v)) &&
|
||||
Number(v) > 0,
|
||||
"请输入有效的正整数",
|
||||
),
|
||||
price_min: z
|
||||
.string()
|
||||
.min(1, "请输入最低价格")
|
||||
@@ -82,6 +92,7 @@ export function UpdateProductSku(props: {
|
||||
price: props.sku.price,
|
||||
discount_id: props.sku.discount ? String(props.sku.discount.id) : "",
|
||||
price_min: props.sku.price_min ?? "",
|
||||
count_min: String(props.sku.count_min),
|
||||
},
|
||||
})
|
||||
|
||||
@@ -107,7 +118,9 @@ export function UpdateProductSku(props: {
|
||||
? Number(data.discount_id)
|
||||
: null,
|
||||
price_min: data.price_min,
|
||||
count_min: Number(data.count_min),
|
||||
})
|
||||
console.log(resp, "resp")
|
||||
|
||||
if (resp.success) {
|
||||
toast.success("套餐修改成功")
|
||||
@@ -130,6 +143,7 @@ export function UpdateProductSku(props: {
|
||||
price: props.sku.price,
|
||||
discount_id: props.sku.discount ? String(props.sku.discount.id) : "",
|
||||
price_min: props.sku.price_min ?? "",
|
||||
count_min: props.sku.count_min ? String(props.sku.count_min) : "",
|
||||
})
|
||||
}
|
||||
setOpen(value)
|
||||
@@ -180,19 +194,6 @@ export function UpdateProductSku(props: {
|
||||
placeholder="请输入单价"
|
||||
{...field}
|
||||
aria-invalid={fieldState.invalid}
|
||||
// onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
// let value = e.target.value
|
||||
// value = value.replace(/[^\d.]/g, "")
|
||||
// const dotCount = (value.match(/\./g) || []).length
|
||||
// if (dotCount > 1) {
|
||||
// value = value.slice(0, value.lastIndexOf("."))
|
||||
// }
|
||||
// if (value.includes(".")) {
|
||||
// const [int, dec] = value.split(".")
|
||||
// value = `${int}.${dec.slice(0, 2)}`
|
||||
// }
|
||||
// field.onChange(value)
|
||||
// }}
|
||||
/>
|
||||
{fieldState.invalid && (
|
||||
<FieldError errors={[fieldState.error]} />
|
||||
@@ -205,25 +206,34 @@ export function UpdateProductSku(props: {
|
||||
name="price_min"
|
||||
render={({ field, fieldState }) => (
|
||||
<Field>
|
||||
<FieldLabel htmlFor="sku-create-price">最低价格</FieldLabel>
|
||||
<FieldLabel htmlFor="sku-update-price-min">
|
||||
最低价格
|
||||
</FieldLabel>
|
||||
<Input
|
||||
id="sku-create-price"
|
||||
id="sku-update-price-min"
|
||||
placeholder="请输入最低价格"
|
||||
{...field}
|
||||
aria-invalid={fieldState.invalid}
|
||||
// onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
// let value = e.target.value
|
||||
// value = value.replace(/[^\d.]/g, "")
|
||||
// const dotCount = (value.match(/\./g) || []).length
|
||||
// if (dotCount > 1) {
|
||||
// value = value.slice(0, value.lastIndexOf("."))
|
||||
// }
|
||||
// if (value.includes(".")) {
|
||||
// const [int, dec] = value.split(".")
|
||||
// value = `${int}.${dec.slice(0, 2)}`
|
||||
// }
|
||||
// field.onChange(value)
|
||||
// }}
|
||||
/>
|
||||
{fieldState.invalid && (
|
||||
<FieldError errors={[fieldState.error]} />
|
||||
)}
|
||||
</Field>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
control={form.control}
|
||||
name="count_min"
|
||||
render={({ field, fieldState }) => (
|
||||
<Field>
|
||||
<FieldLabel htmlFor="sku-update-count-min">
|
||||
最低购买数量
|
||||
</FieldLabel>
|
||||
<Input
|
||||
id="sku-update-count-min"
|
||||
placeholder="请输入最低购买数量"
|
||||
{...field}
|
||||
aria-invalid={fieldState.invalid}
|
||||
/>
|
||||
{fieldState.invalid && (
|
||||
<FieldError errors={[fieldState.error]} />
|
||||
|
||||
@@ -11,4 +11,6 @@ export type ProductSku = Model & {
|
||||
product?: Product
|
||||
price_min?: string
|
||||
discount?: ProductDiscount
|
||||
sort: number
|
||||
count_min: number
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user