您好,我目前正在开发一个项目,在该项目中单击按钮,前端将请求发送到后端并运行一个函数。我在代码中使用 shadcn 默认按钮和 onClick 事件,当我在我的电脑上的本地主机上运行代码时,它可以正常工作,但当我将它托管在 vercel 上并在我的 iphone 上打开它时,按钮无法正常工作。当它在 iPhone 上打开时,有时我需要单击按钮 1 次,并且该功能运行有时我需要单击最多 10 次才能运行该功能。有人对这个问题有解决办法吗?
这是代码,我所说的按钮是“打印标签”按钮
import { useCallback } from "react";
import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { Separator } from "@/components/ui/separator";
import {
Card,
} from "@/components/ui/card";
import { Package } from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { Orders } from "@/lib/types/shipmondo";
import { FurfillOrder, PrintLabel, createSale, findId } from "./actions";
import { Product } from "@/lib/types/wix";
import { Button } from "@/components/ui/button";
import { Progress } from "@/components/ui/progress";
import { Checkbox } from "@/components/ui/checkbox";
export default function Dialogt({ order, totalWeight, products }: { order: Orders, totalWeight: number, products: Product[] }) {
const router = useRouter();
// const [isOpen, setIsOpen] = useState(true);
const [checkedItems, setCheckedItems] = useState<number[]>([]);
const [isPacking, setIsPacking] = useState(false);
const [isButtonDisabled, setIsButtonDisabled] = useState(false);
const [packingStarted, setPackingStarted] = useState(false);
const furfillOrder = async (item_id: number, order_id: number, item_quantity: number) => {
await FurfillOrder(item_id, order_id, item_quantity);
}
const handleCheckboxChange = (index: number, item_id: number, order_id: number, item_quantity: number) => {
setCheckedItems(prevCheckedItems =>
prevCheckedItems.includes(index)
? prevCheckedItems.filter(item => item !== index)
: [...prevCheckedItems, index]
);
furfillOrder(item_id, order_id, item_quantity);
};
const calculateProgress = () => {
const itemCount = order.order_lines?.filter((line: any) => line.line_type === "item").length ?? 0;
return (checkedItems.length / itemCount) * 100;
};
const handelShippingDicount = async (order_id: number, discountId: number, shippingId: number) => {
console.log(order_id)
await furfillOrder(shippingId, order_id, 1);
if (dicountId && dicountId.length > 2) {
await furfillOrder(dicountId, order_id, 1);
console.log(order_id)
console.log("Allt är klart")
} else {
console.log("Fanns inge discountId")
console.log(order_id)
console.log(dicountId)
}
setIsButtonDisabled(true);
console.log(calculateProgress());
setPackingStarted(true); // set packingStarted to true
}
// const packad = async (order_id: string) => {
// await putStatus(order_id);
// setIsPacking(true);
// };
// const handleClose = () => {
// setIsOpen(false);
// };
// const cancelOrder = async (order_id: string) => {
// await cancel(order_id);
// handleClose();
// };
const [isPrinting, setIsPrinting] = useState(false);
const print = useCallback(async (order_id: number) => {
if (isPrinting) return; // prevent multiple clicks
setIsPrinting(true);
await findId(order_id);
setIsPrinting(false);
}, [isPrinting, findId]);
useEffect(() => {
if (isPacking) {
router.push('/packning/packas');
}
}, [isPacking, router]);
let shippingId: any = '';
let dicountId: any = '';
return (
<Dialog>
<DialogTrigger className="h-32 w-10 items-center justify-center flex bg-blend-overlay bg-transparent ">
<Package size={30} />
</DialogTrigger>
<DialogContent className={'g:max-w-screen-lg overflow-y-scroll max-h-screen pb-10'}>
<DialogHeader className="m-4">
<DialogTitle className="items-center flex justify-around">
Order {order.order_id.substring(0, 12)}
{/* {order.order_status === "on_hold" ? <Badge className="bg-[#ffA500] text-black">Påbörjad</Badge> : <Button onClick={() => packad(order.id)}>Packa</Button>}
{order.order_status === 'on_hold' ? <Button
onClick={() => cancelOrder(order.id)}
variant={'ghost'} color={'destructive'}>Avbryt
</Button> : ''} */}
</DialogTitle>
</DialogHeader>
<DialogDescription>
<Card key={order.id} className="flex items-center p-6 rounded-lg border-none m-4">
<div className="flex flex-col items-start gap-4">
<div className="flex flex-col items-start gap-1">
<h3 className=" font-bold">
{order.ship_to.name}
</h3>
<div className="flex items-center gap-2 text-muted-foreground">
<span>Id: {order.order_id.substring(0, 12)}</span>
<div className="h-3 w-3 rounded-full bg-muted" />
<span>Vikt: {totalWeight.toFixed(2)}kg</span>
</div>
</div>
<div className="flex items-center gap-4">
{order.order_status === "open" ? <Badge variant={'destructive'}>Ska packas</Badge> : <Badge className="bg-[#ffA500] text-black">Påbörjad</Badge>}
<div className="text-base">Artiklar: {`${order.order_lines?.length ?? - 1}`}</div>
</div>
</div>
</Card>
{order.order_note && order.order_note.length > 1 ? (
<Card key={order.id} className="flex p-6 rounded-lg border-none m-4">
<h2 className="w-full">
{order.order_note}
</h2>
</Card>
) : (
<Card key={order.id} className="flex p-6 rounded-lg border-none m-4">
<h2 className="w-full">
inga anteckningar
</h2>
</Card>
)}
{order?.order_lines?.map((line: any) => (
<>
{line.line_type === "shipping" && (
<Card key={order.id} className="rounded-lg border-none m-4 flex p-6">
<span className="font-semibold">
Frakt:
</span>
{line.item_name}
<div className="hidden">
{shippingId = line.id}
</div>
</Card>
)
}
{line.line_type === "discount" && (
<Card key={order.id} className="rounded-lg border-none m-4 flex p-6">
<h2 className="w-full">
<span className="font-semibold">
Rabatt:
</span>
{line.item_name}
<div className="hidden">
{dicountId = line.id}
</div>
</h2>
</Card>
)
}
</>
)
)}
<Button
disabled={isButtonDisabled}
onClick={() => handelShippingDicount(order.id, dicountId, shippingId)}
className="w-full bg-transparent border-[#4BB543] border-4 hover:bg-transparent text-black "
>
Börja packa
</Button>
</DialogDescription>
<Separator />
<DialogHeader className="pb-10">
<DialogTitle className="m-2">Produkter</DialogTitle>
{calculateProgress() < 100 ? (
<Progress className="sticky top-4 sm:top-8 md:-6 shadow-2xl w-full" value={calculateProgress()} />
) : (
<Button className="bg-[#00FF00] font-semibold p-8 text-black text-base hover:bg-cyan-500" onClick={() => print(order.id)} disabled={isPrinting}>
Printa label
</Button>
)}
{order?.order_lines?.filter((line: any) => line.line_type === "item").map((line: any, index: number) => (
<button
key={index}
onClick={() => handleCheckboxChange(index, line.id, order.id, line.quantity)}
disabled={!packingStarted || checkedItems.includes(index)} // conditionally disable the button
>
<Card
className={`flex items-center p-6 mb-4 rounded-lg shadow-lg mt-4 active:border-6 active:border-green-600 ${checkedItems.includes(index) ? " border-4 border-[#4BB543] cursor-not-allowed" : ""
}`}
>
<div className="flex flex-col items-start gap-4 w-full">
<div className="flex flex-col items-start gap-1">
<h3 className=" font-bold">
{line.item_name}
</h3>
<div className="flex items-center gap-2 text-muted-foreground">
<span>Id: {line.id}</span>
<div className="h-3 w-3 rounded-full bg-muted" />
<span>Vikt: {line.unit_weight}gr</span>
</div>
</div>
<div className="flex items-center gap-4 font-bold ">
<div>{Math.floor(line.quantity)} st</div>
</div>
</div>
</Card>
</button>
))}
</DialogHeader>
</DialogContent>
</Dialog>
)
}
我在没有表单的对话框上使用 shadcn 按钮也有类似的问题。我无法以常规方法连接按钮单击事件处理程序,例如将 addClick / addClickCapture 属性添加到 Button 元素。
我已经有了对按钮的引用,我使用表的 RowSelectedEvent 处理程序中的引用来启用/禁用按钮。
这是我对话框中的两个组件(内联 onClick (或 onClickCapture)处理程序不起作用):
<div className={cn("flex justify-end")}>
<Button ref={ref} disabled={!projectSelected} onClick={()=>console.log("confirmed")}>Confirm selection</Button>
</div>
<SingleSelectionProjectTableWithAgGrid fetcher={projectsFetcher} rowSelectionHandler={onSelectionChange} />
我的解决方法是在 rowSelectionHandler:
const ref = React.useRef<HTMLButtonElement>(null)
const [projectId, setProjectId] = React.useState<string>()
const onSelectionChange = (evt) => {
if (ref.current) {
setProjectId(evt.data["id"])
ref.current.disabled = !evt.node.selected
ref.current.onclick = () => console.log("Comfirm button clicked")
}
}