feat(ui): 引入 sonner 消息反馈系统,并在首页部署全局行情同步按钮

This commit is contained in:
2026-04-28 15:46:57 +08:00
parent 58db0b82ee
commit 110e75f0a1
9 changed files with 109 additions and 17 deletions
@@ -33,6 +33,7 @@ import {
SelectValue,
} from '@/components/ui/select';
import { Plus } from 'lucide-react';
import { toast } from 'sonner';
import { createAsset } from '@/actions/asset';
const addAssetSchema = z.object({
@@ -94,6 +95,7 @@ export function AddAssetDialog() {
startTransition(async () => {
const result = await createAsset(values);
if (result.success) {
toast.success('资产添加成功');
setOpen(false);
form.reset();
router.refresh();
+8 -2
View File
@@ -3,14 +3,20 @@
import { useState, useTransition } from 'react';
import { Button } from '@/components/ui/button';
import { RefreshCw } from 'lucide-react';
import { toast } from 'sonner';
import { syncAllMarketPrices } from '@/actions/market';
export function SyncButton() {
const [isPending, startTransition] = useTransition();
function handleClick() {
async function handleClick() {
startTransition(async () => {
await syncAllMarketPrices();
try {
await syncAllMarketPrices();
toast.success('行情同步成功', { description: '全市场资产价格已更新为最新市价' });
} catch (error) {
toast.error('行情同步异常', { description: '部分接口可能触发了熔断或网络阻断' });
}
});
}
@@ -33,6 +33,7 @@ import {
SelectValue,
} from '@/components/ui/select';
import { Plus } from 'lucide-react';
import { toast } from 'sonner';
import { createTransaction } from '@/actions/transaction';
const addTransactionSchema = z.object({
@@ -117,6 +118,7 @@ export function AddTransactionDialog({ assets }: AddTransactionDialogProps) {
exchangeRate: '1',
});
if (result.success) {
toast.success('流水记录成功');
setOpen(false);
form.reset();
router.refresh();
+45
View File
@@ -0,0 +1,45 @@
"use client"
import {
CircleCheck,
Info,
LoaderCircle,
OctagonX,
TriangleAlert,
} from "lucide-react"
import { useTheme } from "next-themes"
import { Toaster as Sonner } from "sonner"
type ToasterProps = React.ComponentProps<typeof Sonner>
const Toaster = ({ ...props }: ToasterProps) => {
const { theme = "system" } = useTheme()
return (
<Sonner
theme={theme as ToasterProps["theme"]}
className="toaster group"
icons={{
success: <CircleCheck className="h-4 w-4" />,
info: <Info className="h-4 w-4" />,
warning: <TriangleAlert className="h-4 w-4" />,
error: <OctagonX className="h-4 w-4" />,
loading: <LoaderCircle className="h-4 w-4 animate-spin" />,
}}
toastOptions={{
classNames: {
toast:
"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
description: "group-[.toast]:text-muted-foreground",
actionButton:
"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
cancelButton:
"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
},
}}
{...props}
/>
)
}
export { Toaster }