fix:通知和设备分配/回收
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 4m49s
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 4m49s
This commit is contained in:
@@ -3,9 +3,7 @@
|
||||
<div class="notice" @click.stop>
|
||||
<div class="header">
|
||||
<span class="text">通知</span>
|
||||
<button class="read-all" type="button" @click="handleMarkAllRead">
|
||||
全部已读
|
||||
</button>
|
||||
<button class="read-all" type="button" @click="handleMarkAllRead">全部已读</button>
|
||||
</div>
|
||||
|
||||
<div class="bar">
|
||||
@@ -119,7 +117,7 @@
|
||||
ElMessage.info(item.body || '该通知暂无可跳转目标')
|
||||
return
|
||||
}
|
||||
if (!navigateNotificationTarget(router, targetResponse.data)) {
|
||||
if (!navigateNotificationTarget(router, item.ref_type, targetResponse.data)) {
|
||||
ElMessage.info(item.body || '该通知暂无可跳转目标')
|
||||
} else {
|
||||
close()
|
||||
|
||||
@@ -739,7 +739,7 @@ export const asyncRoutes: AppRouteRecord[] = [
|
||||
{
|
||||
path: 'agent-fund-overview',
|
||||
name: 'AgentFundOverview',
|
||||
component: RoutesAlias.AgentFundOverview,
|
||||
component: RoutesAlias.AgentFundOverviewComponent,
|
||||
meta: {
|
||||
title: 'menus.commission.agentCommission',
|
||||
keepAlive: true,
|
||||
|
||||
@@ -89,7 +89,8 @@ export enum RoutesAlias {
|
||||
// 佣金管理
|
||||
WithdrawalApproval = '/commission-management/withdrawal-approval', // 提现审批
|
||||
MyCommission = '/commission-management/my-commission', // 我的佣金
|
||||
AgentFundOverview = '/commission-management/agent-fund-overview', // 代理商资金概况
|
||||
AgentFundOverview = '/commission/agent-fund-overview', // 代理商资金概况
|
||||
AgentFundOverviewComponent = '/commission-management/agent-fund-overview', // 代理商资金概况组件路径
|
||||
|
||||
// 设置管理
|
||||
WithdrawalSettings = '/settings/withdrawal-settings', // 提现配置
|
||||
|
||||
@@ -1,6 +1,22 @@
|
||||
export type NotificationCategory = 'approval' | 'expiry' | 'sync' | 'system' | string
|
||||
export type NotificationSeverity = 'info' | 'warning' | 'error' | 'critical' | string
|
||||
|
||||
/** 后台通知引用的受控资源类型。 */
|
||||
export type NotificationRefType =
|
||||
| 'system_config'
|
||||
| 'integration_log'
|
||||
| 'package'
|
||||
| 'asset'
|
||||
| 'refund'
|
||||
| 'agent_recharge'
|
||||
| 'wecom_approval'
|
||||
| 'iot_card'
|
||||
| 'device'
|
||||
| 'expiring_asset'
|
||||
| 'shop_fund'
|
||||
| 'card_sync'
|
||||
| (string & {})
|
||||
|
||||
export interface NotificationItem {
|
||||
id: number
|
||||
title: string
|
||||
@@ -11,7 +27,7 @@ export interface NotificationItem {
|
||||
is_read: boolean
|
||||
created_at: string
|
||||
read_at: string | null
|
||||
ref_type: string | null
|
||||
ref_type: NotificationRefType | null
|
||||
ref_id: string | null
|
||||
ref_key: string | null
|
||||
}
|
||||
@@ -63,7 +79,7 @@ export interface NotificationReadAllResponse {
|
||||
|
||||
export interface NotificationTarget {
|
||||
available: boolean
|
||||
target_id: number | null
|
||||
target_id: number | string | null
|
||||
target_key: string
|
||||
target_type: string
|
||||
}
|
||||
|
||||
@@ -1,70 +1,56 @@
|
||||
import type { Router } from 'vue-router'
|
||||
import type { NotificationTarget } from '@/types/api'
|
||||
import type { RouteLocationRaw, Router } from 'vue-router'
|
||||
import type { NotificationRefType, NotificationTarget } from '@/types/api'
|
||||
import { RoutesAlias } from '@/router/routesAlias'
|
||||
|
||||
type TargetRoute = {
|
||||
path: string
|
||||
query?: Record<string, string>
|
||||
type TargetRoute = RouteLocationRaw
|
||||
|
||||
const resolveTargetRoute = (
|
||||
refType: NotificationRefType | null,
|
||||
target: NotificationTarget
|
||||
): TargetRoute | null => {
|
||||
const targetId = target.target_id === null ? '' : String(target.target_id)
|
||||
|
||||
switch (refType) {
|
||||
case 'system_config':
|
||||
return { path: RoutesAlias.SystemConfigs }
|
||||
case 'refund':
|
||||
return { path: RoutesAlias.RefundManagement }
|
||||
case 'agent_recharge':
|
||||
return { path: RoutesAlias.AgentRecharge }
|
||||
case 'iot_card':
|
||||
return targetId ? { path: RoutesAlias.AssetInformation, query: { iccid: targetId } } : null
|
||||
case 'device':
|
||||
return targetId
|
||||
? { path: RoutesAlias.AssetInformation, query: { virtual_no: targetId } }
|
||||
: null
|
||||
case 'expiring_asset':
|
||||
return { path: RoutesAlias.ExpiringAssets }
|
||||
case 'shop_fund':
|
||||
return { path: RoutesAlias.AgentFundOverview }
|
||||
case 'integration_log':
|
||||
case 'package':
|
||||
case 'asset':
|
||||
case 'wecom_approval':
|
||||
case 'card_sync':
|
||||
default:
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
const resolveTargetRoute = (target: NotificationTarget): TargetRoute | null => {
|
||||
const targetId = target.target_id === null ? undefined : String(target.target_id)
|
||||
const targetKey = target.target_key || ''
|
||||
|
||||
if (target.target_type === 'refund_detail' && targetId) {
|
||||
return { path: `${RoutesAlias.RefundDetail}/${targetId}` }
|
||||
export const navigateNotificationTarget = (
|
||||
router: Router,
|
||||
refType: NotificationRefType | null,
|
||||
target?: NotificationTarget | null
|
||||
) => {
|
||||
if (!target) return false
|
||||
if (!target.available) {
|
||||
void router.push(RoutesAlias.Exception403)
|
||||
return true
|
||||
}
|
||||
|
||||
if (target.target_type === 'agent_recharge_detail' && targetId) {
|
||||
return { path: `${RoutesAlias.AgentRechargeDetail}/${targetId}` }
|
||||
}
|
||||
|
||||
if (target.target_type === 'iot_card_detail' && (targetKey || targetId)) {
|
||||
return {
|
||||
path: RoutesAlias.AssetInformation,
|
||||
query: { iccid: targetKey || targetId || '' }
|
||||
}
|
||||
}
|
||||
|
||||
if (target.target_type === 'device_detail' && (targetKey || targetId)) {
|
||||
return {
|
||||
path: RoutesAlias.AssetInformation,
|
||||
query: { virtual_no: targetKey || targetId || '' }
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
target.target_type === 'expiring_asset_list' ||
|
||||
target.target_key === 'expiring_assets' ||
|
||||
target.target_key === 'expiring_asset_list'
|
||||
) {
|
||||
return { path: RoutesAlias.ExpiringAssets }
|
||||
}
|
||||
|
||||
if (target.target_type === 'shop_fund_summary') {
|
||||
return {
|
||||
path: RoutesAlias.AgentFundOverview,
|
||||
query: targetId ? { shop_id: targetId } : undefined
|
||||
}
|
||||
}
|
||||
|
||||
if (target.target_type === 'system_config') {
|
||||
return {
|
||||
path: RoutesAlias.SystemConfigs,
|
||||
query: targetKey ? { config_key: targetKey } : undefined
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export const navigateNotificationTarget = (router: Router, target?: NotificationTarget | null) => {
|
||||
if (!target?.available) return false
|
||||
const route = resolveTargetRoute(target)
|
||||
const route = resolveTargetRoute(refType, target)
|
||||
if (!route) return false
|
||||
|
||||
const resolved = router.resolve({ path: route.path, query: route.query })
|
||||
if (!resolved.matched.length || resolved.name === 'Exception404') return false
|
||||
void router.push(resolved)
|
||||
void router.push(route)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -831,15 +831,20 @@
|
||||
try {
|
||||
const response = await CardService.setSpeedTier(iccid, data.code)
|
||||
if (response.code !== 0) {
|
||||
speedLimitDialogVisible.value = false
|
||||
await nextTick()
|
||||
ElMessage.error(response.msg || '限速设置失败')
|
||||
return
|
||||
}
|
||||
|
||||
ElMessage.success(`限速设置成功:${response.data.speed_tier_name}`)
|
||||
speedLimitDialogVisible.value = false
|
||||
await nextTick()
|
||||
ElMessage.success(`限速设置成功:${response.data.speed_tier_name}`)
|
||||
await handleRefresh()
|
||||
} catch (error) {
|
||||
console.error('设置限速失败:', error)
|
||||
speedLimitDialogVisible.value = false
|
||||
await nextTick()
|
||||
ElMessage.error(normalizeApiError(error).message)
|
||||
} finally {
|
||||
speedTierSubmitting.value = false
|
||||
|
||||
@@ -17,6 +17,21 @@
|
||||
@refresh="handleRefresh"
|
||||
>
|
||||
<template #left>
|
||||
<ElButton
|
||||
type="primary"
|
||||
@click="handleBatchAllocate"
|
||||
:disabled="!selectedDevices.length"
|
||||
v-permission="'device:batch_allocate'"
|
||||
>
|
||||
批量分配
|
||||
</ElButton>
|
||||
<ElButton
|
||||
@click="handleBatchRecall"
|
||||
:disabled="!selectedDevices.length"
|
||||
v-permission="'device:batch_recall'"
|
||||
>
|
||||
批量回收
|
||||
</ElButton>
|
||||
<ElButton
|
||||
type="primary"
|
||||
:disabled="!selectedDevices.length"
|
||||
@@ -2350,6 +2365,19 @@
|
||||
})
|
||||
}
|
||||
|
||||
// 批量分配(设备列表原有操作,和设备批量任务页面并行保留)
|
||||
const handleBatchAllocate = async () => {
|
||||
if (selectedDevices.value.length === 0) {
|
||||
ElMessage.warning('请先选择要分配的设备')
|
||||
return
|
||||
}
|
||||
allocateForm.target_shop_id = undefined
|
||||
allocateForm.remark = ''
|
||||
allocateResult.value = null
|
||||
shopCascadeOptions.value = []
|
||||
allocateDialogVisible.value = true
|
||||
}
|
||||
|
||||
// 确认批量分配
|
||||
const handleConfirmAllocate = async () => {
|
||||
if (!allocateFormRef.value) return
|
||||
@@ -2400,6 +2428,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 批量回收(设备列表原有操作,和设备批量任务页面并行保留)
|
||||
const handleBatchRecall = () => {
|
||||
if (selectedDevices.value.length === 0) {
|
||||
ElMessage.warning('请先选择要回收的设备')
|
||||
return
|
||||
}
|
||||
recallForm.remark = ''
|
||||
recallResult.value = null
|
||||
recallDialogVisible.value = true
|
||||
}
|
||||
|
||||
// 确认批量回收
|
||||
const handleConfirmRecall = async () => {
|
||||
recallLoading.value = true
|
||||
|
||||
Reference in New Issue
Block a user