2026-04-21 22:07:29 +08:00
|
|
|
|
import client from './client'
|
|
|
|
|
|
|
|
|
|
|
|
export interface TenantItem {
|
|
|
|
|
|
id: string
|
|
|
|
|
|
username: string
|
|
|
|
|
|
nickname: string
|
|
|
|
|
|
email: string
|
|
|
|
|
|
phone?: string
|
|
|
|
|
|
type: 'MAIN' | 'SUB'
|
|
|
|
|
|
status: 'ACTIVE' | 'DISABLED' | 'PENDING_EMAIL'
|
|
|
|
|
|
parentId?: string
|
|
|
|
|
|
createdAt: string
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-01 21:27:39 +08:00
|
|
|
|
export interface TenantDetail extends TenantItem {
|
|
|
|
|
|
appCount: number
|
|
|
|
|
|
subAccountCount: number
|
|
|
|
|
|
activeServiceCount: number
|
|
|
|
|
|
apps: AppItem[]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-21 22:07:29 +08:00
|
|
|
|
export interface TenantPage {
|
|
|
|
|
|
content: TenantItem[]
|
|
|
|
|
|
total: number
|
|
|
|
|
|
totalPages: number
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-02 22:57:55 +08:00
|
|
|
|
export interface DailyTrendItem {
|
|
|
|
|
|
date: string
|
|
|
|
|
|
count: number
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-21 22:07:29 +08:00
|
|
|
|
export interface Statistics {
|
|
|
|
|
|
totalTenants: number
|
|
|
|
|
|
todayNew: number
|
|
|
|
|
|
activeApps: number
|
|
|
|
|
|
onlineUsers: number
|
2026-05-02 22:57:55 +08:00
|
|
|
|
dailyTrend: DailyTrendItem[]
|
|
|
|
|
|
serviceDistribution: Record<string, number>
|
2026-04-21 22:07:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-25 06:40:46 +08:00
|
|
|
|
export interface ServiceRequest {
|
|
|
|
|
|
id: string
|
|
|
|
|
|
appId: string
|
|
|
|
|
|
platform: string
|
|
|
|
|
|
serviceType: string
|
|
|
|
|
|
status: 'PENDING' | 'APPROVED' | 'REJECTED'
|
|
|
|
|
|
applyReason?: string
|
|
|
|
|
|
reviewNote?: string
|
|
|
|
|
|
createdAt: string
|
|
|
|
|
|
reviewedAt?: string
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export interface ServiceRequestPage {
|
|
|
|
|
|
content: ServiceRequest[]
|
|
|
|
|
|
total: number
|
|
|
|
|
|
totalPages: number
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-01 21:27:39 +08:00
|
|
|
|
export interface AppItem {
|
|
|
|
|
|
id: string
|
|
|
|
|
|
appKey: string
|
|
|
|
|
|
appSecret: string
|
|
|
|
|
|
name: string
|
|
|
|
|
|
packageName: string
|
|
|
|
|
|
tenantId: string
|
|
|
|
|
|
createdAt: string
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export interface FeatureServiceItem {
|
|
|
|
|
|
id: string
|
|
|
|
|
|
appId: string
|
|
|
|
|
|
platform: string
|
|
|
|
|
|
serviceType: string
|
|
|
|
|
|
enabled: boolean
|
|
|
|
|
|
config?: string | null
|
|
|
|
|
|
createdAt: string
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export interface AppDetail {
|
|
|
|
|
|
app: AppItem
|
|
|
|
|
|
tenant: TenantItem | null
|
|
|
|
|
|
services: FeatureServiceItem[]
|
|
|
|
|
|
serviceCount: number
|
|
|
|
|
|
enabledServiceCount: number
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export interface AppPage {
|
|
|
|
|
|
content: AppItem[]
|
|
|
|
|
|
total: number
|
|
|
|
|
|
totalPages: number
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export interface OpsLogItem {
|
|
|
|
|
|
id: string
|
|
|
|
|
|
tenantId: string
|
|
|
|
|
|
moduleType: string
|
|
|
|
|
|
resourceType: string
|
|
|
|
|
|
resourceId: string
|
|
|
|
|
|
action: string
|
|
|
|
|
|
operator: string
|
|
|
|
|
|
detailJson: string
|
|
|
|
|
|
createdAt: string
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export interface OpsLogPage {
|
|
|
|
|
|
content: OpsLogItem[]
|
|
|
|
|
|
total: number
|
|
|
|
|
|
totalPages: number
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export interface RiskRuleForm {
|
|
|
|
|
|
ipRateLimit: number
|
|
|
|
|
|
loginFailThreshold: number
|
|
|
|
|
|
loginLockMinutes: number
|
|
|
|
|
|
abnormalDetection: boolean
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export interface SensitiveWord {
|
|
|
|
|
|
id: string
|
|
|
|
|
|
word: string
|
|
|
|
|
|
level: '高' | '中' | '低'
|
|
|
|
|
|
category: string
|
|
|
|
|
|
enabled: boolean
|
|
|
|
|
|
updatedAt: string
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export interface SensitiveWordPage {
|
|
|
|
|
|
content: SensitiveWord[]
|
|
|
|
|
|
total: number
|
|
|
|
|
|
totalPages: number
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-05 17:54:59 +08:00
|
|
|
|
export interface PushDeviceInfo {
|
|
|
|
|
|
id: string
|
|
|
|
|
|
vendor: string
|
|
|
|
|
|
tokenPreview: string
|
|
|
|
|
|
platform?: string
|
|
|
|
|
|
deviceId: string
|
|
|
|
|
|
brand?: string
|
|
|
|
|
|
model?: string
|
|
|
|
|
|
osVersion?: string
|
|
|
|
|
|
appVersion?: string
|
|
|
|
|
|
receivePush: boolean
|
|
|
|
|
|
lastLoginAt: string
|
|
|
|
|
|
updatedAt: string
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export interface PushDiagnostics {
|
|
|
|
|
|
tokenType: 'PUSH' | 'IM' | 'UNKNOWN'
|
|
|
|
|
|
appId?: string
|
|
|
|
|
|
userId?: string
|
|
|
|
|
|
online: boolean
|
|
|
|
|
|
lastSeenAt: number
|
|
|
|
|
|
canSendOfflineMessage: boolean
|
|
|
|
|
|
deliverableDevice?: PushDeviceInfo | null
|
|
|
|
|
|
deliverableDevices: PushDeviceInfo[]
|
|
|
|
|
|
devices: PushDeviceInfo[]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export interface PushDeviceLog {
|
|
|
|
|
|
id: string
|
|
|
|
|
|
appId: string
|
|
|
|
|
|
userId: string
|
|
|
|
|
|
vendor: string
|
|
|
|
|
|
tokenPreview: string
|
|
|
|
|
|
platform?: string
|
|
|
|
|
|
deviceId: string
|
|
|
|
|
|
brand?: string
|
|
|
|
|
|
model?: string
|
|
|
|
|
|
osVersion?: string
|
|
|
|
|
|
appVersion?: string
|
|
|
|
|
|
receivePush: boolean
|
|
|
|
|
|
eventType: 'REGISTER' | 'UNREGISTER' | 'RECEIVE_PUSH_UPDATE'
|
|
|
|
|
|
createdAt: string
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export interface PushDeviceLogPage {
|
|
|
|
|
|
content: PushDeviceLog[]
|
|
|
|
|
|
total: number
|
|
|
|
|
|
totalPages: number
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export interface PushTestResult {
|
|
|
|
|
|
appId: string
|
|
|
|
|
|
userId: string
|
|
|
|
|
|
sent: boolean
|
|
|
|
|
|
targetCount: number
|
|
|
|
|
|
targets: PushDeviceInfo[]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-21 22:07:29 +08:00
|
|
|
|
export const opsApi = {
|
|
|
|
|
|
listTenants: (keyword = '', page = 0, size = 20) =>
|
|
|
|
|
|
client.get<{ data: TenantPage }>('/ops/tenants', { params: { keyword, page, size } }),
|
|
|
|
|
|
|
|
|
|
|
|
toggleStatus: (id: string) =>
|
|
|
|
|
|
client.post(`/ops/tenants/${id}/toggle-status`),
|
|
|
|
|
|
|
2026-05-01 21:27:39 +08:00
|
|
|
|
getTenant: (id: string) =>
|
|
|
|
|
|
client.get<{ data: TenantDetail }>(`/ops/tenants/${id}`),
|
|
|
|
|
|
|
|
|
|
|
|
listTenantApps: (id: string) =>
|
|
|
|
|
|
client.get<{ data: AppItem[] }>(`/ops/tenants/${id}/apps`),
|
|
|
|
|
|
|
2026-04-21 22:07:29 +08:00
|
|
|
|
statistics: () =>
|
|
|
|
|
|
client.get<{ data: Statistics }>('/ops/statistics'),
|
2026-04-25 06:40:46 +08:00
|
|
|
|
|
|
|
|
|
|
listServiceRequests: (status = '', page = 0, size = 20) =>
|
|
|
|
|
|
client.get<{ data: ServiceRequestPage }>('/ops/service-requests', { params: { status, page, size } }),
|
|
|
|
|
|
|
|
|
|
|
|
approveRequest: (requestId: string, reviewNote = '') =>
|
|
|
|
|
|
client.post<{ data: ServiceRequest }>(`/ops/service-requests/${requestId}/approve`, { reviewNote }),
|
|
|
|
|
|
|
|
|
|
|
|
rejectRequest: (requestId: string, reviewNote = '') =>
|
|
|
|
|
|
client.post<{ data: ServiceRequest }>(`/ops/service-requests/${requestId}/reject`, { reviewNote }),
|
2026-05-01 21:27:39 +08:00
|
|
|
|
|
|
|
|
|
|
listApps: (keyword = '', page = 0, size = 20) =>
|
|
|
|
|
|
client.get<{ data: AppPage }>('/ops/apps', { params: { keyword, page, size } }),
|
|
|
|
|
|
|
|
|
|
|
|
getApp: (id: string) =>
|
|
|
|
|
|
client.get<{ data: AppDetail }>(`/ops/apps/${id}`),
|
|
|
|
|
|
|
|
|
|
|
|
listAppServices: (id: string) =>
|
|
|
|
|
|
client.get<{ data: FeatureServiceItem[] }>(`/ops/apps/${id}/services`),
|
|
|
|
|
|
|
|
|
|
|
|
listOperationLogs: (page = 0, size = 20) =>
|
|
|
|
|
|
client.get<{ data: OpsLogPage }>('/ops/operation-logs', { params: { page, size } }),
|
|
|
|
|
|
|
|
|
|
|
|
// 风控相关 API(mock 实现,TODO:接入后端)
|
|
|
|
|
|
getRiskRules: () =>
|
|
|
|
|
|
client.get<{ data: RiskRuleForm }>('/ops/risk/rules'),
|
|
|
|
|
|
|
|
|
|
|
|
saveRiskRules: (rules: RiskRuleForm) =>
|
|
|
|
|
|
client.post('/ops/risk/rules', rules),
|
|
|
|
|
|
|
|
|
|
|
|
listSensitiveWords: (page = 0, size = 20) =>
|
|
|
|
|
|
client.get<{ data: SensitiveWordPage }>('/ops/risk/sensitive-words', { params: { page, size } }),
|
|
|
|
|
|
|
|
|
|
|
|
createSensitiveWord: (word: Omit<SensitiveWord, 'id' | 'updatedAt'>) =>
|
|
|
|
|
|
client.post<{ data: SensitiveWord }>('/ops/risk/sensitive-words', word),
|
|
|
|
|
|
|
|
|
|
|
|
updateSensitiveWord: (id: string, word: Partial<SensitiveWord>) =>
|
|
|
|
|
|
client.put<{ data: SensitiveWord }>(`/ops/risk/sensitive-words/${id}`, word),
|
|
|
|
|
|
|
|
|
|
|
|
toggleSensitiveWord: (id: string, enabled: boolean) =>
|
|
|
|
|
|
client.patch(`/ops/risk/sensitive-words/${id}/toggle`, { enabled }),
|
|
|
|
|
|
|
|
|
|
|
|
deleteSensitiveWord: (id: string) =>
|
|
|
|
|
|
client.delete(`/ops/risk/sensitive-words/${id}`),
|
2026-05-05 17:54:59 +08:00
|
|
|
|
|
|
|
|
|
|
searchPushByToken: (token: string, appId = '') =>
|
|
|
|
|
|
client.get<{ data: PushDiagnostics }>('/ops/push/search', { params: { token, appId } }),
|
|
|
|
|
|
|
|
|
|
|
|
listPushDeviceLogs: (appId: string, userId: string, page = 0, size = 20) =>
|
|
|
|
|
|
client.get<{ data: PushDeviceLogPage }>('/ops/push/device-logs', { params: { appId, userId, page, size } }),
|
|
|
|
|
|
|
|
|
|
|
|
sendPushTestOffline: (payload: { appId: string; userId: string; title: string; body: string; payload?: string }) =>
|
|
|
|
|
|
client.post<{ data: PushTestResult }>('/ops/push/test-offline', payload),
|
2026-04-21 22:07:29 +08:00
|
|
|
|
}
|