feat: 完成前端多语言支持和菜单优化
- 缩短菜单标题,解决显示不全问题 - 添加跟随系统语言选项,作为默认选项 - 移除语言切换时的页面刷新,实现无刷新切换 - 完成主要页面的多语言替换: * ConfigPage - 全局配置页面 * ResetPassword - 重置密码页面 * LeaderList - Leader 列表页面 * UserList - 用户列表页面 * Statistics - 统计信息页面 * OrderList - 订单列表页面 * TemplateList - 模板列表页面 * CopyTradingList - 跟单配置列表页面 - 添加简体中文、繁体中文和英文的完整翻译键 - 优化语言设置页面,支持跟随系统语言
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
package com.wrbug.polymarketbot.config
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.springframework.context.i18n.LocaleContextHolder
|
||||
import org.springframework.stereotype.Component
|
||||
import org.springframework.web.servlet.HandlerInterceptor
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* 语言拦截器
|
||||
* 从 HTTP Header 读取语言设置,并设置到 LocaleContextHolder
|
||||
*
|
||||
* 支持的 Header:
|
||||
* - Accept-Language: 标准 HTTP Header(如 zh-CN, zh-TW, en)
|
||||
* - X-Language: 自定义 Header(如 zh-CN, zh-TW, en)
|
||||
*
|
||||
* 语言映射规则:
|
||||
* - zh-CN, zh -> zh-CN (简体中文)
|
||||
* - zh-TW, zh-HK -> zh-TW (繁体中文)
|
||||
* - 其他 -> en (英文,默认)
|
||||
*/
|
||||
@Component
|
||||
class LocaleInterceptor : HandlerInterceptor {
|
||||
|
||||
override fun preHandle(
|
||||
request: HttpServletRequest,
|
||||
response: HttpServletResponse,
|
||||
handler: Any
|
||||
): Boolean {
|
||||
// 优先从 X-Language Header 读取
|
||||
val language = request.getHeader("X-Language")
|
||||
?: request.getHeader("Accept-Language")
|
||||
?: "en"
|
||||
|
||||
// 解析语言
|
||||
val locale = parseLocale(language)
|
||||
|
||||
// 设置到 LocaleContextHolder,供 MessageSource 使用
|
||||
LocaleContextHolder.setLocale(locale)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析语言字符串为 Locale
|
||||
* 支持格式:zh-CN, zh_TW, zh, en, en-US 等
|
||||
*/
|
||||
private fun parseLocale(language: String): Locale {
|
||||
// 移除空格并转为小写
|
||||
val lang = language.trim().lowercase()
|
||||
|
||||
// 处理 zh-CN, zh_CN 等格式
|
||||
if (lang.startsWith("zh")) {
|
||||
// 检查是否是繁体中文
|
||||
if (lang.contains("tw") || lang.contains("hk") || lang.contains("mo")) {
|
||||
return Locale("zh", "TW")
|
||||
}
|
||||
// 默认简体中文
|
||||
return Locale("zh", "CN")
|
||||
}
|
||||
|
||||
// 英文(默认)
|
||||
return Locale("en")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.springframework.context.i18n.LocaleContextHolder
|
||||
import org.springframework.stereotype.Component
|
||||
import org.springframework.web.servlet.HandlerInterceptor
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* 语言拦截器
|
||||
* 从 HTTP Header 读取语言设置,并设置到 LocaleContextHolder
|
||||
*
|
||||
* 支持的 Header:
|
||||
* - Accept-Language: 标准 HTTP Header(如 zh-CN, zh-TW, en)
|
||||
* - X-Language: 自定义 Header(如 zh-CN, zh-TW, en)
|
||||
*
|
||||
* 语言映射规则:
|
||||
* - zh-CN, zh -> zh-CN (简体中文)
|
||||
* - zh-TW, zh-HK -> zh-TW (繁体中文)
|
||||
* - 其他 -> en (英文,默认)
|
||||
*/
|
||||
@Component
|
||||
class LocaleInterceptor : HandlerInterceptor {
|
||||
|
||||
override fun preHandle(
|
||||
request: HttpServletRequest,
|
||||
response: HttpServletResponse,
|
||||
handler: Any
|
||||
): Boolean {
|
||||
// 优先从 X-Language Header 读取
|
||||
val language = request.getHeader("X-Language")
|
||||
?: request.getHeader("Accept-Language")
|
||||
?: "en"
|
||||
|
||||
// 解析语言
|
||||
val locale = parseLocale(language)
|
||||
|
||||
// 设置到 LocaleContextHolder,供 MessageSource 使用
|
||||
LocaleContextHolder.setLocale(locale)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析语言字符串为 Locale
|
||||
* 支持格式:zh-CN, zh_TW, zh, en, en-US 等
|
||||
*/
|
||||
private fun parseLocale(language: String): Locale {
|
||||
// 移除空格并转为小写
|
||||
val lang = language.trim().lowercase()
|
||||
|
||||
// 处理 zh-CN, zh_CN 等格式
|
||||
if (lang.startsWith("zh")) {
|
||||
// 检查是否是繁体中文
|
||||
if (lang.contains("tw") || lang.contains("hk") || lang.contains("mo")) {
|
||||
return Locale("zh", "TW")
|
||||
}
|
||||
// 默认简体中文
|
||||
return Locale("zh", "CN")
|
||||
}
|
||||
|
||||
// 英文(默认)
|
||||
return Locale("en")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,14 +6,32 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
|
||||
|
||||
/**
|
||||
* Web MVC 配置
|
||||
* 注册JWT认证拦截器
|
||||
* 注册JWT认证拦截器和语言拦截器
|
||||
*/
|
||||
@Configuration
|
||||
class WebMvcConfig(
|
||||
private val jwtAuthenticationInterceptor: JwtAuthenticationInterceptor
|
||||
private val jwtAuthenticationInterceptor: JwtAuthenticationInterceptor,
|
||||
private val localeInterceptor: LocaleInterceptor
|
||||
) : WebMvcConfigurer {
|
||||
|
||||
override fun addInterceptors(registry: InterceptorRegistry) {
|
||||
// 先注册语言拦截器(优先级更高)
|
||||
registry.addInterceptor(localeInterceptor)
|
||||
.addPathPatterns("/api/**")
|
||||
|
||||
// 再注册JWT认证拦截器
|
||||
registry.addInterceptor(jwtAuthenticationInterceptor)
|
||||
.addPathPatterns("/api/**")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
registry.addInterceptor(jwtAuthenticationInterceptor)
|
||||
.addPathPatterns("/api/**")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
registry.addInterceptor(jwtAuthenticationInterceptor)
|
||||
.addPathPatterns("/api/**")
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.wrbug.polymarketbot.service.AccountService
|
||||
import com.wrbug.polymarketbot.util.toSafeBigDecimal
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.context.MessageSource
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.*
|
||||
import java.math.BigDecimal
|
||||
@@ -16,7 +17,8 @@ import java.math.BigDecimal
|
||||
@RestController
|
||||
@RequestMapping("/api/copy-trading/accounts")
|
||||
class AccountController(
|
||||
private val accountService: AccountService
|
||||
private val accountService: AccountService,
|
||||
private val messageSource: MessageSource
|
||||
) {
|
||||
|
||||
private val logger = LoggerFactory.getLogger(AccountController::class.java)
|
||||
@@ -29,10 +31,10 @@ class AccountController(
|
||||
return try {
|
||||
// 参数验证
|
||||
if (request.privateKey.isBlank()) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_PRIVATE_KEY_EMPTY))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_PRIVATE_KEY_EMPTY, messageSource = messageSource))
|
||||
}
|
||||
if (request.walletAddress.isBlank()) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_WALLET_ADDRESS_EMPTY))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_WALLET_ADDRESS_EMPTY, messageSource = messageSource))
|
||||
}
|
||||
|
||||
val result = accountService.importAccount(request)
|
||||
@@ -46,17 +48,18 @@ class AccountController(
|
||||
is IllegalArgumentException -> ResponseEntity.ok(
|
||||
ApiResponse.error(
|
||||
ErrorCode.PARAM_ERROR,
|
||||
e.message
|
||||
e.message,
|
||||
messageSource
|
||||
)
|
||||
)
|
||||
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_IMPORT_FAILED, e.message))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_IMPORT_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("导入账户异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_IMPORT_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_IMPORT_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,17 +80,18 @@ class AccountController(
|
||||
is IllegalArgumentException -> ResponseEntity.ok(
|
||||
ApiResponse.error(
|
||||
ErrorCode.PARAM_ERROR,
|
||||
e.message
|
||||
e.message,
|
||||
messageSource
|
||||
)
|
||||
)
|
||||
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_UPDATE_FAILED, e.message))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_UPDATE_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("更新账户异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_UPDATE_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_UPDATE_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,24 +112,26 @@ class AccountController(
|
||||
is IllegalArgumentException -> ResponseEntity.ok(
|
||||
ApiResponse.error(
|
||||
ErrorCode.PARAM_ERROR,
|
||||
e.message
|
||||
e.message,
|
||||
messageSource
|
||||
)
|
||||
)
|
||||
|
||||
is IllegalStateException -> ResponseEntity.ok(
|
||||
ApiResponse.error(
|
||||
ErrorCode.BUSINESS_ERROR,
|
||||
e.message
|
||||
e.message,
|
||||
messageSource
|
||||
)
|
||||
)
|
||||
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_DELETE_FAILED, e.message))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_DELETE_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("删除账户异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_DELETE_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_DELETE_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,12 +148,12 @@ class AccountController(
|
||||
},
|
||||
onFailure = { e ->
|
||||
logger.error("查询账户列表失败: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_LIST_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_LIST_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("查询账户列表异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_LIST_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_LIST_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,14 +174,16 @@ class AccountController(
|
||||
is IllegalArgumentException -> ResponseEntity.ok(
|
||||
ApiResponse.error(
|
||||
ErrorCode.PARAM_ERROR,
|
||||
e.message
|
||||
e.message,
|
||||
messageSource
|
||||
)
|
||||
)
|
||||
|
||||
else -> ResponseEntity.ok(
|
||||
ApiResponse.error(
|
||||
ErrorCode.SERVER_ACCOUNT_DETAIL_FETCH_FAILED,
|
||||
e.message
|
||||
e.message,
|
||||
messageSource
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -183,7 +191,7 @@ class AccountController(
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("查询账户详情异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_DETAIL_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_DETAIL_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,14 +212,16 @@ class AccountController(
|
||||
is IllegalArgumentException -> ResponseEntity.ok(
|
||||
ApiResponse.error(
|
||||
ErrorCode.PARAM_ERROR,
|
||||
e.message
|
||||
e.message,
|
||||
messageSource
|
||||
)
|
||||
)
|
||||
|
||||
else -> ResponseEntity.ok(
|
||||
ApiResponse.error(
|
||||
ErrorCode.SERVER_ACCOUNT_BALANCE_FETCH_FAILED,
|
||||
e.message
|
||||
e.message,
|
||||
messageSource
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -219,7 +229,7 @@ class AccountController(
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("查询账户余额异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_BALANCE_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_BALANCE_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,12 +246,12 @@ class AccountController(
|
||||
},
|
||||
onFailure = { e ->
|
||||
logger.error("查询仓位列表失败: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_POSITIONS_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_POSITIONS_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("查询仓位列表异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_POSITIONS_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_POSITIONS_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,35 +263,35 @@ class AccountController(
|
||||
return try {
|
||||
// 参数验证
|
||||
if (request.accountId <= 0) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ACCOUNT_ID_INVALID))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ACCOUNT_ID_INVALID, messageSource = messageSource))
|
||||
}
|
||||
if (request.marketId.isBlank()) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_MARKET_ID_EMPTY))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_MARKET_ID_EMPTY, messageSource = messageSource))
|
||||
}
|
||||
// side 可以是任意结果名称(如 "YES", "NO", "Pakistan" 等),不再限制为 YES/NO
|
||||
if (request.side.isBlank()) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_SIDE_EMPTY))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_SIDE_EMPTY, messageSource = messageSource))
|
||||
}
|
||||
if (request.orderType !in listOf("MARKET", "LIMIT")) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ORDER_TYPE_MUST_BE_MARKET_OR_LIMIT))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ORDER_TYPE_MUST_BE_MARKET_OR_LIMIT, messageSource = messageSource))
|
||||
}
|
||||
// 如果传了 percent,不需要校验 quantity;如果没传 percent,必须提供 quantity
|
||||
if (request.percent.isNullOrBlank() && request.quantity.isNullOrBlank()) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_QUANTITY_EMPTY))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_QUANTITY_EMPTY, messageSource = messageSource))
|
||||
}
|
||||
// 如果传了 percent,验证百分比值必须在 0-100 之间(支持小数)
|
||||
if (!request.percent.isNullOrBlank()) {
|
||||
try {
|
||||
val percent = request.percent.toSafeBigDecimal()
|
||||
if (percent <= BigDecimal.ZERO || percent > BigDecimal.valueOf(100)) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, "卖出百分比必须在 0-100 之间"))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, "卖出百分比必须在 0-100 之间", messageSource))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, "卖出百分比格式不正确: ${e.message}"))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, "卖出百分比格式不正确: ${e.message}", messageSource))
|
||||
}
|
||||
}
|
||||
if (request.orderType == "LIMIT" && (request.price == null || request.price.isBlank())) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_PRICE_EMPTY))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_PRICE_EMPTY, messageSource = messageSource))
|
||||
}
|
||||
|
||||
val result = runBlocking { accountService.sellPosition(request) }
|
||||
@@ -295,21 +305,24 @@ class AccountController(
|
||||
is IllegalArgumentException -> ResponseEntity.ok(
|
||||
ApiResponse.error(
|
||||
ErrorCode.PARAM_ERROR,
|
||||
e.message
|
||||
e.message,
|
||||
messageSource
|
||||
)
|
||||
)
|
||||
|
||||
is IllegalStateException -> ResponseEntity.ok(
|
||||
ApiResponse.error(
|
||||
ErrorCode.BUSINESS_ERROR,
|
||||
e.message
|
||||
e.message,
|
||||
messageSource
|
||||
)
|
||||
)
|
||||
|
||||
else -> ResponseEntity.ok(
|
||||
ApiResponse.error(
|
||||
ErrorCode.SERVER_ACCOUNT_ORDER_CREATE_FAILED,
|
||||
e.message
|
||||
e.message,
|
||||
messageSource
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -317,7 +330,7 @@ class AccountController(
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("创建卖出订单异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_ORDER_CREATE_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_ORDER_CREATE_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,14 +351,16 @@ class AccountController(
|
||||
is IllegalArgumentException -> ResponseEntity.ok(
|
||||
ApiResponse.error(
|
||||
ErrorCode.PARAM_ERROR,
|
||||
e.message
|
||||
e.message,
|
||||
messageSource
|
||||
)
|
||||
)
|
||||
|
||||
else -> ResponseEntity.ok(
|
||||
ApiResponse.error(
|
||||
ErrorCode.SERVER_ERROR,
|
||||
"获取可赎回仓位统计失败: ${e.message}"
|
||||
"获取可赎回仓位统计失败: ${e.message}",
|
||||
messageSource
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -353,7 +368,7 @@ class AccountController(
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("获取可赎回仓位统计异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "获取可赎回仓位统计失败: ${e.message}"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "获取可赎回仓位统计失败: ${e.message}", messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,19 +380,19 @@ class AccountController(
|
||||
return try {
|
||||
// 参数验证
|
||||
if (request.positions.isEmpty()) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_REDEEM_POSITIONS_EMPTY))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_REDEEM_POSITIONS_EMPTY, messageSource = messageSource))
|
||||
}
|
||||
|
||||
// 验证每个仓位项
|
||||
for (item in request.positions) {
|
||||
if (item.accountId <= 0) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ACCOUNT_ID_INVALID))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ACCOUNT_ID_INVALID, messageSource = messageSource))
|
||||
}
|
||||
if (item.marketId.isBlank()) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_MARKET_ID_EMPTY))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_MARKET_ID_EMPTY, messageSource = messageSource))
|
||||
}
|
||||
if (item.outcomeIndex < 0) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_INDEX_SETS_INVALID))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_INDEX_SETS_INVALID, messageSource = messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -392,21 +407,24 @@ class AccountController(
|
||||
is IllegalArgumentException -> ResponseEntity.ok(
|
||||
ApiResponse.error(
|
||||
ErrorCode.PARAM_ERROR,
|
||||
e.message
|
||||
e.message,
|
||||
messageSource
|
||||
)
|
||||
)
|
||||
|
||||
is IllegalStateException -> ResponseEntity.ok(
|
||||
ApiResponse.error(
|
||||
ErrorCode.BUSINESS_ERROR,
|
||||
e.message
|
||||
e.message,
|
||||
messageSource
|
||||
)
|
||||
)
|
||||
|
||||
else -> ResponseEntity.ok(
|
||||
ApiResponse.error(
|
||||
ErrorCode.SERVER_ACCOUNT_REDEEM_POSITIONS_FAILED,
|
||||
e.message
|
||||
e.message,
|
||||
messageSource
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -414,7 +432,7 @@ class AccountController(
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("赎回仓位异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_REDEEM_POSITIONS_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ACCOUNT_REDEEM_POSITIONS_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.wrbug.polymarketbot.enums.ErrorCode
|
||||
import com.wrbug.polymarketbot.service.AuthService
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.context.MessageSource
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.*
|
||||
|
||||
@@ -14,7 +15,8 @@ import org.springframework.web.bind.annotation.*
|
||||
@RestController
|
||||
@RequestMapping("/api/auth")
|
||||
class AuthController(
|
||||
private val authService: AuthService
|
||||
private val authService: AuthService,
|
||||
private val messageSource: MessageSource
|
||||
) {
|
||||
|
||||
private val logger = LoggerFactory.getLogger(AuthController::class.java)
|
||||
@@ -26,10 +28,10 @@ class AuthController(
|
||||
fun login(@RequestBody request: LoginRequest): ResponseEntity<ApiResponse<LoginResponse>> {
|
||||
return try {
|
||||
if (request.username.isBlank()) {
|
||||
return ResponseEntity.ok(ApiResponse.paramError("用户名不能为空"))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_EMPTY, "用户名不能为空", messageSource))
|
||||
}
|
||||
if (request.password.isBlank()) {
|
||||
return ResponseEntity.ok(ApiResponse.paramError("密码不能为空"))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_EMPTY, "密码不能为空", messageSource))
|
||||
}
|
||||
|
||||
val result = authService.login(request.username, request.password)
|
||||
@@ -42,18 +44,18 @@ class AuthController(
|
||||
when (e) {
|
||||
is IllegalArgumentException -> {
|
||||
if (e.message == ErrorCode.AUTH_USERNAME_OR_PASSWORD_ERROR.message) {
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_USERNAME_OR_PASSWORD_ERROR.code, e.message ?: "用户名或密码错误"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_USERNAME_OR_PASSWORD_ERROR, messageSource = messageSource))
|
||||
} else {
|
||||
ResponseEntity.ok(ApiResponse.paramError(e.message ?: "参数错误"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
else -> ResponseEntity.ok(ApiResponse.serverError("登录失败: ${e.message}"))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_ERROR, "登录失败: ${e.message}", messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("登录异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.serverError("登录失败: ${e.message}"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_ERROR, "登录失败: ${e.message}", messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,13 +69,13 @@ class AuthController(
|
||||
): ResponseEntity<ApiResponse<Unit>> {
|
||||
return try {
|
||||
if (request.resetKey.isBlank()) {
|
||||
return ResponseEntity.ok(ApiResponse.paramError("重置密钥不能为空"))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_EMPTY, "重置密钥不能为空", messageSource))
|
||||
}
|
||||
if (request.username.isBlank()) {
|
||||
return ResponseEntity.ok(ApiResponse.paramError("用户名不能为空"))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_EMPTY, "用户名不能为空", messageSource))
|
||||
}
|
||||
if (request.newPassword.isBlank()) {
|
||||
return ResponseEntity.ok(ApiResponse.paramError("新密码不能为空"))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_EMPTY, "新密码不能为空", messageSource))
|
||||
}
|
||||
|
||||
val result = authService.resetPassword(
|
||||
@@ -95,25 +97,25 @@ class AuthController(
|
||||
is IllegalArgumentException -> {
|
||||
if (e.message == ErrorCode.AUTH_PASSWORD_WEAK.message) {
|
||||
// 密码强度错误可以提示
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_PASSWORD_WEAK.code, e.message ?: "密码长度不符合要求"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_PASSWORD_WEAK, messageSource = messageSource))
|
||||
} else {
|
||||
// 其他错误统一返回"重置失败"
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_ERROR.code, "重置失败"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_ERROR, "重置失败", messageSource))
|
||||
}
|
||||
}
|
||||
is IllegalStateException -> {
|
||||
// 频率限制等错误统一返回"重置失败"
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_ERROR.code, "重置失败"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_ERROR, "重置失败", messageSource))
|
||||
}
|
||||
else -> {
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_ERROR.code, "重置失败"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_ERROR, "重置失败", messageSource))
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("重置密码异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.serverError("重置密码失败: ${e.message}"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_ERROR, "重置密码失败: ${e.message}", messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +129,7 @@ class AuthController(
|
||||
ResponseEntity.ok(ApiResponse.success(CheckFirstUseResponse(isFirstUse = isFirstUse)))
|
||||
} catch (e: Exception) {
|
||||
logger.error("检查首次使用异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.serverError("检查首次使用失败: ${e.message}"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "检查首次使用失败: ${e.message}", messageSource))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+24
-22
@@ -4,6 +4,7 @@ import com.wrbug.polymarketbot.dto.*
|
||||
import com.wrbug.polymarketbot.enums.ErrorCode
|
||||
import com.wrbug.polymarketbot.service.CopyTradingService
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.context.MessageSource
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.*
|
||||
|
||||
@@ -13,7 +14,8 @@ import org.springframework.web.bind.annotation.*
|
||||
@RestController
|
||||
@RequestMapping("/api/copy-trading")
|
||||
class CopyTradingController(
|
||||
private val copyTradingService: CopyTradingService
|
||||
private val copyTradingService: CopyTradingService,
|
||||
private val messageSource: MessageSource
|
||||
) {
|
||||
|
||||
private val logger = LoggerFactory.getLogger(CopyTradingController::class.java)
|
||||
@@ -25,13 +27,13 @@ class CopyTradingController(
|
||||
fun createCopyTrading(@RequestBody request: CopyTradingCreateRequest): ResponseEntity<ApiResponse<CopyTradingDto>> {
|
||||
return try {
|
||||
if (request.accountId <= 0) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ACCOUNT_ID_INVALID))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ACCOUNT_ID_INVALID, messageSource = messageSource))
|
||||
}
|
||||
if (request.templateId <= 0) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_TEMPLATE_ID_INVALID))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_TEMPLATE_ID_INVALID, messageSource = messageSource))
|
||||
}
|
||||
if (request.leaderId <= 0) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_LEADER_ID_INVALID))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_LEADER_ID_INVALID, messageSource = messageSource))
|
||||
}
|
||||
|
||||
val result = copyTradingService.createCopyTrading(request)
|
||||
@@ -42,14 +44,14 @@ class CopyTradingController(
|
||||
onFailure = { e ->
|
||||
logger.error("创建跟单失败: ${e.message}", e)
|
||||
when (e) {
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_COPY_TRADING_CREATE_FAILED, e.message))
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_COPY_TRADING_CREATE_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("创建跟单异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_COPY_TRADING_CREATE_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_COPY_TRADING_CREATE_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,12 +68,12 @@ class CopyTradingController(
|
||||
},
|
||||
onFailure = { e ->
|
||||
logger.error("查询跟单列表失败: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_COPY_TRADING_LIST_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_COPY_TRADING_LIST_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("查询跟单列表异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_COPY_TRADING_LIST_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_COPY_TRADING_LIST_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +84,7 @@ class CopyTradingController(
|
||||
fun updateCopyTradingStatus(@RequestBody request: CopyTradingUpdateStatusRequest): ResponseEntity<ApiResponse<CopyTradingDto>> {
|
||||
return try {
|
||||
if (request.copyTradingId <= 0) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_COPY_TRADING_ID_INVALID))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_COPY_TRADING_ID_INVALID, messageSource = messageSource))
|
||||
}
|
||||
|
||||
val result = copyTradingService.updateCopyTradingStatus(request)
|
||||
@@ -93,15 +95,15 @@ class CopyTradingController(
|
||||
onFailure = { e ->
|
||||
logger.error("更新跟单状态失败: ${e.message}", e)
|
||||
when (e) {
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message))
|
||||
is IllegalStateException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.BUSINESS_ERROR, e.message))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_COPY_TRADING_UPDATE_FAILED, e.message))
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
is IllegalStateException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.BUSINESS_ERROR, e.message, messageSource))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_COPY_TRADING_UPDATE_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("更新跟单状态异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_COPY_TRADING_UPDATE_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_COPY_TRADING_UPDATE_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +114,7 @@ class CopyTradingController(
|
||||
fun deleteCopyTrading(@RequestBody request: CopyTradingDeleteRequest): ResponseEntity<ApiResponse<Unit>> {
|
||||
return try {
|
||||
if (request.copyTradingId <= 0) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_COPY_TRADING_ID_INVALID))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_COPY_TRADING_ID_INVALID, messageSource = messageSource))
|
||||
}
|
||||
|
||||
val result = copyTradingService.deleteCopyTrading(request.copyTradingId)
|
||||
@@ -123,14 +125,14 @@ class CopyTradingController(
|
||||
onFailure = { e ->
|
||||
logger.error("删除跟单失败: ${e.message}", e)
|
||||
when (e) {
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_COPY_TRADING_DELETE_FAILED, e.message))
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_COPY_TRADING_DELETE_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("删除跟单异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_COPY_TRADING_DELETE_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_COPY_TRADING_DELETE_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +143,7 @@ class CopyTradingController(
|
||||
fun getAccountTemplates(@RequestBody request: AccountTemplatesRequest): ResponseEntity<ApiResponse<AccountTemplatesResponse>> {
|
||||
return try {
|
||||
if (request.accountId <= 0) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ACCOUNT_ID_INVALID))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ACCOUNT_ID_INVALID, messageSource = messageSource))
|
||||
}
|
||||
|
||||
val result = copyTradingService.getAccountTemplates(request.accountId)
|
||||
@@ -152,14 +154,14 @@ class CopyTradingController(
|
||||
onFailure = { e ->
|
||||
logger.error("查询钱包绑定的模板失败: ${e.message}", e)
|
||||
when (e) {
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_COPY_TRADING_TEMPLATES_FETCH_FAILED, e.message))
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_COPY_TRADING_TEMPLATES_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("查询钱包绑定的模板异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_COPY_TRADING_TEMPLATES_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_COPY_TRADING_TEMPLATES_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+27
-24
@@ -5,6 +5,7 @@ import com.wrbug.polymarketbot.enums.ErrorCode
|
||||
import com.wrbug.polymarketbot.service.CopyTradingStatisticsService
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.context.MessageSource
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.*
|
||||
|
||||
@@ -15,7 +16,8 @@ import org.springframework.web.bind.annotation.*
|
||||
@RestController
|
||||
@RequestMapping("/api/copy-trading/statistics")
|
||||
class CopyTradingStatisticsController(
|
||||
private val statisticsService: CopyTradingStatisticsService
|
||||
private val statisticsService: CopyTradingStatisticsService,
|
||||
private val messageSource: MessageSource
|
||||
) {
|
||||
|
||||
private val logger = LoggerFactory.getLogger(CopyTradingStatisticsController::class.java)
|
||||
@@ -28,7 +30,7 @@ class CopyTradingStatisticsController(
|
||||
fun getStatisticsDetail(@RequestBody request: StatisticsDetailRequest): ResponseEntity<ApiResponse<CopyTradingStatisticsResponse>> {
|
||||
return try {
|
||||
if (request.copyTradingId <= 0) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_COPY_TRADING_ID_INVALID))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_COPY_TRADING_ID_INVALID, messageSource = messageSource))
|
||||
}
|
||||
|
||||
val result = runBlocking { statisticsService.getStatistics(request.copyTradingId) }
|
||||
@@ -39,14 +41,14 @@ class CopyTradingStatisticsController(
|
||||
onFailure = { e ->
|
||||
logger.error("获取统计信息失败: copyTradingId=${request.copyTradingId}", e)
|
||||
when (e) {
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_STATISTICS_FETCH_FAILED, e.message))
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_STATISTICS_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("获取统计信息异常: copyTradingId=${request.copyTradingId}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_STATISTICS_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_STATISTICS_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,14 +69,14 @@ class CopyTradingStatisticsController(
|
||||
onFailure = { e ->
|
||||
logger.error("获取全局统计失败", e)
|
||||
when (e) {
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_STATISTICS_FETCH_FAILED, e.message))
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_STATISTICS_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("获取全局统计异常", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_STATISTICS_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_STATISTICS_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +88,7 @@ class CopyTradingStatisticsController(
|
||||
fun getLeaderStatistics(@RequestBody request: LeaderStatisticsRequest): ResponseEntity<ApiResponse<StatisticsResponse>> {
|
||||
return try {
|
||||
if (request.leaderId <= 0) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_LEADER_ID_INVALID))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_LEADER_ID_INVALID, messageSource = messageSource))
|
||||
}
|
||||
|
||||
val result = runBlocking {
|
||||
@@ -99,14 +101,14 @@ class CopyTradingStatisticsController(
|
||||
onFailure = { e ->
|
||||
logger.error("获取 Leader 统计失败: leaderId=${request.leaderId}", e)
|
||||
when (e) {
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_STATISTICS_FETCH_FAILED, e.message))
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_STATISTICS_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("获取 Leader 统计异常: leaderId=${request.leaderId}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_STATISTICS_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_STATISTICS_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,11 +120,11 @@ class CopyTradingStatisticsController(
|
||||
fun getCategoryStatistics(@RequestBody request: CategoryStatisticsRequest): ResponseEntity<ApiResponse<StatisticsResponse>> {
|
||||
return try {
|
||||
if (request.category.isBlank()) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, "分类不能为空"))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, "分类不能为空", messageSource))
|
||||
}
|
||||
|
||||
if (request.category != "sports" && request.category != "crypto") {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, "分类必须是 sports 或 crypto"))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, "分类必须是 sports 或 crypto", messageSource))
|
||||
}
|
||||
|
||||
val result = runBlocking {
|
||||
@@ -135,14 +137,14 @@ class CopyTradingStatisticsController(
|
||||
onFailure = { e ->
|
||||
logger.error("获取分类统计失败: category=${request.category}", e)
|
||||
when (e) {
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_STATISTICS_FETCH_FAILED, e.message))
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_STATISTICS_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("获取分类统计异常: category=${request.category}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_STATISTICS_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_STATISTICS_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -154,7 +156,8 @@ class CopyTradingStatisticsController(
|
||||
@RestController
|
||||
@RequestMapping("/api/copy-trading/orders")
|
||||
class CopyOrderTrackingController(
|
||||
private val statisticsService: CopyTradingStatisticsService
|
||||
private val statisticsService: CopyTradingStatisticsService,
|
||||
private val messageSource: MessageSource
|
||||
) {
|
||||
|
||||
private val logger = LoggerFactory.getLogger(CopyOrderTrackingController::class.java)
|
||||
@@ -167,16 +170,16 @@ class CopyOrderTrackingController(
|
||||
fun getOrderList(@RequestBody request: OrderTrackingRequest): ResponseEntity<ApiResponse<OrderListResponse>> {
|
||||
return try {
|
||||
if (request.copyTradingId <= 0) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_COPY_TRADING_ID_INVALID))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_COPY_TRADING_ID_INVALID, messageSource = messageSource))
|
||||
}
|
||||
|
||||
if (request.type.isBlank()) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_EMPTY, "订单类型不能为空"))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_EMPTY, "订单类型不能为空", messageSource))
|
||||
}
|
||||
|
||||
val validTypes = listOf("buy", "sell", "matched")
|
||||
if (!validTypes.contains(request.type.lowercase())) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ORDER_TYPE_INVALID_FOR_TRACKING))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ORDER_TYPE_INVALID_FOR_TRACKING, messageSource = messageSource))
|
||||
}
|
||||
|
||||
val result = statisticsService.getOrderList(request)
|
||||
@@ -187,14 +190,14 @@ class CopyOrderTrackingController(
|
||||
onFailure = { e ->
|
||||
logger.error("查询订单列表失败: copyTradingId=${request.copyTradingId}, type=${request.type}", e)
|
||||
when (e) {
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ORDER_TRACKING_LIST_FETCH_FAILED, e.message))
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ORDER_TRACKING_LIST_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("查询订单列表异常: copyTradingId=${request.copyTradingId}, type=${request.type}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ORDER_TRACKING_LIST_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ORDER_TRACKING_LIST_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+27
-25
@@ -4,6 +4,7 @@ import com.wrbug.polymarketbot.dto.*
|
||||
import com.wrbug.polymarketbot.enums.ErrorCode
|
||||
import com.wrbug.polymarketbot.service.CopyTradingTemplateService
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.context.MessageSource
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.*
|
||||
|
||||
@@ -13,7 +14,8 @@ import org.springframework.web.bind.annotation.*
|
||||
@RestController
|
||||
@RequestMapping("/api/copy-trading/templates")
|
||||
class CopyTradingTemplateController(
|
||||
private val templateService: CopyTradingTemplateService
|
||||
private val templateService: CopyTradingTemplateService,
|
||||
private val messageSource: MessageSource
|
||||
) {
|
||||
|
||||
private val logger = LoggerFactory.getLogger(CopyTradingTemplateController::class.java)
|
||||
@@ -25,7 +27,7 @@ class CopyTradingTemplateController(
|
||||
fun createTemplate(@RequestBody request: TemplateCreateRequest): ResponseEntity<ApiResponse<TemplateDto>> {
|
||||
return try {
|
||||
if (request.templateName.isBlank()) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_TEMPLATE_NAME_EMPTY))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_TEMPLATE_NAME_EMPTY, messageSource = messageSource))
|
||||
}
|
||||
|
||||
val result = templateService.createTemplate(request)
|
||||
@@ -36,14 +38,14 @@ class CopyTradingTemplateController(
|
||||
onFailure = { e ->
|
||||
logger.error("创建模板失败: ${e.message}", e)
|
||||
when (e) {
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_CREATE_FAILED, e.message))
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_CREATE_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("创建模板异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_CREATE_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_CREATE_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +56,7 @@ class CopyTradingTemplateController(
|
||||
fun updateTemplate(@RequestBody request: TemplateUpdateRequest): ResponseEntity<ApiResponse<TemplateDto>> {
|
||||
return try {
|
||||
if (request.templateId <= 0) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_TEMPLATE_ID_INVALID))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_TEMPLATE_ID_INVALID, messageSource = messageSource))
|
||||
}
|
||||
|
||||
val result = templateService.updateTemplate(request)
|
||||
@@ -65,14 +67,14 @@ class CopyTradingTemplateController(
|
||||
onFailure = { e ->
|
||||
logger.error("更新模板失败: ${e.message}", e)
|
||||
when (e) {
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_UPDATE_FAILED, e.message))
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_UPDATE_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("更新模板异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_UPDATE_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_UPDATE_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +85,7 @@ class CopyTradingTemplateController(
|
||||
fun deleteTemplate(@RequestBody request: TemplateDeleteRequest): ResponseEntity<ApiResponse<Unit>> {
|
||||
return try {
|
||||
if (request.templateId <= 0) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_TEMPLATE_ID_INVALID))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_TEMPLATE_ID_INVALID, messageSource = messageSource))
|
||||
}
|
||||
|
||||
val result = templateService.deleteTemplate(request.templateId)
|
||||
@@ -94,15 +96,15 @@ class CopyTradingTemplateController(
|
||||
onFailure = { e ->
|
||||
logger.error("删除模板失败: ${e.message}", e)
|
||||
when (e) {
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message))
|
||||
is IllegalStateException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.BUSINESS_ERROR, e.message))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_DELETE_FAILED, e.message))
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
is IllegalStateException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.BUSINESS_ERROR, e.message, messageSource))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_DELETE_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("删除模板异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_DELETE_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_DELETE_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,10 +115,10 @@ class CopyTradingTemplateController(
|
||||
fun copyTemplate(@RequestBody request: TemplateCopyRequest): ResponseEntity<ApiResponse<TemplateDto>> {
|
||||
return try {
|
||||
if (request.templateId <= 0) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_TEMPLATE_ID_INVALID))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_TEMPLATE_ID_INVALID, messageSource = messageSource))
|
||||
}
|
||||
if (request.templateName.isBlank()) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_TEMPLATE_NAME_EMPTY))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_TEMPLATE_NAME_EMPTY, messageSource = messageSource))
|
||||
}
|
||||
|
||||
val result = templateService.copyTemplate(request)
|
||||
@@ -127,14 +129,14 @@ class CopyTradingTemplateController(
|
||||
onFailure = { e ->
|
||||
logger.error("复制模板失败: ${e.message}", e)
|
||||
when (e) {
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_COPY_FAILED, e.message))
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_COPY_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("复制模板异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_COPY_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_COPY_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,12 +153,12 @@ class CopyTradingTemplateController(
|
||||
},
|
||||
onFailure = { e ->
|
||||
logger.error("查询模板列表失败: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_LIST_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_LIST_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("查询模板列表异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_LIST_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_LIST_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +169,7 @@ class CopyTradingTemplateController(
|
||||
fun getTemplateDetail(@RequestBody request: TemplateDetailRequest): ResponseEntity<ApiResponse<TemplateDto>> {
|
||||
return try {
|
||||
if (request.templateId <= 0) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_TEMPLATE_ID_INVALID))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_TEMPLATE_ID_INVALID, messageSource = messageSource))
|
||||
}
|
||||
|
||||
val result = templateService.getTemplateDetail(request.templateId)
|
||||
@@ -178,14 +180,14 @@ class CopyTradingTemplateController(
|
||||
onFailure = { e ->
|
||||
logger.error("查询模板详情失败: ${e.message}", e)
|
||||
when (e) {
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_DETAIL_FETCH_FAILED, e.message))
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_DETAIL_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("查询模板详情异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_DETAIL_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_TEMPLATE_DETAIL_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.wrbug.polymarketbot.dto.*
|
||||
import com.wrbug.polymarketbot.enums.ErrorCode
|
||||
import com.wrbug.polymarketbot.service.LeaderService
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.context.MessageSource
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.*
|
||||
|
||||
@@ -13,7 +14,8 @@ import org.springframework.web.bind.annotation.*
|
||||
@RestController
|
||||
@RequestMapping("/api/copy-trading/leaders")
|
||||
class LeaderController(
|
||||
private val leaderService: LeaderService
|
||||
private val leaderService: LeaderService,
|
||||
private val messageSource: MessageSource
|
||||
) {
|
||||
|
||||
private val logger = LoggerFactory.getLogger(LeaderController::class.java)
|
||||
@@ -25,7 +27,7 @@ class LeaderController(
|
||||
fun addLeader(@RequestBody request: LeaderAddRequest): ResponseEntity<ApiResponse<LeaderDto>> {
|
||||
return try {
|
||||
if (request.leaderAddress.isBlank()) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_LEADER_ADDRESS_EMPTY))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_LEADER_ADDRESS_EMPTY, messageSource = messageSource))
|
||||
}
|
||||
|
||||
val result = leaderService.addLeader(request)
|
||||
@@ -36,15 +38,15 @@ class LeaderController(
|
||||
onFailure = { e ->
|
||||
logger.error("添加 Leader 失败: ${e.message}", e)
|
||||
when (e) {
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message))
|
||||
is IllegalStateException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.BUSINESS_ERROR, e.message))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_LEADER_ADD_FAILED, e.message))
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
is IllegalStateException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.BUSINESS_ERROR, e.message, messageSource))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_LEADER_ADD_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("添加 Leader 异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_LEADER_ADD_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_LEADER_ADD_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +57,7 @@ class LeaderController(
|
||||
fun updateLeader(@RequestBody request: LeaderUpdateRequest): ResponseEntity<ApiResponse<LeaderDto>> {
|
||||
return try {
|
||||
if (request.leaderId <= 0) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_LEADER_ID_INVALID))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_LEADER_ID_INVALID, messageSource = messageSource))
|
||||
}
|
||||
|
||||
val result = leaderService.updateLeader(request)
|
||||
@@ -66,14 +68,14 @@ class LeaderController(
|
||||
onFailure = { e ->
|
||||
logger.error("更新 Leader 失败: ${e.message}", e)
|
||||
when (e) {
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_LEADER_UPDATE_FAILED, e.message))
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_LEADER_UPDATE_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("更新 Leader 异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_LEADER_UPDATE_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_LEADER_UPDATE_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +86,7 @@ class LeaderController(
|
||||
fun deleteLeader(@RequestBody request: LeaderDeleteRequest): ResponseEntity<ApiResponse<Unit>> {
|
||||
return try {
|
||||
if (request.leaderId <= 0) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_LEADER_ID_INVALID))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_LEADER_ID_INVALID, messageSource = messageSource))
|
||||
}
|
||||
|
||||
val result = leaderService.deleteLeader(request.leaderId)
|
||||
@@ -95,15 +97,15 @@ class LeaderController(
|
||||
onFailure = { e ->
|
||||
logger.error("删除 Leader 失败: ${e.message}", e)
|
||||
when (e) {
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message))
|
||||
is IllegalStateException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.BUSINESS_ERROR, e.message))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_LEADER_DELETE_FAILED, e.message))
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
is IllegalStateException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.BUSINESS_ERROR, e.message, messageSource))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_LEADER_DELETE_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("删除 Leader 异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_LEADER_DELETE_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_LEADER_DELETE_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,12 +122,12 @@ class LeaderController(
|
||||
},
|
||||
onFailure = { e ->
|
||||
logger.error("查询 Leader 列表失败: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_LEADER_LIST_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_LEADER_LIST_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("查询 Leader 列表异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_LEADER_LIST_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_LEADER_LIST_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +138,7 @@ class LeaderController(
|
||||
fun getLeaderDetail(@RequestBody request: LeaderDetailRequest): ResponseEntity<ApiResponse<LeaderDto>> {
|
||||
return try {
|
||||
if (request.leaderId <= 0) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_LEADER_ID_INVALID))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_LEADER_ID_INVALID, messageSource = messageSource))
|
||||
}
|
||||
|
||||
val result = leaderService.getLeaderDetail(request.leaderId)
|
||||
@@ -147,14 +149,14 @@ class LeaderController(
|
||||
onFailure = { e ->
|
||||
logger.error("查询 Leader 详情失败: ${e.message}", e)
|
||||
when (e) {
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_LEADER_DETAIL_FETCH_FAILED, e.message))
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_LEADER_DETAIL_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("查询 Leader 详情异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_LEADER_DETAIL_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_LEADER_DETAIL_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -166,3 +168,7 @@ data class LeaderDetailRequest(
|
||||
val leaderId: Long
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.wrbug.polymarketbot.service.AccountService
|
||||
import com.wrbug.polymarketbot.service.PolymarketClobService
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.context.MessageSource
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.*
|
||||
|
||||
@@ -18,7 +19,8 @@ import org.springframework.web.bind.annotation.*
|
||||
@RequestMapping("/api/copy-trading/markets")
|
||||
class MarketController(
|
||||
private val accountService: AccountService,
|
||||
private val clobService: PolymarketClobService
|
||||
private val clobService: PolymarketClobService,
|
||||
private val messageSource: MessageSource
|
||||
) {
|
||||
|
||||
private val logger = LoggerFactory.getLogger(MarketController::class.java)
|
||||
@@ -31,7 +33,7 @@ class MarketController(
|
||||
fun getMarketPrice(@RequestBody request: MarketPriceRequest): ResponseEntity<ApiResponse<MarketPriceResponse>> {
|
||||
return try {
|
||||
if (request.marketId.isBlank()) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_MARKET_ID_EMPTY))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_MARKET_ID_EMPTY, messageSource = messageSource))
|
||||
}
|
||||
|
||||
val result = runBlocking { accountService.getMarketPrice(request.marketId) }
|
||||
@@ -41,12 +43,12 @@ class MarketController(
|
||||
},
|
||||
onFailure = { e ->
|
||||
logger.error("获取市场价格失败: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_MARKET_PRICE_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_MARKET_PRICE_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("获取市场价格异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_MARKET_PRICE_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_MARKET_PRICE_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +61,7 @@ class MarketController(
|
||||
fun getLatestPrice(@RequestBody request: LatestPriceRequest): ResponseEntity<ApiResponse<LatestPriceResponse>> {
|
||||
return try {
|
||||
if (request.tokenId.isBlank()) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_TOKEN_ID_EMPTY))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_TOKEN_ID_EMPTY, messageSource = messageSource))
|
||||
}
|
||||
|
||||
val result = runBlocking { clobService.getLatestPrice(request.tokenId) }
|
||||
@@ -69,13 +71,17 @@ class MarketController(
|
||||
},
|
||||
onFailure = { e ->
|
||||
logger.error("获取最新价失败: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_MARKET_LATEST_PRICE_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_MARKET_LATEST_PRICE_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("获取最新价异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_MARKET_LATEST_PRICE_FETCH_FAILED, e.message))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_MARKET_LATEST_PRICE_FETCH_FAILED, e.message, messageSource))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+16
-10
@@ -7,6 +7,7 @@ import com.wrbug.polymarketbot.service.ProxyConfigService
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.context.MessageSource
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.*
|
||||
|
||||
@@ -17,7 +18,8 @@ import org.springframework.web.bind.annotation.*
|
||||
@RequestMapping("/api/proxy-config")
|
||||
class ProxyConfigController(
|
||||
private val proxyConfigService: ProxyConfigService,
|
||||
private val apiHealthCheckService: ApiHealthCheckService
|
||||
private val apiHealthCheckService: ApiHealthCheckService,
|
||||
private val messageSource: MessageSource
|
||||
) {
|
||||
|
||||
private val logger = LoggerFactory.getLogger(ProxyConfigController::class.java)
|
||||
@@ -32,7 +34,7 @@ class ProxyConfigController(
|
||||
ResponseEntity.ok(ApiResponse.success(config))
|
||||
} catch (e: Exception) {
|
||||
logger.error("获取代理配置失败", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "获取代理配置失败:${e.message}"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "获取代理配置失败:${e.message}", messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +48,7 @@ class ProxyConfigController(
|
||||
ResponseEntity.ok(ApiResponse.success(configs))
|
||||
} catch (e: Exception) {
|
||||
logger.error("获取代理配置列表失败", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "获取代理配置列表失败:${e.message}"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "获取代理配置列表失败:${e.message}", messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,11 +64,11 @@ class ProxyConfigController(
|
||||
} else {
|
||||
val error = result.exceptionOrNull()
|
||||
logger.error("保存 HTTP 代理配置失败", error)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, error?.message ?: "保存失败"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, error?.message ?: "保存失败", messageSource))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logger.error("保存 HTTP 代理配置异常", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "保存 HTTP 代理配置失败:${e.message}"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "保存 HTTP 代理配置失败:${e.message}", messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +82,7 @@ class ProxyConfigController(
|
||||
ResponseEntity.ok(ApiResponse.success(result))
|
||||
} catch (e: Exception) {
|
||||
logger.error("代理检查失败", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "代理检查失败:${e.message}"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "代理检查失败:${e.message}", messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +93,7 @@ class ProxyConfigController(
|
||||
fun deleteProxyConfig(@RequestBody request: Map<String, Long>): ResponseEntity<ApiResponse<Unit>> {
|
||||
return try {
|
||||
val id = request["id"] ?: return ResponseEntity.ok(
|
||||
ApiResponse.error(ErrorCode.PARAM_ERROR, "参数错误:缺少 id")
|
||||
ApiResponse.error(ErrorCode.PARAM_ERROR, "参数错误:缺少 id", messageSource)
|
||||
)
|
||||
|
||||
val result = proxyConfigService.deleteProxyConfig(id)
|
||||
@@ -100,11 +102,11 @@ class ProxyConfigController(
|
||||
} else {
|
||||
val error = result.exceptionOrNull()
|
||||
logger.error("删除代理配置失败:id=$id", error)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, error?.message ?: "删除失败"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, error?.message ?: "删除失败", messageSource))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logger.error("删除代理配置异常", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "删除代理配置失败:${e.message}"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "删除代理配置失败:${e.message}", messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,8 +120,12 @@ class ProxyConfigController(
|
||||
ResponseEntity.ok(ApiResponse.success(result))
|
||||
} catch (e: Exception) {
|
||||
logger.error("API 健康检查失败", e)
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "API 健康检查失败:${e.message}"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "API 健康检查失败:${e.message}", messageSource))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.wrbug.polymarketbot.enums.ErrorCode
|
||||
import com.wrbug.polymarketbot.service.UserService
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.context.MessageSource
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.*
|
||||
|
||||
@@ -14,7 +15,8 @@ import org.springframework.web.bind.annotation.*
|
||||
@RestController
|
||||
@RequestMapping("/api/users")
|
||||
class UserController(
|
||||
private val userService: UserService
|
||||
private val userService: UserService,
|
||||
private val messageSource: MessageSource
|
||||
) {
|
||||
|
||||
private val logger = LoggerFactory.getLogger(UserController::class.java)
|
||||
@@ -49,14 +51,14 @@ class UserController(
|
||||
return try {
|
||||
val currentUsername = getCurrentUsername(request)
|
||||
if (currentUsername == null) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_ERROR.code, "未获取到用户信息"))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_ERROR, "未获取到用户信息", messageSource))
|
||||
}
|
||||
|
||||
val users = userService.getUserList(currentUsername)
|
||||
ResponseEntity.ok(ApiResponse.success(users))
|
||||
} catch (e: Exception) {
|
||||
logger.error("获取用户列表异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.serverError("获取用户列表失败: ${e.message}"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "获取用户列表失败: ${e.message}", messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,15 +86,15 @@ class UserController(
|
||||
onFailure = { e ->
|
||||
logger.error("创建用户失败: ${e.message}", e)
|
||||
when (e) {
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.paramError(e.message ?: "参数错误"))
|
||||
is IllegalStateException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_PERMISSION_DENIED.code, e.message ?: "权限不足"))
|
||||
else -> ResponseEntity.ok(ApiResponse.serverError("创建用户失败: ${e.message}"))
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
is IllegalStateException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_PERMISSION_DENIED, e.message, messageSource))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "创建用户失败: ${e.message}", messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("创建用户异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.serverError("创建用户失败: ${e.message}"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "创建用户失败: ${e.message}", messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,15 +122,15 @@ class UserController(
|
||||
onFailure = { e ->
|
||||
logger.error("更新用户密码失败: ${e.message}", e)
|
||||
when (e) {
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.paramError(e.message ?: "参数错误"))
|
||||
is IllegalStateException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_PERMISSION_DENIED.code, e.message ?: "权限不足"))
|
||||
else -> ResponseEntity.ok(ApiResponse.serverError("更新用户密码失败: ${e.message}"))
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
is IllegalStateException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_PERMISSION_DENIED, e.message, messageSource))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "更新用户密码失败: ${e.message}", messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("更新用户密码异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.serverError("更新用户密码失败: ${e.message}"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "更新用户密码失败: ${e.message}", messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +145,7 @@ class UserController(
|
||||
return try {
|
||||
val currentUsername = getCurrentUsername(httpRequest)
|
||||
if (currentUsername == null) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_ERROR.code, "未获取到用户信息"))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_ERROR, "未获取到用户信息", messageSource))
|
||||
}
|
||||
|
||||
val result = userService.updateOwnPassword(requestBody.newPassword, currentUsername)
|
||||
@@ -155,14 +157,14 @@ class UserController(
|
||||
onFailure = { e ->
|
||||
logger.error("修改自己密码失败: ${e.message}", e)
|
||||
when (e) {
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.paramError(e.message ?: "参数错误"))
|
||||
else -> ResponseEntity.ok(ApiResponse.serverError("修改密码失败: ${e.message}"))
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "修改密码失败: ${e.message}", messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("修改自己密码异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.serverError("修改密码失败: ${e.message}"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "修改密码失败: ${e.message}", messageSource))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +179,7 @@ class UserController(
|
||||
return try {
|
||||
val error = checkDefaultUser(httpRequest)
|
||||
if (error != null) {
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_PERMISSION_DENIED.code, error))
|
||||
return ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_PERMISSION_DENIED, error, messageSource))
|
||||
}
|
||||
|
||||
val currentUsername = getCurrentUsername(httpRequest)!!
|
||||
@@ -190,15 +192,15 @@ class UserController(
|
||||
onFailure = { e ->
|
||||
logger.error("删除用户失败: ${e.message}", e)
|
||||
when (e) {
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.paramError(e.message ?: "参数错误"))
|
||||
is IllegalStateException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_PERMISSION_DENIED.code, e.message ?: "权限不足"))
|
||||
else -> ResponseEntity.ok(ApiResponse.serverError("删除用户失败: ${e.message}"))
|
||||
is IllegalArgumentException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource))
|
||||
is IllegalStateException -> ResponseEntity.ok(ApiResponse.error(ErrorCode.AUTH_PERMISSION_DENIED, e.message, messageSource))
|
||||
else -> ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "删除用户失败: ${e.message}", messageSource))
|
||||
}
|
||||
}
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.error("删除用户异常: ${e.message}", e)
|
||||
ResponseEntity.ok(ApiResponse.serverError("删除用户失败: ${e.message}"))
|
||||
ResponseEntity.ok(ApiResponse.error(ErrorCode.SERVER_ERROR, "删除用户失败: ${e.message}", messageSource))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package com.wrbug.polymarketbot.dto
|
||||
|
||||
import com.wrbug.polymarketbot.enums.ErrorCode
|
||||
import org.springframework.context.MessageSource
|
||||
import org.springframework.context.i18n.LocaleContextHolder
|
||||
|
||||
/**
|
||||
* 统一API响应格式
|
||||
* @param code 响应码,0表示成功,非0表示失败
|
||||
* @param data 响应数据,可以是任意类型(对象、数组、字符串、数字等)
|
||||
* @param msg 响应消息,成功时通常为空,失败时包含错误提示
|
||||
* @param msg 响应消息,成功时通常为空,失败时包含错误提示(已国际化)
|
||||
*/
|
||||
data class ApiResponse<T>(
|
||||
val code: Int,
|
||||
@@ -22,13 +24,40 @@ data class ApiResponse<T>(
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建失败响应(使用 ErrorCode 枚举)
|
||||
* 创建失败响应(使用 ErrorCode 枚举,支持多语言)
|
||||
* @param errorCode 错误码枚举
|
||||
* @param customMsg 自定义消息(可选,如果提供则使用自定义消息,否则使用国际化消息)
|
||||
* @param messageSource 消息源(可选,如果提供则使用国际化,否则使用默认消息)
|
||||
*/
|
||||
fun <T> error(errorCode: ErrorCode, customMsg: String? = null): ApiResponse<T> {
|
||||
fun <T> error(
|
||||
errorCode: ErrorCode,
|
||||
customMsg: String? = null,
|
||||
messageSource: MessageSource? = null
|
||||
): ApiResponse<T> {
|
||||
val msg: String = if (customMsg != null) {
|
||||
customMsg
|
||||
} else if (messageSource != null) {
|
||||
// 使用 MessageSource 获取国际化消息
|
||||
try {
|
||||
messageSource.getMessage(
|
||||
errorCode.messageKey,
|
||||
null,
|
||||
errorCode.message, // 默认消息(fallback)
|
||||
LocaleContextHolder.getLocale()
|
||||
) ?: errorCode.message
|
||||
} catch (e: Exception) {
|
||||
// 如果获取失败,使用默认消息
|
||||
errorCode.message
|
||||
}
|
||||
} else {
|
||||
// 如果没有提供 MessageSource,使用默认消息
|
||||
errorCode.message
|
||||
}
|
||||
|
||||
return ApiResponse(
|
||||
code = errorCode.code,
|
||||
data = null,
|
||||
msg = customMsg ?: errorCode.message
|
||||
msg = msg
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -19,202 +19,203 @@ package com.wrbug.polymarketbot.enums
|
||||
*/
|
||||
enum class ErrorCode(
|
||||
val code: Int,
|
||||
val message: String
|
||||
val message: String,
|
||||
val messageKey: String
|
||||
) {
|
||||
// ==================== 参数错误 (1001-1999) ====================
|
||||
PARAM_ERROR(1001, "参数错误"),
|
||||
PARAM_EMPTY(1002, "参数不能为空"),
|
||||
PARAM_INVALID(1003, "参数无效"),
|
||||
PARAM_ERROR(1001, "参数错误", "error.param.error"),
|
||||
PARAM_EMPTY(1002, "参数不能为空", "error.param.empty"),
|
||||
PARAM_INVALID(1003, "参数无效", "error.param.invalid"),
|
||||
|
||||
// 账户相关参数错误
|
||||
PARAM_PRIVATE_KEY_EMPTY(1101, "私钥不能为空"),
|
||||
PARAM_WALLET_ADDRESS_EMPTY(1102, "钱包地址不能为空"),
|
||||
PARAM_WALLET_ADDRESS_INVALID(1103, "钱包地址格式无效"),
|
||||
PARAM_ACCOUNT_ID_INVALID(1104, "账户ID无效"),
|
||||
PARAM_ACCOUNT_NAME_EMPTY(1105, "账户名称不能为空"),
|
||||
PARAM_PRIVATE_KEY_EMPTY(1101, "私钥不能为空", "error.param.private_key_empty"),
|
||||
PARAM_WALLET_ADDRESS_EMPTY(1102, "钱包地址不能为空", "error.param.wallet_address_empty"),
|
||||
PARAM_WALLET_ADDRESS_INVALID(1103, "钱包地址格式无效", "error.param.wallet_address_invalid"),
|
||||
PARAM_ACCOUNT_ID_INVALID(1104, "账户ID无效", "error.param.account_id_invalid"),
|
||||
PARAM_ACCOUNT_NAME_EMPTY(1105, "账户名称不能为空", "error.param.account_name_empty"),
|
||||
|
||||
// Leader 相关参数错误
|
||||
PARAM_LEADER_ADDRESS_EMPTY(1201, "Leader 地址不能为空"),
|
||||
PARAM_LEADER_ADDRESS_INVALID(1202, "Leader 地址格式无效"),
|
||||
PARAM_LEADER_ID_INVALID(1203, "Leader ID 无效"),
|
||||
PARAM_LEADER_NAME_EMPTY(1204, "Leader 名称不能为空"),
|
||||
PARAM_CATEGORY_INVALID(1205, "分类无效,只支持 sports 或 crypto"),
|
||||
PARAM_LEADER_ADDRESS_EMPTY(1201, "Leader 地址不能为空", "error.param.leader_address_empty"),
|
||||
PARAM_LEADER_ADDRESS_INVALID(1202, "Leader 地址格式无效", "error.param.leader_address_invalid"),
|
||||
PARAM_LEADER_ID_INVALID(1203, "Leader ID 无效", "error.param.leader_id_invalid"),
|
||||
PARAM_LEADER_NAME_EMPTY(1204, "Leader 名称不能为空", "error.param.leader_name_empty"),
|
||||
PARAM_CATEGORY_INVALID(1205, "分类无效,只支持 sports 或 crypto", "error.param.category_invalid"),
|
||||
|
||||
// 模板相关参数错误
|
||||
PARAM_TEMPLATE_NAME_EMPTY(1301, "模板名称不能为空"),
|
||||
PARAM_TEMPLATE_ID_INVALID(1302, "模板 ID 无效"),
|
||||
PARAM_COPY_MODE_INVALID(1303, "copyMode 必须是 RATIO 或 FIXED"),
|
||||
PARAM_COPY_RATIO_INVALID(1304, "跟单比例无效"),
|
||||
PARAM_FIXED_AMOUNT_INVALID(1305, "固定金额无效"),
|
||||
PARAM_TEMPLATE_NAME_EMPTY(1301, "模板名称不能为空", "error.param.template_name_empty"),
|
||||
PARAM_TEMPLATE_ID_INVALID(1302, "模板 ID 无效", "error.param.template_id_invalid"),
|
||||
PARAM_COPY_MODE_INVALID(1303, "copyMode 必须是 RATIO 或 FIXED", "error.param.copy_mode_invalid"),
|
||||
PARAM_COPY_RATIO_INVALID(1304, "跟单比例无效", "error.param.copy_ratio_invalid"),
|
||||
PARAM_FIXED_AMOUNT_INVALID(1305, "固定金额无效", "error.param.fixed_amount_invalid"),
|
||||
|
||||
// 跟单相关参数错误
|
||||
PARAM_COPY_TRADING_ID_INVALID(1401, "跟单关系ID无效"),
|
||||
PARAM_ORDER_TYPE_INVALID(1402, "订单类型无效"),
|
||||
PARAM_ORDER_TYPE_MUST_BE_MARKET_OR_LIMIT(1403, "订单类型必须是MARKET或LIMIT"),
|
||||
PARAM_QUANTITY_EMPTY(1404, "数量不能为空"),
|
||||
PARAM_PRICE_EMPTY(1405, "限价订单必须提供价格"),
|
||||
PARAM_SIDE_EMPTY(1406, "方向不能为空"),
|
||||
PARAM_MARKET_ID_EMPTY(1407, "市场ID不能为空"),
|
||||
PARAM_ORDER_TYPE_EMPTY(1408, "订单类型不能为空"),
|
||||
PARAM_COPY_TRADING_ID_INVALID(1401, "跟单关系ID无效", "error.param.copy_trading_id_invalid"),
|
||||
PARAM_ORDER_TYPE_INVALID(1402, "订单类型无效", "error.param.order_type_invalid"),
|
||||
PARAM_ORDER_TYPE_MUST_BE_MARKET_OR_LIMIT(1403, "订单类型必须是MARKET或LIMIT", "error.param.order_type_must_be_market_or_limit"),
|
||||
PARAM_QUANTITY_EMPTY(1404, "数量不能为空", "error.param.quantity_empty"),
|
||||
PARAM_PRICE_EMPTY(1405, "限价订单必须提供价格", "error.param.price_empty"),
|
||||
PARAM_SIDE_EMPTY(1406, "方向不能为空", "error.param.side_empty"),
|
||||
PARAM_MARKET_ID_EMPTY(1407, "市场ID不能为空", "error.param.market_id_empty"),
|
||||
PARAM_ORDER_TYPE_EMPTY(1408, "订单类型不能为空", "error.param.order_type_empty"),
|
||||
|
||||
// 市场相关参数错误
|
||||
PARAM_TOKEN_ID_EMPTY(1501, "tokenId 不能为空"),
|
||||
PARAM_CONDITION_ID_EMPTY(1502, "conditionId 不能为空"),
|
||||
PARAM_REDEEM_POSITIONS_EMPTY(1503, "赎回仓位列表不能为空"),
|
||||
PARAM_INDEX_SETS_INVALID(1504, "结果索引无效"),
|
||||
PARAM_TOKEN_ID_EMPTY(1501, "tokenId 不能为空", "error.param.token_id_empty"),
|
||||
PARAM_CONDITION_ID_EMPTY(1502, "conditionId 不能为空", "error.param.condition_id_empty"),
|
||||
PARAM_REDEEM_POSITIONS_EMPTY(1503, "赎回仓位列表不能为空", "error.param.redeem_positions_empty"),
|
||||
PARAM_INDEX_SETS_INVALID(1504, "结果索引无效", "error.param.index_sets_invalid"),
|
||||
|
||||
// 统计相关参数错误
|
||||
PARAM_ORDER_TYPE_INVALID_FOR_TRACKING(1601, "订单类型无效,必须是: buy, sell, matched"),
|
||||
PARAM_ORDER_TYPE_INVALID_FOR_TRACKING(1601, "订单类型无效,必须是: buy, sell, matched", "error.param.order_type_invalid_for_tracking"),
|
||||
|
||||
// ==================== 认证/权限错误 (2001-2999) ====================
|
||||
AUTH_ERROR(2001, "认证失败"),
|
||||
AUTH_TOKEN_INVALID(2002, "认证令牌无效"),
|
||||
AUTH_TOKEN_EXPIRED(2003, "认证令牌已过期"),
|
||||
AUTH_PERMISSION_DENIED(2004, "权限不足"),
|
||||
AUTH_API_KEY_INVALID(2005, "API Key 无效"),
|
||||
AUTH_API_SECRET_INVALID(2006, "API Secret 无效"),
|
||||
AUTH_API_PASSPHRASE_INVALID(2007, "API Passphrase 无效"),
|
||||
AUTH_API_CREDENTIALS_MISSING(2008, "API 凭证未配置"),
|
||||
AUTH_USERNAME_OR_PASSWORD_ERROR(2009, "用户名或密码错误"),
|
||||
AUTH_RESET_KEY_INVALID(2010, "重置密钥错误"),
|
||||
AUTH_RESET_PASSWORD_RATE_LIMIT(2011, "频率限制:1分钟内最多尝试3次,请稍后再试"),
|
||||
AUTH_USER_NOT_FOUND(2012, "用户不存在"),
|
||||
AUTH_PASSWORD_WEAK(2013, "密码长度不符合要求,至少6位"),
|
||||
AUTH_ERROR(2001, "认证失败", "error.auth.error"),
|
||||
AUTH_TOKEN_INVALID(2002, "认证令牌无效", "error.auth.token_invalid"),
|
||||
AUTH_TOKEN_EXPIRED(2003, "认证令牌已过期", "error.auth.token_expired"),
|
||||
AUTH_PERMISSION_DENIED(2004, "权限不足", "error.auth.permission_denied"),
|
||||
AUTH_API_KEY_INVALID(2005, "API Key 无效", "error.auth.api_key_invalid"),
|
||||
AUTH_API_SECRET_INVALID(2006, "API Secret 无效", "error.auth.api_secret_invalid"),
|
||||
AUTH_API_PASSPHRASE_INVALID(2007, "API Passphrase 无效", "error.auth.api_passphrase_invalid"),
|
||||
AUTH_API_CREDENTIALS_MISSING(2008, "API 凭证未配置", "error.auth.api_credentials_missing"),
|
||||
AUTH_USERNAME_OR_PASSWORD_ERROR(2009, "用户名或密码错误", "error.auth.username_or_password_error"),
|
||||
AUTH_RESET_KEY_INVALID(2010, "重置密钥错误", "error.auth.reset_key_invalid"),
|
||||
AUTH_RESET_PASSWORD_RATE_LIMIT(2011, "频率限制:1分钟内最多尝试3次,请稍后再试", "error.auth.reset_password_rate_limit"),
|
||||
AUTH_USER_NOT_FOUND(2012, "用户不存在", "error.auth.user_not_found"),
|
||||
AUTH_PASSWORD_WEAK(2013, "密码长度不符合要求,至少6位", "error.auth.password_weak"),
|
||||
|
||||
// ==================== 资源不存在 (3001-3999) ====================
|
||||
NOT_FOUND(3001, "资源不存在"),
|
||||
ACCOUNT_NOT_FOUND(3002, "账户不存在"),
|
||||
LEADER_NOT_FOUND(3003, "Leader 不存在"),
|
||||
TEMPLATE_NOT_FOUND(3004, "模板不存在"),
|
||||
COPY_TRADING_NOT_FOUND(3005, "跟单关系不存在"),
|
||||
MARKET_NOT_FOUND(3006, "市场不存在"),
|
||||
ORDER_NOT_FOUND(3007, "订单不存在"),
|
||||
POSITION_NOT_FOUND(3008, "仓位不存在"),
|
||||
NOT_FOUND(3001, "资源不存在", "error.not_found"),
|
||||
ACCOUNT_NOT_FOUND(3002, "账户不存在", "error.account_not_found"),
|
||||
LEADER_NOT_FOUND(3003, "Leader 不存在", "error.leader_not_found"),
|
||||
TEMPLATE_NOT_FOUND(3004, "模板不存在", "error.template_not_found"),
|
||||
COPY_TRADING_NOT_FOUND(3005, "跟单关系不存在", "error.copy_trading_not_found"),
|
||||
MARKET_NOT_FOUND(3006, "市场不存在", "error.market_not_found"),
|
||||
ORDER_NOT_FOUND(3007, "订单不存在", "error.order_not_found"),
|
||||
POSITION_NOT_FOUND(3008, "仓位不存在", "error.position_not_found"),
|
||||
|
||||
// ==================== 业务逻辑错误 (4001-4999) ====================
|
||||
BUSINESS_ERROR(4001, "业务逻辑错误"),
|
||||
BUSINESS_ERROR(4001, "业务逻辑错误", "error.business.error"),
|
||||
|
||||
// Leader 管理 (4001-4099)
|
||||
LEADER_ALREADY_EXISTS(4001, "该 Leader 地址已存在"),
|
||||
LEADER_ADDRESS_SAME_AS_ACCOUNT(4002, "Leader 地址不能与自己的账户地址相同"),
|
||||
LEADER_HAS_COPY_TRADINGS(4003, "该 Leader 还有跟单关系,请先删除跟单关系"),
|
||||
LEADER_ALREADY_EXISTS(4001, "该 Leader 地址已存在", "error.leader_already_exists"),
|
||||
LEADER_ADDRESS_SAME_AS_ACCOUNT(4002, "Leader 地址不能与自己的账户地址相同", "error.leader_address_same_as_account"),
|
||||
LEADER_HAS_COPY_TRADINGS(4003, "该 Leader 还有跟单关系,请先删除跟单关系", "error.leader_has_copy_tradings"),
|
||||
|
||||
// 模板管理 (4101-4199)
|
||||
TEMPLATE_NAME_ALREADY_EXISTS(4101, "模板名称已存在"),
|
||||
TEMPLATE_HAS_COPY_TRADINGS(4102, "该模板还有跟单关系在使用,请先删除跟单关系"),
|
||||
TEMPLATE_NAME_ALREADY_EXISTS(4101, "模板名称已存在", "error.template_name_already_exists"),
|
||||
TEMPLATE_HAS_COPY_TRADINGS(4102, "该模板还有跟单关系在使用,请先删除跟单关系", "error.template_has_copy_tradings"),
|
||||
|
||||
// 跟单管理 (4201-4299)
|
||||
COPY_TRADING_ALREADY_EXISTS(4201, "该跟单关系已存在"),
|
||||
COPY_TRADING_DISABLED(4202, "跟单关系已禁用"),
|
||||
COPY_TRADING_ENABLED(4203, "跟单关系已启用"),
|
||||
NO_ENABLED_COPY_TRADINGS(4204, "没有启用的跟单关系"),
|
||||
COPY_TRADING_ALREADY_EXISTS(4201, "该跟单关系已存在", "error.copy_trading_already_exists"),
|
||||
COPY_TRADING_DISABLED(4202, "跟单关系已禁用", "error.copy_trading_disabled"),
|
||||
COPY_TRADING_ENABLED(4203, "跟单关系已启用", "error.copy_trading_enabled"),
|
||||
NO_ENABLED_COPY_TRADINGS(4204, "没有启用的跟单关系", "error.no_enabled_copy_tradings"),
|
||||
|
||||
// 订单相关 (4301-4399)
|
||||
ORDER_CREATE_FAILED(4301, "创建订单失败"),
|
||||
ORDER_CANCEL_FAILED(4302, "取消订单失败"),
|
||||
ORDER_NOT_MATCHED(4303, "订单未匹配"),
|
||||
ORDER_ALREADY_FILLED(4304, "订单已成交"),
|
||||
ORDER_INSUFFICIENT_BALANCE(4305, "余额不足"),
|
||||
ORDER_AMOUNT_TOO_SMALL(4306, "订单金额低于最小限制"),
|
||||
ORDER_AMOUNT_TOO_LARGE(4307, "订单金额超过最大限制"),
|
||||
ORDER_PRICE_INVALID(4308, "订单价格无效"),
|
||||
ORDER_QUANTITY_INVALID(4309, "订单数量无效"),
|
||||
ORDER_CREATE_FAILED(4301, "创建订单失败", "error.order_create_failed"),
|
||||
ORDER_CANCEL_FAILED(4302, "取消订单失败", "error.order_cancel_failed"),
|
||||
ORDER_NOT_MATCHED(4303, "订单未匹配", "error.order_not_matched"),
|
||||
ORDER_ALREADY_FILLED(4304, "订单已成交", "error.order_already_filled"),
|
||||
ORDER_INSUFFICIENT_BALANCE(4305, "余额不足", "error.order_insufficient_balance"),
|
||||
ORDER_AMOUNT_TOO_SMALL(4306, "订单金额低于最小限制", "error.order_amount_too_small"),
|
||||
ORDER_AMOUNT_TOO_LARGE(4307, "订单金额超过最大限制", "error.order_amount_too_large"),
|
||||
ORDER_PRICE_INVALID(4308, "订单价格无效", "error.order_price_invalid"),
|
||||
ORDER_QUANTITY_INVALID(4309, "订单数量无效", "error.order_quantity_invalid"),
|
||||
|
||||
// 市场相关 (4401-4499)
|
||||
MARKET_PRICE_FETCH_FAILED(4401, "获取市场价格失败"),
|
||||
MARKET_ORDERBOOK_EMPTY(4402, "订单簿为空"),
|
||||
MARKET_TOKEN_ID_INVALID(4403, "Token ID 无效"),
|
||||
MARKET_PRICE_FETCH_FAILED(4401, "获取市场价格失败", "error.market_price_fetch_failed"),
|
||||
MARKET_ORDERBOOK_EMPTY(4402, "订单簿为空", "error.market_orderbook_empty"),
|
||||
MARKET_TOKEN_ID_INVALID(4403, "Token ID 无效", "error.market_token_id_invalid"),
|
||||
|
||||
// 仓位相关 (4501-4599)
|
||||
POSITION_REDEEM_FAILED(4501, "赎回仓位失败"),
|
||||
POSITION_NOT_REDEEMABLE(4502, "仓位不可赎回"),
|
||||
POSITION_INSUFFICIENT(4503, "仓位不足"),
|
||||
POSITION_ALREADY_REDEEMED(4504, "仓位已赎回"),
|
||||
POSITION_REDEEM_FAILED(4501, "赎回仓位失败", "error.position_redeem_failed"),
|
||||
POSITION_NOT_REDEEMABLE(4502, "仓位不可赎回", "error.position_not_redeemable"),
|
||||
POSITION_INSUFFICIENT(4503, "仓位不足", "error.position_insufficient"),
|
||||
POSITION_ALREADY_REDEEMED(4504, "仓位已赎回", "error.position_already_redeemed"),
|
||||
|
||||
// 账户相关业务错误 (4601-4699)
|
||||
ACCOUNT_ALREADY_EXISTS(4601, "账户已存在"),
|
||||
ACCOUNT_IS_DEFAULT(4602, "账户已是默认账户"),
|
||||
ACCOUNT_HAS_ACTIVE_ORDERS(4603, "账户有活跃订单"),
|
||||
ACCOUNT_IS_LAST_ONE(4604, "不能删除最后一个账户"),
|
||||
ACCOUNT_API_KEY_CREATE_FAILED(4605, "自动获取 API Key 失败"),
|
||||
ACCOUNT_PROXY_ADDRESS_FETCH_FAILED(4606, "获取代理地址失败"),
|
||||
ACCOUNT_BALANCE_FETCH_FAILED(4607, "查询账户余额失败"),
|
||||
ACCOUNT_POSITIONS_FETCH_FAILED(4608, "查询仓位列表失败"),
|
||||
ACCOUNT_ALREADY_EXISTS(4601, "账户已存在", "error.account_already_exists"),
|
||||
ACCOUNT_IS_DEFAULT(4602, "账户已是默认账户", "error.account_is_default"),
|
||||
ACCOUNT_HAS_ACTIVE_ORDERS(4603, "账户有活跃订单", "error.account_has_active_orders"),
|
||||
ACCOUNT_IS_LAST_ONE(4604, "不能删除最后一个账户", "error.account_is_last_one"),
|
||||
ACCOUNT_API_KEY_CREATE_FAILED(4605, "自动获取 API Key 失败", "error.account_api_key_create_failed"),
|
||||
ACCOUNT_PROXY_ADDRESS_FETCH_FAILED(4606, "获取代理地址失败", "error.account_proxy_address_fetch_failed"),
|
||||
ACCOUNT_BALANCE_FETCH_FAILED(4607, "查询账户余额失败", "error.account_balance_fetch_failed"),
|
||||
ACCOUNT_POSITIONS_FETCH_FAILED(4608, "查询仓位列表失败", "error.account_positions_fetch_failed"),
|
||||
|
||||
// 统计相关 (4701-4799)
|
||||
STATISTICS_FETCH_FAILED(4701, "获取统计信息失败"),
|
||||
ORDER_LIST_FETCH_FAILED(4702, "查询订单列表失败"),
|
||||
STATISTICS_FETCH_FAILED(4701, "获取统计信息失败", "error.statistics_fetch_failed"),
|
||||
ORDER_LIST_FETCH_FAILED(4702, "查询订单列表失败", "error.order_list_fetch_failed"),
|
||||
|
||||
// ==================== 服务器内部错误 (5001-5999) ====================
|
||||
SERVER_ERROR(5001, "服务器内部错误"),
|
||||
SERVER_DATABASE_ERROR(5002, "数据库错误"),
|
||||
SERVER_NETWORK_ERROR(5003, "网络错误"),
|
||||
SERVER_TIMEOUT(5004, "请求超时"),
|
||||
SERVER_EXTERNAL_API_ERROR(5005, "外部API调用失败"),
|
||||
SERVER_RPC_ERROR(5006, "RPC调用失败"),
|
||||
SERVER_WEBSOCKET_ERROR(5007, "WebSocket连接错误"),
|
||||
SERVER_ENCRYPTION_ERROR(5008, "加密/解密错误"),
|
||||
SERVER_SIGNATURE_ERROR(5009, "签名错误"),
|
||||
SERVER_ERROR(5001, "服务器内部错误", "error.server.error"),
|
||||
SERVER_DATABASE_ERROR(5002, "数据库错误", "error.server.database_error"),
|
||||
SERVER_NETWORK_ERROR(5003, "网络错误", "error.server.network_error"),
|
||||
SERVER_TIMEOUT(5004, "请求超时", "error.server.timeout"),
|
||||
SERVER_EXTERNAL_API_ERROR(5005, "外部API调用失败", "error.server.external_api_error"),
|
||||
SERVER_RPC_ERROR(5006, "RPC调用失败", "error.server.rpc_error"),
|
||||
SERVER_WEBSOCKET_ERROR(5007, "WebSocket连接错误", "error.server.websocket_error"),
|
||||
SERVER_ENCRYPTION_ERROR(5008, "加密/解密错误", "error.server.encryption_error"),
|
||||
SERVER_SIGNATURE_ERROR(5009, "签名错误", "error.server.signature_error"),
|
||||
|
||||
// 账户服务错误 (5101-5199)
|
||||
SERVER_ACCOUNT_IMPORT_FAILED(5101, "导入账户失败"),
|
||||
SERVER_ACCOUNT_UPDATE_FAILED(5102, "更新账户失败"),
|
||||
SERVER_ACCOUNT_DELETE_FAILED(5103, "删除账户失败"),
|
||||
SERVER_ACCOUNT_LIST_FETCH_FAILED(5104, "查询账户列表失败"),
|
||||
SERVER_ACCOUNT_DETAIL_FETCH_FAILED(5105, "查询账户详情失败"),
|
||||
SERVER_ACCOUNT_BALANCE_FETCH_FAILED(5106, "查询账户余额失败"),
|
||||
SERVER_ACCOUNT_DEFAULT_SET_FAILED(5107, "设置默认账户失败"),
|
||||
SERVER_ACCOUNT_POSITIONS_FETCH_FAILED(5108, "查询仓位列表失败"),
|
||||
SERVER_ACCOUNT_ORDER_CREATE_FAILED(5109, "创建卖出订单失败"),
|
||||
SERVER_ACCOUNT_REDEEM_POSITIONS_FAILED(5110, "赎回仓位失败"),
|
||||
SERVER_ACCOUNT_IMPORT_FAILED(5101, "导入账户失败", "error.server.account_import_failed"),
|
||||
SERVER_ACCOUNT_UPDATE_FAILED(5102, "更新账户失败", "error.server.account_update_failed"),
|
||||
SERVER_ACCOUNT_DELETE_FAILED(5103, "删除账户失败", "error.server.account_delete_failed"),
|
||||
SERVER_ACCOUNT_LIST_FETCH_FAILED(5104, "查询账户列表失败", "error.server.account_list_fetch_failed"),
|
||||
SERVER_ACCOUNT_DETAIL_FETCH_FAILED(5105, "查询账户详情失败", "error.server.account_detail_fetch_failed"),
|
||||
SERVER_ACCOUNT_BALANCE_FETCH_FAILED(5106, "查询账户余额失败", "error.server.account_balance_fetch_failed"),
|
||||
SERVER_ACCOUNT_DEFAULT_SET_FAILED(5107, "设置默认账户失败", "error.server.account_default_set_failed"),
|
||||
SERVER_ACCOUNT_POSITIONS_FETCH_FAILED(5108, "查询仓位列表失败", "error.server.account_positions_fetch_failed"),
|
||||
SERVER_ACCOUNT_ORDER_CREATE_FAILED(5109, "创建卖出订单失败", "error.server.account_order_create_failed"),
|
||||
SERVER_ACCOUNT_REDEEM_POSITIONS_FAILED(5110, "赎回仓位失败", "error.server.account_redeem_positions_failed"),
|
||||
|
||||
// Leader 服务错误 (5201-5299)
|
||||
SERVER_LEADER_ADD_FAILED(5201, "添加 Leader 失败"),
|
||||
SERVER_LEADER_UPDATE_FAILED(5202, "更新 Leader 失败"),
|
||||
SERVER_LEADER_DELETE_FAILED(5203, "删除 Leader 失败"),
|
||||
SERVER_LEADER_LIST_FETCH_FAILED(5204, "查询 Leader 列表失败"),
|
||||
SERVER_LEADER_DETAIL_FETCH_FAILED(5205, "查询 Leader 详情失败"),
|
||||
SERVER_LEADER_ADD_FAILED(5201, "添加 Leader 失败", "error.server.leader_add_failed"),
|
||||
SERVER_LEADER_UPDATE_FAILED(5202, "更新 Leader 失败", "error.server.leader_update_failed"),
|
||||
SERVER_LEADER_DELETE_FAILED(5203, "删除 Leader 失败", "error.server.leader_delete_failed"),
|
||||
SERVER_LEADER_LIST_FETCH_FAILED(5204, "查询 Leader 列表失败", "error.server.leader_list_fetch_failed"),
|
||||
SERVER_LEADER_DETAIL_FETCH_FAILED(5205, "查询 Leader 详情失败", "error.server.leader_detail_fetch_failed"),
|
||||
|
||||
// 模板服务错误 (5301-5399)
|
||||
SERVER_TEMPLATE_CREATE_FAILED(5301, "创建模板失败"),
|
||||
SERVER_TEMPLATE_UPDATE_FAILED(5302, "更新模板失败"),
|
||||
SERVER_TEMPLATE_DELETE_FAILED(5303, "删除模板失败"),
|
||||
SERVER_TEMPLATE_COPY_FAILED(5304, "复制模板失败"),
|
||||
SERVER_TEMPLATE_LIST_FETCH_FAILED(5305, "查询模板列表失败"),
|
||||
SERVER_TEMPLATE_DETAIL_FETCH_FAILED(5306, "查询模板详情失败"),
|
||||
SERVER_TEMPLATE_CREATE_FAILED(5301, "创建模板失败", "error.server.template_create_failed"),
|
||||
SERVER_TEMPLATE_UPDATE_FAILED(5302, "更新模板失败", "error.server.template_update_failed"),
|
||||
SERVER_TEMPLATE_DELETE_FAILED(5303, "删除模板失败", "error.server.template_delete_failed"),
|
||||
SERVER_TEMPLATE_COPY_FAILED(5304, "复制模板失败", "error.server.template_copy_failed"),
|
||||
SERVER_TEMPLATE_LIST_FETCH_FAILED(5305, "查询模板列表失败", "error.server.template_list_fetch_failed"),
|
||||
SERVER_TEMPLATE_DETAIL_FETCH_FAILED(5306, "查询模板详情失败", "error.server.template_detail_fetch_failed"),
|
||||
|
||||
// 跟单服务错误 (5401-5499)
|
||||
SERVER_COPY_TRADING_CREATE_FAILED(5401, "创建跟单失败"),
|
||||
SERVER_COPY_TRADING_UPDATE_FAILED(5402, "更新跟单失败"),
|
||||
SERVER_COPY_TRADING_DELETE_FAILED(5403, "删除跟单失败"),
|
||||
SERVER_COPY_TRADING_LIST_FETCH_FAILED(5404, "查询跟单列表失败"),
|
||||
SERVER_COPY_TRADING_TEMPLATES_FETCH_FAILED(5405, "查询钱包绑定的模板失败"),
|
||||
SERVER_COPY_TRADING_CREATE_FAILED(5401, "创建跟单失败", "error.server.copy_trading_create_failed"),
|
||||
SERVER_COPY_TRADING_UPDATE_FAILED(5402, "更新跟单失败", "error.server.copy_trading_update_failed"),
|
||||
SERVER_COPY_TRADING_DELETE_FAILED(5403, "删除跟单失败", "error.server.copy_trading_delete_failed"),
|
||||
SERVER_COPY_TRADING_LIST_FETCH_FAILED(5404, "查询跟单列表失败", "error.server.copy_trading_list_fetch_failed"),
|
||||
SERVER_COPY_TRADING_TEMPLATES_FETCH_FAILED(5405, "查询钱包绑定的模板失败", "error.server.copy_trading_templates_fetch_failed"),
|
||||
|
||||
// 市场服务错误 (5501-5599)
|
||||
SERVER_MARKET_PRICE_FETCH_FAILED(5501, "获取市场价格失败"),
|
||||
SERVER_MARKET_LATEST_PRICE_FETCH_FAILED(5502, "获取最新价失败"),
|
||||
SERVER_MARKET_PRICE_FETCH_FAILED(5501, "获取市场价格失败", "error.server.market_price_fetch_failed"),
|
||||
SERVER_MARKET_LATEST_PRICE_FETCH_FAILED(5502, "获取最新价失败", "error.server.market_latest_price_fetch_failed"),
|
||||
|
||||
// 统计服务错误 (5601-5699)
|
||||
SERVER_STATISTICS_FETCH_FAILED(5601, "获取统计信息失败"),
|
||||
SERVER_ORDER_TRACKING_LIST_FETCH_FAILED(5602, "查询订单列表失败"),
|
||||
SERVER_STATISTICS_FETCH_FAILED(5601, "获取统计信息失败", "error.server.statistics_fetch_failed"),
|
||||
SERVER_ORDER_TRACKING_LIST_FETCH_FAILED(5602, "查询订单列表失败", "error.server.order_tracking_list_fetch_failed"),
|
||||
|
||||
// 区块链服务错误 (5701-5799)
|
||||
SERVER_BLOCKCHAIN_RPC_ERROR(5701, "区块链RPC调用失败"),
|
||||
SERVER_BLOCKCHAIN_PROXY_ADDRESS_FETCH_FAILED(5702, "获取代理地址失败"),
|
||||
SERVER_BLOCKCHAIN_BALANCE_FETCH_FAILED(5703, "查询余额失败"),
|
||||
SERVER_BLOCKCHAIN_POSITIONS_FETCH_FAILED(5704, "查询仓位失败"),
|
||||
SERVER_BLOCKCHAIN_REDEEM_FAILED(5705, "赎回仓位交易失败"),
|
||||
SERVER_BLOCKCHAIN_RPC_ERROR(5701, "区块链RPC调用失败", "error.server.blockchain_rpc_error"),
|
||||
SERVER_BLOCKCHAIN_PROXY_ADDRESS_FETCH_FAILED(5702, "获取代理地址失败", "error.server.blockchain_proxy_address_fetch_failed"),
|
||||
SERVER_BLOCKCHAIN_BALANCE_FETCH_FAILED(5703, "查询余额失败", "error.server.blockchain_balance_fetch_failed"),
|
||||
SERVER_BLOCKCHAIN_POSITIONS_FETCH_FAILED(5704, "查询仓位失败", "error.server.blockchain_positions_fetch_failed"),
|
||||
SERVER_BLOCKCHAIN_REDEEM_FAILED(5705, "赎回仓位交易失败", "error.server.blockchain_redeem_failed"),
|
||||
|
||||
// WebSocket 服务错误 (5801-5899)
|
||||
SERVER_WEBSOCKET_CONNECTION_FAILED(5801, "WebSocket连接失败"),
|
||||
SERVER_WEBSOCKET_MESSAGE_SEND_FAILED(5802, "WebSocket消息发送失败"),
|
||||
SERVER_WEBSOCKET_SUBSCRIBE_FAILED(5803, "WebSocket订阅失败"),
|
||||
SERVER_WEBSOCKET_CONNECTION_FAILED(5801, "WebSocket连接失败", "error.server.websocket_connection_failed"),
|
||||
SERVER_WEBSOCKET_MESSAGE_SEND_FAILED(5802, "WebSocket消息发送失败", "error.server.websocket_message_send_failed"),
|
||||
SERVER_WEBSOCKET_SUBSCRIBE_FAILED(5803, "WebSocket订阅失败", "error.server.websocket_subscribe_failed"),
|
||||
|
||||
// 订单跟踪服务错误 (5901-5999)
|
||||
SERVER_ORDER_TRACKING_PROCESS_FAILED(5901, "处理订单跟踪失败"),
|
||||
SERVER_ORDER_TRACKING_BUY_FAILED(5902, "处理买入订单失败"),
|
||||
SERVER_ORDER_TRACKING_SELL_FAILED(5903, "处理卖出订单失败"),
|
||||
SERVER_ORDER_TRACKING_MATCH_FAILED(5904, "订单匹配失败");
|
||||
SERVER_ORDER_TRACKING_PROCESS_FAILED(5901, "处理订单跟踪失败", "error.server.order_tracking_process_failed"),
|
||||
SERVER_ORDER_TRACKING_BUY_FAILED(5902, "处理买入订单失败", "error.server.order_tracking_buy_failed"),
|
||||
SERVER_ORDER_TRACKING_SELL_FAILED(5903, "处理卖出订单失败", "error.server.order_tracking_sell_failed"),
|
||||
SERVER_ORDER_TRACKING_MATCH_FAILED(5904, "订单匹配失败", "error.server.order_tracking_match_failed");
|
||||
|
||||
companion object {
|
||||
/**
|
||||
@@ -225,8 +226,9 @@ enum class ErrorCode(
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据错误码获取错误消息
|
||||
* 根据错误码获取错误消息(已废弃,使用 messageKey + MessageSource)
|
||||
*/
|
||||
@Deprecated("使用 messageKey + MessageSource 获取多语言消息", ReplaceWith("使用 ErrorCode.messageKey"))
|
||||
fun getMessage(code: Int): String {
|
||||
return fromCode(code)?.message ?: "未知错误"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.wrbug.polymarketbot.util
|
||||
|
||||
/**
|
||||
* ApiResponse 扩展函数
|
||||
*
|
||||
* 注意:ApiResponse.error() 方法已经在 ApiResponse.kt 中定义,支持多语言。
|
||||
* 此文件保留用于未来可能的扩展功能。
|
||||
*
|
||||
* 使用方式:
|
||||
* ApiResponse.error(ErrorCode.PARAM_ERROR, messageSource = messageSource)
|
||||
* ApiResponse.error(ErrorCode.PARAM_ERROR, "自定义消息", messageSource)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
package com.wrbug.polymarketbot.util
|
||||
|
||||
import com.wrbug.polymarketbot.enums.ErrorCode
|
||||
import org.springframework.context.MessageSource
|
||||
import org.springframework.context.i18n.LocaleContextHolder
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
/**
|
||||
* 消息工具类
|
||||
* 用于获取国际化消息
|
||||
*/
|
||||
@Component
|
||||
class MessageUtils(
|
||||
private val messageSource: MessageSource
|
||||
) {
|
||||
/**
|
||||
* 根据 ErrorCode 获取国际化错误消息
|
||||
*/
|
||||
fun getMessage(errorCode: ErrorCode): String {
|
||||
return try {
|
||||
messageSource.getMessage(
|
||||
errorCode.messageKey,
|
||||
null,
|
||||
errorCode.message, // 默认消息(fallback)
|
||||
LocaleContextHolder.getLocale()
|
||||
) ?: errorCode.message
|
||||
} catch (e: Exception) {
|
||||
// 如果获取失败,使用默认消息
|
||||
errorCode.message
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据消息键获取国际化消息
|
||||
* @param key 消息键
|
||||
* @param defaultMessage 默认消息(如果找不到消息键)
|
||||
* @param args 消息参数(用于占位符替换)
|
||||
*/
|
||||
fun getMessage(key: String, defaultMessage: String = key, vararg args: Any?): String {
|
||||
return try {
|
||||
messageSource.getMessage(
|
||||
key,
|
||||
args,
|
||||
defaultMessage,
|
||||
LocaleContextHolder.getLocale()
|
||||
) ?: defaultMessage
|
||||
} catch (e: Exception) {
|
||||
defaultMessage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
import com.wrbug.polymarketbot.enums.ErrorCode
|
||||
import org.springframework.context.MessageSource
|
||||
import org.springframework.context.i18n.LocaleContextHolder
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
/**
|
||||
* 消息工具类
|
||||
* 用于获取国际化消息
|
||||
*/
|
||||
@Component
|
||||
class MessageUtils(
|
||||
private val messageSource: MessageSource
|
||||
) {
|
||||
/**
|
||||
* 根据 ErrorCode 获取国际化错误消息
|
||||
*/
|
||||
fun getMessage(errorCode: ErrorCode): String {
|
||||
return try {
|
||||
messageSource.getMessage(
|
||||
errorCode.messageKey,
|
||||
null,
|
||||
errorCode.message, // 默认消息(fallback)
|
||||
LocaleContextHolder.getLocale()
|
||||
) ?: errorCode.message
|
||||
} catch (e: Exception) {
|
||||
// 如果获取失败,使用默认消息
|
||||
errorCode.message
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据消息键获取国际化消息
|
||||
* @param key 消息键
|
||||
* @param defaultMessage 默认消息(如果找不到消息键)
|
||||
* @param args 消息参数(用于占位符替换)
|
||||
*/
|
||||
fun getMessage(key: String, defaultMessage: String = key, vararg args: Any?): String {
|
||||
return try {
|
||||
messageSource.getMessage(
|
||||
key,
|
||||
args,
|
||||
defaultMessage,
|
||||
LocaleContextHolder.getLocale()
|
||||
) ?: defaultMessage
|
||||
} catch (e: Exception) {
|
||||
defaultMessage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user