feat(toast): 使用SVG图标替换字符图标并优化样式

- 新增四种SVG图标:info、success、warning、error
- 修改Toast组件使用SVG图标替代字符图标
- 更新图标映射逻辑,使用IconId类型定义图标标识
- 调整Toast样式类,使用更具体的Tailwind类名
- 移除旧的alertStyles对象和字符图标映射
- 登录页面增加错误处理和Toast提示
- 布局文件微调菜单样式,增加顶部内边距
This commit is contained in:
Chaos
2025-11-23 21:59:47 +08:00
parent a71622f797
commit 71f19b658c
5 changed files with 42 additions and 22 deletions

View File

@@ -1,22 +1,15 @@
<script lang="ts">
import { toast } from '$lib/stores/toastStore';
import { toast, type ToastType } from '$lib/stores/toastStore';
import { fly } from 'svelte/transition';
import { flip } from 'svelte/animate';
import Icon from '$lib/components/icon/Icon.svelte';
import type { IconId } from '$lib/types/icon-ids.ts';
// 映射 Toast 类型到 daisyUI 的 alert 样式类
const alertStyles = {
info: 'alert-info',
success: 'alert-success',
warning: 'alert-warning',
error: 'alert-error'
};
// 映射 Toast 类型到图标 (可选,为了更像 AntD)
const icons = {
info: '',
success: '✅',
warning: '⚠️',
error: '❌'
const toastIconMap: Record<ToastType, IconId> = {
success: 'success',
error: 'error',
warning: 'warning',
info: 'info'
};
</script>
@@ -25,9 +18,9 @@
<div
animate:flip={{ duration: 300 }}
transition:fly={{ x: 100, duration: 300 }}
class="alert {alertStyles[t.type]} shadow-lg min-w-[200px] flex justify-start"
class="alert bg-base-100 text-base-content border-0 shadow-base-300/50 shadow-lg min-w-[200px] flex justify-start"
>
<span>{icons[t.type]}</span>
<span><Icon id={toastIconMap[t.type]} size="24"></Icon></span>
<span>{t.message}</span>
</div>
{/each}

View File

@@ -120,4 +120,21 @@
<path fill="#ffffff" d="M 294.644531 174.898438 L 291.878906 170.023438 L 291.832031 170.023438 L 273.359375 138.019531 L 249.835938 97.03125 L 247.199219 92.507812 C 245.707031 89.945312 242.964844 88.371094 240.003906 88.371094 L 221.074219 88.371094 C 214.949219 88.371094 210.917969 94.753906 213.546875 100.285156 L 223.050781 120.25 C 223.140625 120.445312 223.242188 120.636719 223.351562 120.824219 L 243.175781 155.304688 L 251.59375 169.8125 C 257.941406 180.757812 257.964844 194.253906 251.660156 205.222656 L 244.746094 217.246094 L 244.5625 217.246094 L 242.058594 221.632812 C 238.851562 227.257812 230.734375 227.230469 227.558594 221.585938 L 155.027344 92.621094 C 153.550781 89.996094 150.773438 88.371094 147.765625 88.371094 L 135.160156 88.371094 C 132.257812 88.371094 129.5625 89.882812 128.050781 92.359375 L 125.230469 96.972656 L 101.675781 138.019531 L 78.15625 178.835938 C 75.042969 184.171875 75.003906 190.757812 78.050781 196.132812 L 78.132812 196.277344 L 81.566406 202.160156 L 101.675781 237.128906 L 125.203125 277.953125 L 127.835938 282.472656 C 129.332031 285.03125 132.070312 286.605469 135.035156 286.605469 L 156.164062 286.605469 C 162.601562 286.605469 166.609375 279.613281 163.351562 274.0625 L 151.742188 254.253906 L 131.859375 219.671875 L 121.308594 201.484375 C 116.289062 192.828125 116.289062 182.148438 121.308594 173.496094 L 131.851562 155.320312 L 133.03125 153.261719 C 136.242188 147.679688 144.296875 147.691406 147.492188 153.28125 L 221.234375 282.40625 C 222.71875 285.003906 225.476562 286.605469 228.46875 286.605469 L 240.003906 286.605469 C 242.964844 286.605469 245.707031 285.03125 247.199219 282.472656 L 249.820312 277.976562 L 273.363281 237.121094 L 296.882812 196.136719 C 299.996094 190.796875 300.015625 184.195312 296.921875 178.839844 L 294.644531 174.898438 " fill-opacity="1" fill-rule="nonzero"/>
</g>
</symbol>
<symbol id="info" viewBox="0 0 24 24">
<path fill="#3B82F6" d="M12 1.999c5.524 0 10.002 4.478 10.002 10.002c0 5.523-4.478 10.001-10.002 10.001S2 17.524 2 12.001C1.999 6.477 6.476 1.999 12 1.999" class="duoicon-secondary-layer" opacity="0.3" />
<path fill="#3B82F6" d="M12.001 6.5a1.252 1.252 0 1 0 .002 2.503A1.252 1.252 0 0 0 12 6.5zm-.005 3.749a1 1 0 0 0-.992.885l-.007.116l.004 5.502l.006.117a1 1 0 0 0 1.987-.002L13 16.75l-.004-5.501l-.007-.117a1 1 0 0 0-.994-.882z" class="duoicon-primary-layer" />
</symbol>
<symbol id="success" viewBox="0 0 24 24">
<path fill="#10B981" fill-rule="evenodd" d="M10.586 2.1a2 2 0 0 1 2.7-.116l.128.117L15.314 4H18a2 2 0 0 1 1.994 1.85L20 6v2.686l1.9 1.9a2 2 0 0 1 .116 2.701l-.117.127l-1.9 1.9V18a2 2 0 0 1-1.85 1.995L18 20h-2.685l-1.9 1.9a2 2 0 0 1-2.701.116l-.127-.116l-1.9-1.9H6a2 2 0 0 1-1.995-1.85L4 18v-2.686l-1.9-1.9a2 2 0 0 1-.116-2.701l.116-.127l1.9-1.9V6a2 2 0 0 1 1.85-1.994L6 4h2.686z" class="duoicon-secondary-layer" opacity="0.3" />
<path fill="#10B981" fill-rule="evenodd" d="m15.079 8.983l-4.244 4.244l-1.768-1.768a1 1 0 1 0-1.414 1.415l2.404 2.404a1.1 1.1 0 0 0 1.556 0l4.88-4.881a1 1 0 0 0-1.414-1.414" class="duoicon-primary-layer" />
</symbol>
<symbol id="warning" viewBox="0 0 24 24">
<path fill="#F59E0B" fill-rule="evenodd" d="M15.314 2a2 2 0 0 1 1.414.586l4.686 4.686A2 2 0 0 1 22 8.686v6.628a2 2 0 0 1-.586 1.414l-4.686 4.686a2 2 0 0 1-1.414.586H8.686a2 2 0 0 1-1.414-.586l-4.686-4.686A2 2 0 0 1 2 15.314V8.686a2 2 0 0 1 .586-1.414l4.686-4.686A2 2 0 0 1 8.686 2z" class="duoicon-secondary-layer" opacity="0.3" />
<path fill="#F59E0B" fill-rule="evenodd" d="M12 6a1 1 0 0 0-.993.883L11 7v6a1 1 0 0 0 1.993.117L13 13V7a1 1 0 0 0-1-1m0 9a1 1 0 1 0 0 2a1 1 0 0 0 0-2" class="duoicon-primary-layer" />
</symbol>
<symbol id="error" viewBox="0 0 24 24">
<path fill="#EF4444" d="m13.299 3.148l8.634 14.954a1.5 1.5 0 0 1-1.299 2.25H3.366a1.5 1.5 0 0 1-1.299-2.25l8.634-14.954c.577-1 2.02-1 2.598 0" class="duoicon-secondary-layer" opacity="0.3" />
<path fill="#EF4444" d="M12 8a1 1 0 0 0-.993.883L11 9v4a1 1 0 0 0 1.993.117L13 13V9a1 1 0 0 0-1-1m0 7a1 1 0 1 0 0 2a1 1 0 0 0 0-2" class="duoicon-primary-layer" />
</symbol>
</svg>

View File

@@ -7,5 +7,9 @@ export type IconId =
"starburst"|
"home"|
"menu"|
"logo"
"logo"|
"success"|
"error"|
"warning"|
"info"
;

View File

@@ -89,7 +89,7 @@
</a>
</div>
<ul class="menu menu-vertical transition-all duration-1000 w-full">
<ul class="menu pt-6 menu-vertical transition-all duration-1000 w-full">
{#each navItems as item(item.id)}
<li class="w-full {item.isActive ? 'menu-active' : ''}">
<a href={resolve(item.href)} onclick={handleMobileClose}>

View File

@@ -26,6 +26,7 @@
// await new Promise(r => setTimeout(r, 500));
await authService.login(loginPayload);
if (get(authStore).isAuthenticated) {
toast.success('登录成功,正在跳转到首页')
setTimeout( async () => {
@@ -34,9 +35,14 @@
}, 1000)
}
} catch (e) {
} catch (e:unknown) {
if (e instanceof Error) {
console.error(e);
// 这里建议加上一个 Toast 提示错误,比如 daisyUI 的 alert
toast.error(e.message);
} else {
console.error(e);
toast.error('登录失败,请重试');
}
} finally {
isLoading = false;
}