🔱: [client] sync upgrade with 7 commits [trident-sync]

chore:
Merge branch 'vben'

# Conflicts:
#	package.json
perf: antdv示例改成使用vben框架
chore: vben
chore: vben
chore: vben
This commit is contained in:
GitHub Actions Bot
2025-03-03 19:24:51 +00:00
parent de26ee9383
commit 335d175d57
649 changed files with 36984 additions and 826 deletions
@@ -0,0 +1,153 @@
<script lang="ts" setup>
import type { NotificationItem } from "./types";
import { Bell, MailCheck } from "/@/vben/icons";
import { $t } from "/@/vben/locales";
import { VbenButton, VbenIconButton, VbenPopover, VbenScrollbar } from "/@/vben//shadcn-ui";
import { useToggle } from "@vueuse/core";
interface Props {
/**
* 显示圆点
*/
dot?: boolean;
/**
* 消息列表
*/
notifications?: NotificationItem[];
}
defineOptions({ name: "NotificationPopup" });
withDefaults(defineProps<Props>(), {
dot: false,
notifications: () => []
});
const emit = defineEmits<{
clear: [];
makeAll: [];
read: [NotificationItem];
viewAll: [];
}>();
const [open, toggle] = useToggle();
function close() {
open.value = false;
}
function handleViewAll() {
emit("viewAll");
close();
}
function handleMakeAll() {
emit("makeAll");
}
function handleClear() {
emit("clear");
}
function handleClick(item: NotificationItem) {
emit("read", item);
}
</script>
<template>
<VbenPopover v-model:open="open" content-class="relative right-2 w-[360px] p-0">
<template #trigger>
<div class="flex-center mr-2 h-full" @click.stop="toggle()">
<VbenIconButton class="bell-button text-foreground relative">
<span v-if="dot" class="bg-primary absolute right-0.5 top-0.5 h-2 w-2 rounded"></span>
<Bell class="size-4" />
</VbenIconButton>
</div>
</template>
<div class="relative">
<div class="flex items-center justify-between p-4 py-3">
<div class="text-foreground">{{ $t("ui.widgets.notifications") }}</div>
<VbenIconButton :disabled="notifications.length <= 0" :tooltip="$t('ui.widgets.markAllAsRead')" @click="handleMakeAll">
<MailCheck class="size-4" />
</VbenIconButton>
</div>
<VbenScrollbar v-if="notifications.length > 0">
<ul class="!flex max-h-[360px] w-full flex-col">
<template v-for="item in notifications" :key="item.title">
<li class="hover:bg-accent border-border relative flex w-full cursor-pointer items-start gap-5 border-t px-3 py-3" @click="handleClick(item)">
<span v-if="!item.isRead" class="bg-primary absolute right-2 top-2 h-2 w-2 rounded"></span>
<span class="relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full">
<img :src="item.avatar" class="aspect-square h-full w-full object-cover" role="img" />
</span>
<div class="flex flex-col gap-1 leading-none">
<p class="font-semibold">{{ item.title }}</p>
<p class="text-muted-foreground my-1 line-clamp-2 text-xs">
{{ item.message }}
</p>
<p class="text-muted-foreground line-clamp-2 text-xs">
{{ item.date }}
</p>
</div>
</li>
</template>
</ul>
</VbenScrollbar>
<template v-else>
<div class="flex-center text-muted-foreground min-h-[150px] w-full">
{{ $t("common.noData") }}
</div>
</template>
<div class="border-border flex items-center justify-between border-t px-4 py-3">
<VbenButton :disabled="notifications.length <= 0" size="sm" variant="ghost" @click="handleClear">
{{ $t("ui.widgets.clearNotifications") }}
</VbenButton>
<VbenButton size="sm" @click="handleViewAll">
{{ $t("ui.widgets.viewAll") }}
</VbenButton>
</div>
</div>
</VbenPopover>
</template>
<style scoped>
:deep(.bell-button) {
&:hover {
svg {
animation: bell-ring 1s both;
}
}
}
@keyframes bell-ring {
0%,
100% {
transform-origin: top;
}
15% {
transform: rotateZ(10deg);
}
30% {
transform: rotateZ(-10deg);
}
45% {
transform: rotateZ(5deg);
}
60% {
transform: rotateZ(-5deg);
}
75% {
transform: rotateZ(2deg);
}
}
</style>