This commit is contained in:
137
src/utils/business/audit.ts
Normal file
137
src/utils/business/audit.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
import type {
|
||||
AuditActorKind,
|
||||
AuditCategory,
|
||||
AuditResult,
|
||||
AuditRiskLevel,
|
||||
AuditScopeType,
|
||||
AuditSource,
|
||||
IntegrationResultCategory
|
||||
} from '@/types/api'
|
||||
|
||||
export const auditCategoryLabels: Record<AuditCategory, string> = {
|
||||
configuration: '配置',
|
||||
reliability: '可靠性',
|
||||
asset: '资产',
|
||||
security: '安全',
|
||||
identity: '身份',
|
||||
business: '业务'
|
||||
}
|
||||
|
||||
export const auditActorKindLabels: Record<AuditActorKind, string> = {
|
||||
account: '人工账号',
|
||||
personal_customer: '个人客户',
|
||||
openapi: '开放接口账号',
|
||||
system_task: '系统任务',
|
||||
scheduled_job: '计划任务',
|
||||
external_system: '外部系统'
|
||||
}
|
||||
|
||||
export const auditScopeTypeLabels: Record<AuditScopeType, string> = {
|
||||
platform: '平台',
|
||||
shop: '店铺',
|
||||
personal_customer: '个人客户'
|
||||
}
|
||||
|
||||
export const auditSourceLabels: Record<AuditSource, string> = {
|
||||
admin_api: '后台管理 API',
|
||||
personal_api: '个人客户 API',
|
||||
openapi: '代理 OpenAPI',
|
||||
worker: '异步 Worker',
|
||||
scheduler: '计划任务',
|
||||
callback: '外部系统回调'
|
||||
}
|
||||
|
||||
export const auditResourceRelationLabels: Record<string, string> = {
|
||||
primary: '主要资源',
|
||||
affected: '受影响资源',
|
||||
reference: '引用资源'
|
||||
}
|
||||
|
||||
export const auditSubjectVisibilityLabels: Record<string, string> = {
|
||||
internal_only: '仅平台可见',
|
||||
subject_result: '主体可见结论',
|
||||
subject_detail: '主体可见安全详情'
|
||||
}
|
||||
|
||||
export const auditResourceTypeLabels: Record<string, string> = {
|
||||
iot_card: 'IoT 卡',
|
||||
device: '设备',
|
||||
asset_allocation_record: '资产分配记录',
|
||||
exchange_order: '换卡订单',
|
||||
shop: '店铺',
|
||||
enterprise: '企业',
|
||||
order: '订单',
|
||||
refund: '退款',
|
||||
integration_log: '外部集成记录'
|
||||
}
|
||||
|
||||
export const auditResultMeta: Record<
|
||||
AuditResult,
|
||||
{ label: string; type: 'success' | 'danger' | 'warning' | 'info' }
|
||||
> = {
|
||||
success: { label: '成功', type: 'success' },
|
||||
failed: { label: '失败', type: 'danger' },
|
||||
denied: { label: '拒绝', type: 'danger' },
|
||||
partial: { label: '部分成功', type: 'warning' },
|
||||
unknown: { label: '未知', type: 'info' }
|
||||
}
|
||||
|
||||
const auditResultLabels: Record<string, string> = {
|
||||
success: '成功',
|
||||
failed: '失败',
|
||||
denied: '拒绝',
|
||||
partial: '部分成功',
|
||||
unknown: '未知',
|
||||
pending: '处理中',
|
||||
not_found: '未找到',
|
||||
invalid_payload: '无效载荷',
|
||||
conflict: '冲突',
|
||||
ignored: '已忽略',
|
||||
merged: '已合并',
|
||||
rate_limited: '已限流',
|
||||
completed: '已完成',
|
||||
cancelled: '已取消'
|
||||
}
|
||||
|
||||
export function auditResultDisplay(result?: string | null, resultName?: string | null): string {
|
||||
const name = resultName?.trim()
|
||||
if (name) return name
|
||||
return result ? auditResultLabels[result] || result : '-'
|
||||
}
|
||||
|
||||
export const auditRiskMeta: Record<
|
||||
AuditRiskLevel,
|
||||
{ label: string; type: 'success' | 'danger' | 'warning' | 'info' }
|
||||
> = {
|
||||
low: { label: '低', type: 'success' },
|
||||
normal: { label: '普通', type: 'info' },
|
||||
high: { label: '高', type: 'warning' },
|
||||
critical: { label: '严重', type: 'danger' }
|
||||
}
|
||||
|
||||
export const integrationCategoryMeta: Record<
|
||||
IntegrationResultCategory,
|
||||
{ label: string; type: 'success' | 'danger' | 'warning' | 'info' }
|
||||
> = {
|
||||
processing: { label: '处理中', type: 'warning' },
|
||||
succeeded: { label: '成功', type: 'success' },
|
||||
indeterminate: { label: '结果不确定', type: 'warning' },
|
||||
failed: { label: '失败', type: 'danger' },
|
||||
not_sent: { label: '未发送', type: 'info' }
|
||||
}
|
||||
|
||||
export function toRfc3339(value?: string | Date | null): string | undefined {
|
||||
if (!value) return undefined
|
||||
const date = value instanceof Date ? value : new Date(value)
|
||||
return Number.isNaN(date.getTime()) ? undefined : date.toISOString()
|
||||
}
|
||||
|
||||
export function fenDisplay(value?: number | null): string {
|
||||
return typeof value === 'number' ? `¥${(value / 100).toFixed(2)}` : '-'
|
||||
}
|
||||
|
||||
export function auditJson(value: unknown): string {
|
||||
if (value === null || value === undefined) return '-'
|
||||
if (typeof value === 'string') return value
|
||||
return JSON.stringify(value, null, 2)
|
||||
}
|
||||
69
src/utils/business/auditNavigation.ts
Normal file
69
src/utils/business/auditNavigation.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import type { AuditSubjectResourceType } from '@/types/api'
|
||||
import type { AuditFinanceField, AuditInvestigationTarget } from '@/components/business/audit/types'
|
||||
|
||||
interface AuditResourceRouteOptions {
|
||||
userType?: number
|
||||
resourceType: AuditSubjectResourceType | string
|
||||
internalId?: string | number | null
|
||||
businessIdentifier?: string | null
|
||||
}
|
||||
|
||||
/** 根据当前主体选择平台内部 ID 或主体安全业务标识。 */
|
||||
export function resolveAuditResourceTarget(
|
||||
options: AuditResourceRouteOptions
|
||||
): AuditInvestigationTarget | null {
|
||||
const { userType, resourceType, internalId, businessIdentifier } = options
|
||||
const normalizedBusinessIdentifier = businessIdentifier?.trim()
|
||||
if (userType === 3) {
|
||||
if (
|
||||
!normalizedBusinessIdentifier ||
|
||||
![
|
||||
'iot_card',
|
||||
'device',
|
||||
'asset_allocation_record',
|
||||
'exchange_order',
|
||||
'shop',
|
||||
'enterprise'
|
||||
].includes(resourceType)
|
||||
)
|
||||
return null
|
||||
return {
|
||||
mode: 'agent',
|
||||
resourceType: resourceType as AuditSubjectResourceType,
|
||||
id: normalizedBusinessIdentifier
|
||||
}
|
||||
}
|
||||
if (userType === 4) {
|
||||
if (!normalizedBusinessIdentifier || !['iot_card', 'device'].includes(resourceType)) return null
|
||||
return {
|
||||
mode: 'enterprise',
|
||||
resourceType: resourceType as AuditSubjectResourceType,
|
||||
id: normalizedBusinessIdentifier
|
||||
}
|
||||
}
|
||||
if (
|
||||
internalId === undefined ||
|
||||
internalId === null ||
|
||||
internalId === '' ||
|
||||
(typeof internalId === 'string' && !internalId.trim()) ||
|
||||
(typeof internalId === 'number' && (!Number.isFinite(internalId) || internalId <= 0))
|
||||
)
|
||||
return null
|
||||
return { mode: 'resource', resourceType, id: String(internalId).trim() }
|
||||
}
|
||||
|
||||
export function resolveFinanceAuditTarget(
|
||||
field: AuditFinanceField,
|
||||
value?: string | number | null
|
||||
): AuditInvestigationTarget | null {
|
||||
const normalizedValue = typeof value === 'string' ? value.trim() : value
|
||||
if (
|
||||
normalizedValue === undefined ||
|
||||
normalizedValue === null ||
|
||||
normalizedValue === '' ||
|
||||
(typeof normalizedValue === 'number' &&
|
||||
(!Number.isFinite(normalizedValue) || normalizedValue <= 0))
|
||||
)
|
||||
return null
|
||||
return { mode: 'finance', field, value: normalizedValue }
|
||||
}
|
||||
@@ -9,8 +9,16 @@ const resolveTargetRoute = (
|
||||
target: NotificationTarget
|
||||
): TargetRoute | null => {
|
||||
const targetId = target.target_id === null ? '' : String(target.target_id)
|
||||
const targetType = target.target_type || refType
|
||||
|
||||
switch (refType) {
|
||||
if (targetType === 'integration_log') {
|
||||
const integrationId = target.target_key?.trim()
|
||||
return integrationId
|
||||
? { path: `/audit/integrations/${encodeURIComponent(integrationId)}` }
|
||||
: null
|
||||
}
|
||||
|
||||
switch (targetType) {
|
||||
case 'system_config':
|
||||
return { path: RoutesAlias.SystemConfigs }
|
||||
case 'refund':
|
||||
@@ -27,7 +35,6 @@ const resolveTargetRoute = (
|
||||
return { path: RoutesAlias.ExpiringAssets }
|
||||
case 'shop_fund':
|
||||
return { path: RoutesAlias.AgentFundOverview }
|
||||
case 'integration_log':
|
||||
case 'package':
|
||||
case 'asset':
|
||||
case 'wecom_approval':
|
||||
|
||||
Reference in New Issue
Block a user