feat(shopDashboard): 为 Dashboard 添加新订单声音提醒功能

- 将 useOrderNotify 改造为实例安全的 Composable,支持多个页面独立调用
- 在 shop/dashboard 和 cms/dashboard 页面添加新订单提醒开关和测试按钮
- 新订单提醒触发时自动刷新 Dashboard 数据,提升数据同步性
- 新订单提醒包括叮声和语音播报,用户交互后自动解锁音频播放
- cms/dashboard 概况卡片标题添加提醒控件,shop/dashboard 欢迎横幅右侧添加提醒栏
- 提取 cms/dashboard loadData 函数实现复用,统一数据加载逻辑
- 优化组件状态管理,防止多个实例间状态冲突,提升稳定性和可维护性
This commit is contained in:
2026-07-14 20:58:40 +08:00
parent a2640ba7dc
commit 5106fe101c
4 changed files with 192 additions and 244 deletions

View File

@@ -7,13 +7,23 @@
<p class="welcome-sub">欢迎回来管理员今日数据已更新</p>
</div>
<div class="welcome-right">
<a-space>
<a-tag color="green" style="font-size:13px;padding:4px 12px">{{ siteStore.statusText || '正常' }}</a-tag>
<a-button size="small" @click="refreshStatistics" :loading="loading">
<template #icon><ReloadOutlined /></template>
刷新数据
</a-button>
</a-space>
<div class="welcome-actions">
<div class="order-notify-bar">
<span class="order-notify-label">新订单提醒</span>
<a-switch v-model:checked="notifyEnabled" @change="onNotifyToggle" size="small" />
<a-tooltip title="开启后每60秒自动检测新订单检测到后播放叮声并语音播报">
<InfoCircleOutlined class="order-notify-info" />
</a-tooltip>
<a-button size="small" :disabled="!notifyEnabled" @click="onTestNotify">测试</a-button>
</div>
<a-space>
<a-tag color="green" style="font-size:13px;padding:4px 12px">{{ siteStore.statusText || '正常' }}</a-tag>
<a-button size="small" @click="refreshStatistics" :loading="loading">
<template #icon><ReloadOutlined /></template>
刷新数据
</a-button>
</a-space>
</div>
</div>
</div>
@@ -207,6 +217,7 @@
<script lang="ts" setup>
import { reactive, ref, computed, onMounted, onUnmounted } from 'vue';
import { useRouter } from 'vue-router';
import { useOrderNotify } from '@/views/shop/shopOrder/useOrderNotify';
import {
ReloadOutlined,
RightOutlined,
@@ -215,7 +226,8 @@ import {
UserOutlined,
ShopOutlined,
FileTextOutlined,
ClearOutlined
ClearOutlined,
InfoCircleOutlined
} from '@ant-design/icons-vue';
import { message } from 'ant-design-vue/es';
import { useSiteStore } from '@/store/modules/site';
@@ -318,6 +330,11 @@ const handleClearCache = () => {
);
};
// 新订单声音提醒
const { enabled: notifyEnabled, toggle: onNotifyToggle, testNotify: onTestNotify } = useOrderNotify({
onNewOrder: () => loadData()
});
// 刷新统计数据
const refreshStatistics = async () => {
try {
@@ -405,6 +422,34 @@ onUnmounted(() => {
.welcome-title { font-size: 20px; font-weight: 700; color: #fff; margin: 0 0 6px; }
.welcome-sub { font-size: 14px; color: rgba(255,255,255,0.7); margin: 0; }
/* 欢迎横幅右侧操作区 */
.welcome-actions {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 8px;
}
/* 新订单提醒栏 */
.order-notify-bar {
display: flex;
align-items: center;
gap: 8px;
background: rgba(255,255,255,0.12);
border-radius: 8px;
padding: 5px 12px;
}
.order-notify-label {
font-size: 13px;
color: rgba(255,255,255,0.85);
white-space: nowrap;
}
.order-notify-info {
color: rgba(255,255,255,0.6);
font-size: 14px;
cursor: help;
}
/* 核心统计块 */
.stat-block {
padding: 18px 20px;