feat(business): 添加业务模块前后端服务

后端Controllers:
- AuditController: 审计日志API
- SystemController: 系统配置API
- RewardController: 奖励管理API
- RiskController: 风险管理API

前端Services:
- activity.ts: 活动管理服务
- user管理服务
-Manage.ts: 用户 reward.ts: 奖励管理服务
- risk.ts: 风险管理服务
- audit.ts: 审计日志服务
- systemConfig.ts: 系统配置服务
- activity.ts: 活动类型定义
This commit is contained in:
Your Name
2026-03-05 11:04:33 +08:00
parent 6d0922fb44
commit 7913bb5a34
11 changed files with 1760 additions and 0 deletions

View File

@@ -0,0 +1,206 @@
/**
* 活动管理服务
*/
import type { Activity } from '../types/activity'
export interface ApiResponse<T> {
code: number
data: T
message?: string
}
export interface ActivityListQuery {
page?: number
size?: number
status?: string
keyword?: string
startDate?: string
endDate?: string
}
class ActivityService {
private baseUrl = '/api'
/**
* 获取活动列表
*/
async getActivities(params?: ActivityListQuery): Promise<Activity[]> {
const searchParams = new URLSearchParams()
if (params?.page) searchParams.set('page', String(params.page))
if (params?.size) searchParams.set('size', String(params.size))
if (params?.status) searchParams.set('status', params.status)
if (params?.keyword) searchParams.set('keyword', params.keyword)
const response = await fetch(`${this.baseUrl}/activities?${searchParams}`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<Activity[]>
if (result.code !== 200) {
throw new Error(result.message || '获取活动列表失败')
}
return result.data
}
/**
* 获取单个活动详情
*/
async getActivityById(id: number): Promise<Activity | null> {
const response = await fetch(`${this.baseUrl}/activities/${id}`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<Activity>
if (result.code !== 200) {
return null
}
return result.data
}
/**
* 创建活动
*/
async createActivity(data: Partial<Activity>): Promise<number> {
const response = await fetch(`${this.baseUrl}/activities`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify(data)
})
const result = await response.json() as ApiResponse<number>
if (result.code !== 200) {
throw new Error(result.message || '创建活动失败')
}
return result.data
}
/**
* 更新活动
*/
async updateActivity(id: number, data: Partial<Activity>): Promise<void> {
const response = await fetch(`${this.baseUrl}/activities/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify(data)
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '更新活动失败')
}
}
/**
* 删除活动
*/
async deleteActivity(id: number): Promise<void> {
const response = await fetch(`${this.baseUrl}/activities/${id}`, {
method: 'DELETE',
credentials: 'include'
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '删除活动失败')
}
}
/**
* 发布活动
*/
async publishActivity(id: number): Promise<void> {
const response = await fetch(`${this.baseUrl}/activities/${id}/publish`, {
method: 'POST',
credentials: 'include'
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '发布活动失败')
}
}
/**
* 暂停活动
*/
async pauseActivity(id: number): Promise<void> {
const response = await fetch(`${this.baseUrl}/activities/${id}/pause`, {
method: 'POST',
credentials: 'include'
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '暂停活动失败')
}
}
/**
* 恢复活动
*/
async resumeActivity(id: number): Promise<void> {
const response = await fetch(`${this.baseUrl}/activities/${id}/resume`, {
method: 'POST',
credentials: 'include'
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '恢复活动失败')
}
}
/**
* 结束活动
*/
async endActivity(id: number): Promise<void> {
const response = await fetch(`${this.baseUrl}/activities/${id}/end`, {
method: 'POST',
credentials: 'include'
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '结束活动失败')
}
}
/**
* 获取活动统计
*/
async getActivityStats(id: number): Promise<any> {
const response = await fetch(`${this.baseUrl}/activities/${id}/stats`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<any>
if (result.code !== 200) {
throw new Error(result.message || '获取活动统计失败')
}
return result.data
}
/**
* 获取活动图表数据
*/
async getActivityGraph(id: number): Promise<any> {
const response = await fetch(`${this.baseUrl}/activities/${id}/graph`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<any>
if (result.code !== 200) {
throw new Error(result.message || '获取活动图表失败')
}
return result.data
}
/**
* 获取活动排行榜
*/
async getActivityLeaderboard(id: number, limit?: number): Promise<any[]> {
const params = limit ? `?limit=${limit}` : ''
const response = await fetch(`${this.baseUrl}/activities/${id}/leaderboard${params}`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<any[]>
if (result.code !== 200) {
throw new Error(result.message || '获取排行榜失败')
}
return result.data
}
}
export const activityService = new ActivityService()
export default activityService

View File

@@ -0,0 +1,162 @@
/**
* 审计日志服务
*/
export interface AuditLog {
id: number
userId: number
userName?: string
action: string
module: string
resource?: string
method?: string
requestUri?: string
requestMethod?: string
requestParams?: string
requestBody?: string
responseStatus?: number
responseBody?: string
ipAddress?: string
userAgent?: string
duration?: number
errorMessage?: string
createdAt: string
}
export interface ApiResponse<T> {
code: number
data: T
message?: string
}
class AuditService {
private baseUrl = '/api'
/**
* 获取审计日志列表
*/
async getLogs(params?: {
page?: number
size?: number
userId?: number
action?: string
module?: string
startDate?: string
endDate?: string
keyword?: string
}): Promise<AuditLog[]> {
const searchParams = new URLSearchParams()
if (params?.page) searchParams.set('page', String(params.page))
if (params?.size) searchParams.set('size', String(params.size))
if (params?.userId) searchParams.set('userId', String(params.userId))
if (params?.action) searchParams.set('action', params.action)
if (params?.module) searchParams.set('module', params.module)
if (params?.keyword) searchParams.set('keyword', params.keyword)
const response = await fetch(`${this.baseUrl}/audit/logs?${searchParams}`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<AuditLog[]>
if (result.code !== 200) {
throw new Error(result.message || '获取审计日志失败')
}
return result.data
}
/**
* 获取单个日志详情
*/
async getLogById(id: number): Promise<AuditLog | null> {
const response = await fetch(`${this.baseUrl}/audit/logs/${id}`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<AuditLog>
if (result.code !== 200) {
return null
}
return result.data
}
/**
* 获取操作类型列表
*/
async getActionTypes(): Promise<string[]> {
const response = await fetch(`${this.baseUrl}/audit/actions`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<string[]>
if (result.code !== 200) {
return []
}
return result.data
}
/**
* 获取模块列表
*/
async getModules(): Promise<string[]> {
const response = await fetch(`${this.baseUrl}/audit/modules`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<string[]>
if (result.code !== 200) {
return []
}
return result.data
}
/**
* 导出审计日志
*/
async exportLogs(params?: {
userId?: number
action?: string
module?: string
startDate?: string
endDate?: string
keyword?: string
}): Promise<Blob> {
const searchParams = new URLSearchParams()
if (params?.userId) searchParams.set('userId', String(params.userId))
if (params?.action) searchParams.set('action', params.action)
if (params?.module) searchParams.set('module', params.module)
if (params?.keyword) searchParams.set('keyword', params.keyword)
const response = await fetch(`${this.baseUrl}/audit/logs/export?${searchParams}`, {
credentials: 'include'
})
if (!response.ok) {
throw new Error('导出审计日志失败')
}
return response.blob()
}
/**
* 获取审计统计
*/
async getStats(params?: {
startDate?: string
endDate?: string
}): Promise<{
totalCount: number
actionCounts: Record<string, number>
userCounts: Record<string, number>
dailyCounts: Record<string, number>
}> {
const searchParams = new URLSearchParams()
if (params?.startDate) searchParams.set('startDate', params.startDate)
if (params?.endDate) searchParams.set('endDate', params.endDate)
const response = await fetch(`${this.baseUrl}/audit/stats?${searchParams}`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<any>
if (result.code !== 200) {
throw new Error(result.message || '获取审计统计失败')
}
return result.data
}
}
export const auditService = new AuditService()
export default auditService

View File

@@ -0,0 +1,212 @@
/**
* 奖励管理服务
*/
export interface Reward {
id?: number
userId: number
userName?: string
activityId?: number
activityName?: string
rewardType: RewardType
rewardAmount: number
status: RewardStatus
applyReason?: string
applyTime?: string
approveTime?: string
grantTime?: string
createdAt?: string
updatedAt?: string
}
export type RewardType = 'COUPON' | 'POINTS' | 'CASH' | 'GIFT'
export type RewardStatus = 'PENDING' | 'APPROVED' | 'REJECTED' | 'GRANTED' | 'CANCELLED'
export interface ApiResponse<T> {
code: number
data: T
message?: string
}
export interface RewardListQuery {
page?: number
size?: number
status?: string
rewardType?: string
userId?: number
activityId?: number
startDate?: string
endDate?: string
}
class RewardService {
private baseUrl = '/api'
/**
* 获取奖励列表
*/
async getRewards(params?: RewardListQuery): Promise<Reward[]> {
const searchParams = new URLSearchParams()
if (params?.page) searchParams.set('page', String(params.page))
if (params?.size) searchParams.set('size', String(params.size))
if (params?.status) searchParams.set('status', params.status)
if (params?.rewardType) searchParams.set('rewardType', params.rewardType)
const response = await fetch(`${this.baseUrl}/rewards?${searchParams}`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<Reward[]>
if (result.code !== 200) {
throw new Error(result.message || '获取奖励列表失败')
}
return result.data
}
/**
* 获取单个奖励详情
*/
async getRewardById(id: number): Promise<Reward | null> {
const response = await fetch(`${this.baseUrl}/rewards/${id}`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<Reward>
if (result.code !== 200) {
return null
}
return result.data
}
/**
* 申请奖励
*/
async applyReward(data: {
userId: number
activityId: number
rewardType: RewardType
rewardAmount: number
applyReason: string
}): Promise<number> {
const response = await fetch(`${this.baseUrl}/rewards/apply`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify(data)
})
const result = await response.json() as ApiResponse<number>
if (result.code !== 200) {
throw new Error(result.message || '申请奖励失败')
}
return result.data
}
/**
* 审批奖励
*/
async approveReward(id: number, approved: boolean, comment?: string): Promise<void> {
const response = await fetch(`${this.baseUrl}/rewards/${id}/approve`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ approved, comment })
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '审批奖励失败')
}
}
/**
* 发放奖励
*/
async grantReward(id: number): Promise<void> {
const response = await fetch(`${this.baseUrl}/rewards/${id}/grant`, {
method: 'POST',
credentials: 'include'
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '发放奖励失败')
}
}
/**
* 批量发放奖励
*/
async batchGrantRewards(ids: number[]): Promise<void> {
const response = await fetch(`${this.baseUrl}/rewards/batch-grant`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ ids })
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '批量发放失败')
}
}
/**
* 取消奖励
*/
async cancelReward(id: number, reason: string): Promise<void> {
const response = await fetch(`${this.baseUrl}/rewards/${id}/cancel`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ reason })
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '取消奖励失败')
}
}
/**
* 获取待审批奖励数量
*/
async getPendingCount(): Promise<number> {
const response = await fetch(`${this.baseUrl}/rewards/pending-count`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<number>
if (result.code !== 200) {
return 0
}
return result.data
}
/**
* 导出奖励记录
*/
async exportRewards(params?: RewardListQuery): Promise<Blob> {
const searchParams = new URLSearchParams()
if (params?.status) searchParams.set('status', params.status)
if (params?.rewardType) searchParams.set('rewardType', params.rewardType)
const response = await fetch(`${this.baseUrl}/rewards/export?${searchParams}`, {
credentials: 'include'
})
if (!response.ok) {
throw new Error('导出奖励记录失败')
}
return response.blob()
}
/**
* 奖励对账
*/
async reconcile(startDate: string, endDate: string): Promise<any> {
const response = await fetch(`${this.baseUrl}/rewards/reconcile?startDate=${startDate}&endDate=${endDate}`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<any>
if (result.code !== 200) {
throw new Error(result.message || '对账失败')
}
return result.data
}
}
export const rewardService = new RewardService()
export default rewardService

View File

@@ -0,0 +1,243 @@
/**
* 风险管理服务
*/
export interface RiskAlert {
id: number
type: RiskType
level: RiskLevel
title: string
description: string
userId?: number
userName?: string
activityId?: number
activityName?: string
data?: Record<string, any>
status: AlertStatus
handleResult?: string
handledBy?: number
handledAt?: string
createdAt: string
updatedAt?: string
}
export type RiskType = 'CHEAT' | 'ABNORMAL' | 'VIOLATION' | 'SYSTEM'
export type RiskLevel = 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL'
export type AlertStatus = 'PENDING' | 'HANDLED' | 'IGNORED' | 'WHITELISTED'
export interface RiskRule {
id: number
name: string
code: string
description?: string
riskType: RiskType
condition: string
action: RiskAction
status: RuleStatus
priority: number
createdBy?: number
createdAt?: string
updatedAt?: string
}
export type RiskAction = 'BLOCK' | 'WARN' | 'LOG' | 'CAPTCHA'
export type RuleStatus = 'ENABLED' | 'DISABLED'
export interface ApiResponse<T> {
code: number
data: T
message?: string
}
class RiskService {
private baseUrl = '/api'
/**
* 获取风险告警列表
*/
async getAlerts(params?: {
page?: number
size?: number
type?: string
level?: string
status?: string
startDate?: string
endDate?: string
}): Promise<RiskAlert[]> {
const searchParams = new URLSearchParams()
if (params?.page) searchParams.set('page', String(params.page))
if (params?.size) searchParams.set('size', String(params.size))
if (params?.type) searchParams.set('type', params.type)
if (params?.level) searchParams.set('level', params.level)
if (params?.status) searchParams.set('status', params.status)
const response = await fetch(`${this.baseUrl}/risk/alerts?${searchParams}`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<RiskAlert[]>
if (result.code !== 200) {
throw new Error(result.message || '获取风险告警失败')
}
return result.data
}
/**
* 获取单个告警详情
*/
async getAlertById(id: number): Promise<RiskAlert | null> {
const response = await fetch(`${this.baseUrl}/risk/alerts/${id}`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<RiskAlert>
if (result.code !== 200) {
return null
}
return result.data
}
/**
* 处理风险告警
*/
async handleAlert(id: number, data: {
status: AlertStatus
handleResult: string
}): Promise<void> {
const response = await fetch(`${this.baseUrl}/risk/alerts/${id}/handle`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify(data)
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '处理告警失败')
}
}
/**
* 批量处理告警
*/
async batchHandleAlerts(ids: number[], data: {
status: AlertStatus
handleResult: string
}): Promise<void> {
const response = await fetch(`${this.baseUrl}/risk/alerts/batch-handle`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ ids, ...data })
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '批量处理失败')
}
}
/**
* 获取风控规则列表
*/
async getRules(params?: {
page?: number
size?: number
riskType?: string
status?: string
}): Promise<RiskRule[]> {
const searchParams = new URLSearchParams()
if (params?.page) searchParams.set('page', String(params.page))
if (params?.size) searchParams.set('size', String(params.size))
if (params?.riskType) searchParams.set('riskType', params.riskType)
if (params?.status) searchParams.set('status', params.status)
const response = await fetch(`${this.baseUrl}/risk/rules?${searchParams}`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<RiskRule[]>
if (result.code !== 200) {
throw new Error(result.message || '获取风控规则失败')
}
return result.data
}
/**
* 创建风控规则
*/
async createRule(data: Partial<RiskRule>): Promise<number> {
const response = await fetch(`${this.baseUrl}/risk/rules`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify(data)
})
const result = await response.json() as ApiResponse<number>
if (result.code !== 200) {
throw new Error(result.message || '创建规则失败')
}
return result.data
}
/**
* 更新风控规则
*/
async updateRule(id: number, data: Partial<RiskRule>): Promise<void> {
const response = await fetch(`${this.baseUrl}/risk/rules/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify(data)
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '更新规则失败')
}
}
/**
* 删除风控规则
*/
async deleteRule(id: number): Promise<void> {
const response = await fetch(`${this.baseUrl}/risk/rules/${id}`, {
method: 'DELETE',
credentials: 'include'
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '删除规则失败')
}
}
/**
* 启用/禁用规则
*/
async toggleRule(id: number, enabled: boolean): Promise<void> {
const response = await fetch(`${this.baseUrl}/risk/rules/${id}/toggle`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ enabled })
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '切换规则状态失败')
}
}
/**
* 获取待处理告警数量
*/
async getPendingAlertCount(): Promise<number> {
const response = await fetch(`${this.baseUrl}/risk/alerts/pending-count`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<number>
if (result.code !== 200) {
return 0
}
return result.data
}
}
export const riskService = new RiskService()
export default riskService

View File

@@ -0,0 +1,164 @@
/**
* 系统配置服务
*/
export interface SystemConfig {
id: number
configKey: string
configValue: string
valueType: ValueType
description?: string
category: ConfigCategory
isSystem: boolean
createdAt?: string
updatedAt?: string
}
export type ValueType = 'STRING' | 'NUMBER' | 'BOOLEAN' | 'JSON'
export type ConfigCategory = 'SYSTEM' | 'ACTIVITY' | 'REWARD' | 'NOTIFICATION' | 'SECURITY'
export interface ApiResponse<T> {
code: number
data: T
message?: string
}
class SystemConfigService {
private baseUrl = '/api'
/**
* 获取系统配置列表
*/
async getConfigs(params?: {
category?: ConfigCategory
keyword?: string
}): Promise<SystemConfig[]> {
const searchParams = new URLSearchParams()
if (params?.category) searchParams.set('category', params.category)
if (params?.keyword) searchParams.set('keyword', params.keyword)
const response = await fetch(`${this.baseUrl}/system/configs?${searchParams}`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<SystemConfig[]>
if (result.code !== 200) {
throw new Error(result.message || '获取配置列表失败')
}
return result.data
}
/**
* 获取单个配置
*/
async getConfigByKey(key: string): Promise<SystemConfig | null> {
const response = await fetch(`${this.baseUrl}/system/configs/${key}`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<SystemConfig>
if (result.code !== 200) {
return null
}
return result.data
}
/**
* 更新配置
*/
async updateConfig(key: string, value: string): Promise<void> {
const response = await fetch(`${this.baseUrl}/system/configs/${key}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ configValue: value })
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '更新配置失败')
}
}
/**
* 批量更新配置
*/
async batchUpdateConfigs(configs: { key: string; value: string }[]): Promise<void> {
const response = await fetch(`${this.baseUrl}/system/configs/batch`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ configs })
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '批量更新配置失败')
}
}
/**
* 重置配置
*/
async resetConfig(key: string): Promise<void> {
const response = await fetch(`${this.baseUrl}/system/configs/${key}/reset`, {
method: 'POST',
credentials: 'include'
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '重置配置失败')
}
}
/**
* 清除缓存
*/
async clearCache(cacheType?: string): Promise<void> {
const url = cacheType
? `${this.baseUrl}/system/cache/clear?type=${cacheType}`
: `${this.baseUrl}/system/cache/clear`
const response = await fetch(url, {
method: 'POST',
credentials: 'include'
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '清除缓存失败')
}
}
/**
* 获取缓存列表
*/
async getCacheList(): Promise<{ name: string; size: number }[]> {
const response = await fetch(`${this.baseUrl}/system/cache/list`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<any[]>
if (result.code !== 200) {
return []
}
return result.data
}
/**
* 获取系统信息
*/
async getSystemInfo(): Promise<{
version: string
uptime: number
memory: { total: number; used: number; free: number }
cpu: number
threads: number
}> {
const response = await fetch(`${this.baseUrl}/system/info`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<any>
if (result.code !== 200) {
throw new Error(result.message || '获取系统信息失败')
}
return result.data
}
}
export const systemConfigService = new SystemConfigService()
export default systemConfigService

View File

@@ -0,0 +1,202 @@
/**
* 用户管理服务
*/
export interface User {
id: number
username: string
email?: string
phone?: string
nickname?: string
avatar?: string
status: UserStatus
roles?: string[]
departmentId?: number
departmentName?: string
realNameVerified?: boolean
createdAt?: string
updatedAt?: string
}
export type UserStatus = 'ACTIVE' | 'FROZEN' | 'DISABLED'
export interface ApiResponse<T> {
code: number
data: T
message?: string
}
export interface UserListQuery {
page?: number
size?: number
keyword?: string
status?: string
departmentId?: number
startDate?: string
endDate?: string
}
class UserService {
private baseUrl = '/api'
/**
* 获取用户列表
*/
async getUsers(params?: UserListQuery): Promise<User[]> {
const searchParams = new URLSearchParams()
if (params?.page) searchParams.set('page', String(params.page))
if (params?.size) searchParams.set('size', String(params.size))
if (params?.keyword) searchParams.set('keyword', params.keyword)
if (params?.status) searchParams.set('status', params.status)
const response = await fetch(`${this.baseUrl}/users?${searchParams}`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<User[]>
if (result.code !== 200) {
throw new Error(result.message || '获取用户列表失败')
}
return result.data
}
/**
* 获取单个用户详情
*/
async getUserById(id: number): Promise<User | null> {
const response = await fetch(`${this.baseUrl}/users/${id}`, {
credentials: 'include'
})
const result = await response.json() as ApiResponse<User>
if (result.code !== 200) {
return null
}
return result.data
}
/**
* 创建用户
*/
async createUser(data: Partial<User>): Promise<number> {
const response = await fetch(`${this.baseUrl}/users`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify(data)
})
const result = await response.json() as ApiResponse<number>
if (result.code !== 200) {
throw new Error(result.message || '创建用户失败')
}
return result.data
}
/**
* 更新用户
*/
async updateUser(id: number, data: Partial<User>): Promise<void> {
const response = await fetch(`${this.baseUrl}/users/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify(data)
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '更新用户失败')
}
}
/**
* 删除用户
*/
async deleteUser(id: number): Promise<void> {
const response = await fetch(`${this.baseUrl}/users/${id}`, {
method: 'DELETE',
credentials: 'include'
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '删除用户失败')
}
}
/**
* 冻结用户
*/
async freezeUser(id: number): Promise<void> {
const response = await fetch(`${this.baseUrl}/users/${id}/freeze`, {
method: 'POST',
credentials: 'include'
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '冻结用户失败')
}
}
/**
* 解冻用户
*/
async unfreezeUser(id: number): Promise<void> {
const response = await fetch(`${this.baseUrl}/users/${id}/unfreeze`, {
method: 'POST',
credentials: 'include'
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '解冻用户失败')
}
}
/**
* 分配角色
*/
async assignRoles(userId: number, roleIds: number[]): Promise<void> {
const response = await fetch(`${this.baseUrl}/users/${userId}/roles`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ roleIds })
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '分配角色失败')
}
}
/**
* 实名认证
*/
async verifyRealName(userId: number, realNameInfo: any): Promise<void> {
const response = await fetch(`${this.baseUrl}/users/${userId}/verify`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify(realNameInfo)
})
const result = await response.json() as ApiResponse<void>
if (result.code !== 200) {
throw new Error(result.message || '实名认证失败')
}
}
/**
* 导出用户
*/
async exportUsers(params?: UserListQuery): Promise<Blob> {
const searchParams = new URLSearchParams()
if (params?.keyword) searchParams.set('keyword', params.keyword)
if (params?.status) searchParams.set('status', params.status)
const response = await fetch(`${this.baseUrl}/users/export?${searchParams}`, {
credentials: 'include'
})
if (!response.ok) {
throw new Error('导出用户失败')
}
return response.blob()
}
}
export const userService = new UserService()
export default userService

View File

@@ -0,0 +1,48 @@
/**
* 活动类型定义
*/
export interface Activity {
id?: number
name: string
description?: string
shortLinkPrefix?: string
startTime: string
endTime: string
status: ActivityStatus
rewardType?: RewardType
rewardAmount?: number
rewardDesc?: string
posterUrl?: string
callbackUrl?: string
createdAt?: string
updatedAt?: string
}
export type ActivityStatus = 'DRAFT' | 'PUBLISHED' | 'PAUSED' | 'ENDED'
export type RewardType = 'COUPON' | 'POINTS' | 'CASH' | 'GIFT'
export interface ActivityStats {
views: number
shares: number
clicks: number
conversions: number
rewardIssued: number
}
export interface ActivityGraphData {
dates: string[]
views: number[]
shares: number[]
clicks: number[]
}
export interface LeaderboardEntry {
rank: number
userId: string
userName: string
shares: number
clicks: number
rewards: number
}