修复apiresult的问题;增加用户详情查看的逻辑
This commit is contained in:
@@ -12,6 +12,7 @@ import com.bbit.ticket.entity.common.BizException
|
||||
import com.bbit.ticket.entity.common.ErrorCode
|
||||
import com.bbit.ticket.entity.common.PageResult
|
||||
import com.bbit.ticket.entity.common.statusLabel
|
||||
import com.bbit.ticket.entity.common.system.UserRoleBrief
|
||||
import com.bbit.ticket.utils.ApiKeyUtil
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import org.jetbrains.exposed.v1.core.Op
|
||||
@@ -90,10 +91,26 @@ object UserDao {
|
||||
|
||||
fun detail(id: Uuid): UserDetailResponse {
|
||||
val user = requireActive(id)
|
||||
val roleIds = SysUserRoleTable.selectAll()
|
||||
.where { SysUserRoleTable.userId eq id }
|
||||
.map { it[SysUserRoleTable.roleId].toString() }
|
||||
return user.toUserDetail(roleIds)
|
||||
val roles = (SysUserRoleTable innerJoin SysRoleTable)
|
||||
.selectAll()
|
||||
.where {
|
||||
(SysUserRoleTable.userId eq id) and
|
||||
SysRoleTable.deletedAt.isNull()
|
||||
}
|
||||
.map {
|
||||
UserRoleBrief(
|
||||
id = it[SysRoleTable.id].toString(),
|
||||
name = it[SysRoleTable.name],
|
||||
code = it[SysRoleTable.code],
|
||||
)
|
||||
}
|
||||
val roleIds = roles.map { it.id }
|
||||
val org = user[SysUserTable.orgId]?.let { orgId ->
|
||||
SysOrgTable.selectAll()
|
||||
.where { (SysOrgTable.id eq orgId) and SysOrgTable.deletedAt.isNull() }
|
||||
.singleOrNull()
|
||||
}
|
||||
return user.toUserDetail(roleIds, roles, org)
|
||||
}
|
||||
|
||||
fun updateProfile(id: Uuid, request: UpdateUserRequest, orgId: Uuid?) {
|
||||
@@ -226,7 +243,11 @@ object UserDao {
|
||||
apiKey = this[SysUserTable.apiKey],
|
||||
)
|
||||
|
||||
private fun ResultRow.toUserDetail(roleIds: List<String>) = UserDetailResponse(
|
||||
private fun ResultRow.toUserDetail(
|
||||
roleIds: List<String>,
|
||||
roles: List<UserRoleBrief>,
|
||||
org: ResultRow?,
|
||||
) = UserDetailResponse(
|
||||
id = this[SysUserTable.id].toString(),
|
||||
username = this[SysUserTable.username],
|
||||
nickname = this[SysUserTable.nickname],
|
||||
@@ -235,13 +256,38 @@ object UserDao {
|
||||
email = this[SysUserTable.email],
|
||||
avatar = this[SysUserTable.avatar],
|
||||
orgId = this[SysUserTable.orgId]?.toString(),
|
||||
orgName = org?.get(SysOrgTable.name),
|
||||
orgCode = org?.get(SysOrgTable.code),
|
||||
status = this[SysUserTable.status],
|
||||
statusLabel = statusLabel(this[SysUserTable.status]),
|
||||
roleIds = roleIds,
|
||||
roles = roles,
|
||||
apiKey = this[SysUserTable.apiKey],
|
||||
tokenVersion = this[SysUserTable.tokenVersion],
|
||||
lastLoginAt = this[SysUserTable.lastLoginAt]?.toString(),
|
||||
lastLoginIp = this[SysUserTable.lastLoginIp],
|
||||
createdAt = this[SysUserTable.createdAt].toString(),
|
||||
createdBy = this[SysUserTable.createdBy]?.toString(),
|
||||
updatedAt = this[SysUserTable.updatedAt]?.toString(),
|
||||
updatedBy = this[SysUserTable.updatedBy]?.toString(),
|
||||
deletedAt = this[SysUserTable.deletedAt]?.toString(),
|
||||
deletedBy = this[SysUserTable.deletedBy]?.toString(),
|
||||
version = this[SysUserTable.version],
|
||||
taxpayerNum = this[SysUserTable.taxpayerNum],
|
||||
account = this[SysUserTable.taxAccount],
|
||||
taxPassword = this[SysUserTable.taxPassword],
|
||||
taxIdentityType = this[SysUserTable.taxIdentityType],
|
||||
taxContactName = this[SysUserTable.taxContactName],
|
||||
taxContactPhone = this[SysUserTable.taxContactPhone],
|
||||
taxContactEmail = this[SysUserTable.taxContactEmail],
|
||||
taxLegalPersonName = this[SysUserTable.taxLegalPersonName],
|
||||
taxEnterpriseName = this[SysUserTable.taxEnterpriseName],
|
||||
taxRegionCode = this[SysUserTable.taxRegionCode],
|
||||
taxCityName = this[SysUserTable.taxCityName],
|
||||
taxEnterpriseAddress = this[SysUserTable.taxEnterpriseAddress],
|
||||
taxRegistrationCertificate = this[SysUserTable.taxRegistrationCertificate],
|
||||
bankName = this[SysUserTable.bankName],
|
||||
bankAccount = this[SysUserTable.bankAccount],
|
||||
presetAddress = this[SysUserTable.presetAddress],
|
||||
presetPhone = this[SysUserTable.presetPhone],
|
||||
)
|
||||
}
|
||||
|
||||
@@ -24,14 +24,46 @@ data class UserDetailResponse(
|
||||
val email: String? = null,
|
||||
val avatar: String? = null,
|
||||
val orgId: String? = null,
|
||||
val orgName: String? = null,
|
||||
val orgCode: String? = null,
|
||||
val status: String,
|
||||
val statusLabel: String,
|
||||
val roleIds: List<String>,
|
||||
val roles: List<UserRoleBrief> = emptyList(),
|
||||
val apiKey: String? = null,
|
||||
val tokenVersion: Int,
|
||||
val lastLoginAt: String? = null,
|
||||
val lastLoginIp: String? = null,
|
||||
val createdAt: String? = null,
|
||||
val createdBy: String? = null,
|
||||
val updatedAt: String? = null,
|
||||
val updatedBy: String? = null,
|
||||
val deletedAt: String? = null,
|
||||
val deletedBy: String? = null,
|
||||
val version: Int,
|
||||
val taxpayerNum: String? = null,
|
||||
val account: String? = null,
|
||||
val taxPassword: String? = null,
|
||||
val taxIdentityType: String? = null,
|
||||
val taxContactName: String? = null,
|
||||
val taxContactPhone: String? = null,
|
||||
val taxContactEmail: String? = null,
|
||||
val taxLegalPersonName: String? = null,
|
||||
val taxEnterpriseName: String? = null,
|
||||
val taxRegionCode: String? = null,
|
||||
val taxCityName: String? = null,
|
||||
val taxEnterpriseAddress: String? = null,
|
||||
val taxRegistrationCertificate: String? = null,
|
||||
val bankName: String? = null,
|
||||
val bankAccount: String? = null,
|
||||
val presetAddress: String? = null,
|
||||
val presetPhone: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class UserRoleBrief(
|
||||
val id: String,
|
||||
val name: String,
|
||||
val code: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
|
||||
+12
-8
@@ -12,9 +12,10 @@ import com.bbit.ticket.service.openapi.OpenBlueInvoiceService
|
||||
import com.bbit.ticket.service.system.ApiAccessLogService
|
||||
import com.bbit.ticket.utils.requireOpenApiPrincipal
|
||||
import com.bbit.ticket.utils.plugins.myJson
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.server.application.ApplicationCall
|
||||
import io.ktor.server.request.receive
|
||||
import io.ktor.server.response.respond
|
||||
import io.ktor.server.response.respondText
|
||||
import io.ktor.server.routing.Route
|
||||
import io.ktor.server.routing.get
|
||||
import io.ktor.server.routing.post
|
||||
@@ -92,20 +93,23 @@ private suspend inline fun <reified T> ApplicationCall.respondOpenApi(
|
||||
try {
|
||||
val response = ok(block())
|
||||
val responseBody = myJson.encodeToString(response)
|
||||
respond(response)
|
||||
respondText(responseBody, ContentType.Application.Json)
|
||||
saveOpenApiLog(appKey, appName, requestBody, response.code, responseBody, "SUCCESS", null, start)
|
||||
} catch (e: PTException) {
|
||||
val response = fail(code = e.code, message = e.message, traceId = e.serialNo)
|
||||
respond(response)
|
||||
saveOpenApiLog(appKey, appName, requestBody, e.code, myJson.encodeToString(response), "FAILED", e.message, start)
|
||||
val responseBody = myJson.encodeToString(response)
|
||||
respondText(responseBody, ContentType.Application.Json)
|
||||
saveOpenApiLog(appKey, appName, requestBody, e.code, responseBody, "FAILED", e.message, start)
|
||||
} catch (e: BizException) {
|
||||
val response = fail(code = e.errorCode, message = e.message)
|
||||
respond(e.status, response)
|
||||
saveOpenApiLog(appKey, appName, requestBody, e.errorCode, myJson.encodeToString(response), "FAILED", e.message, start)
|
||||
val responseBody = myJson.encodeToString(response)
|
||||
respondText(responseBody, ContentType.Application.Json, e.status)
|
||||
saveOpenApiLog(appKey, appName, requestBody, e.errorCode, responseBody, "FAILED", e.message, start)
|
||||
} catch (e: Exception) {
|
||||
val response = fail(code = "-1", message = e.message ?: "开放接口调用失败")
|
||||
respond(response)
|
||||
saveOpenApiLog(appKey, appName, requestBody, "-1", myJson.encodeToString(response), "FAILED", e.message, start)
|
||||
val responseBody = myJson.encodeToString(response)
|
||||
respondText(responseBody, ContentType.Application.Json)
|
||||
saveOpenApiLog(appKey, appName, requestBody, "-1", responseBody, "FAILED", e.message, start)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,12 +4,15 @@ import com.bbit.ticket.entity.common.BizException
|
||||
import com.bbit.ticket.entity.common.PTException
|
||||
import com.bbit.ticket.entity.common.fail
|
||||
import com.bbit.ticket.entity.common.ok
|
||||
import com.bbit.ticket.utils.plugins.myJson
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.HttpHeaders
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.server.application.ApplicationCall
|
||||
import io.ktor.server.response.header
|
||||
import io.ktor.server.response.respond
|
||||
import io.ktor.server.response.respondBytes
|
||||
import io.ktor.server.response.respondText
|
||||
import kotlinx.serialization.encodeToString
|
||||
|
||||
/**
|
||||
* 使用统一票通响应格式执行接口逻辑。
|
||||
@@ -22,13 +25,39 @@ suspend inline fun <reified T> ApplicationCall.respondPt(
|
||||
crossinline block: suspend () -> T,
|
||||
) {
|
||||
try {
|
||||
respond(ok(block()))
|
||||
respondJson(ok(block()))
|
||||
} catch (e: PTException) {
|
||||
respond(fail(code = e.code, message = e.message, traceId = e.serialNo))
|
||||
respondJson(fail(code = e.code, message = e.message, traceId = e.serialNo))
|
||||
} catch (e: BizException) {
|
||||
respond(e.status, fail(code = e.errorCode, message = e.message))
|
||||
respondJson(fail(code = e.errorCode, message = e.message), e.status)
|
||||
} catch (e: Exception) {
|
||||
respond(fail(code = "-1", message = e.message ?: fallbackMessage))
|
||||
respondJson(fail(code = "-1", message = e.message ?: fallbackMessage))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用统一票通响应格式执行可空查询,空结果按空对象返回。
|
||||
*
|
||||
* @param fallbackMessage 未知异常时返回给前端的兜底提示。
|
||||
* @param block 当前接口要执行的查询逻辑。
|
||||
*/
|
||||
suspend inline fun <reified T : Any> ApplicationCall.respondPtOrEmptyObject(
|
||||
fallbackMessage: String,
|
||||
crossinline block: suspend () -> T?,
|
||||
) {
|
||||
try {
|
||||
val data = block()
|
||||
if (data == null) {
|
||||
respondJson(ok(emptyMap<String, String>()))
|
||||
} else {
|
||||
respondJson(ok(data))
|
||||
}
|
||||
} catch (e: PTException) {
|
||||
respondJson(fail(code = e.code, message = e.message, traceId = e.serialNo))
|
||||
} catch (e: BizException) {
|
||||
respondJson(fail(code = e.errorCode, message = e.message), e.status)
|
||||
} catch (e: Exception) {
|
||||
respondJson(fail(code = "-1", message = e.message ?: fallbackMessage))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +70,7 @@ suspend inline fun <reified T> ApplicationCall.respondPt(
|
||||
suspend fun ApplicationCall.requiredQueryParameter(name: String, message: String): String? {
|
||||
val value = request.queryParameters[name]?.trim()?.takeIf { it.isNotEmpty() }
|
||||
if (value == null) {
|
||||
respond(fail(code = "-1", message = message))
|
||||
respondJson(fail(code = "-1", message = message))
|
||||
}
|
||||
return value
|
||||
}
|
||||
@@ -62,10 +91,23 @@ suspend fun ApplicationCall.respondPtPdf(
|
||||
response.header(HttpHeaders.ContentDisposition, "inline; filename=\"$filename\"")
|
||||
respondBytes(block(), ContentType.Application.Pdf)
|
||||
} catch (e: PTException) {
|
||||
respond(fail(code = e.code, message = e.message, traceId = e.serialNo))
|
||||
respondJson(fail(code = e.code, message = e.message, traceId = e.serialNo))
|
||||
} catch (e: BizException) {
|
||||
respond(e.status, fail(code = e.errorCode, message = e.message))
|
||||
respondJson(fail(code = e.errorCode, message = e.message), e.status)
|
||||
} catch (e: Exception) {
|
||||
respond(fail(code = "-1", message = e.message ?: fallbackMessage))
|
||||
respondJson(fail(code = "-1", message = e.message ?: fallbackMessage))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显式序列化 JSON 响应,避免 Ktor 在泛型 helper 中丢失 ApiResult<T> 类型信息。
|
||||
*
|
||||
* @param data 要返回的响应对象。
|
||||
* @param status HTTP 状态码。
|
||||
*/
|
||||
suspend inline fun <reified T> ApplicationCall.respondJson(
|
||||
data: T,
|
||||
status: HttpStatusCode = HttpStatusCode.OK,
|
||||
) {
|
||||
respondText(myJson.encodeToString(data), ContentType.Application.Json, status)
|
||||
}
|
||||
|
||||
@@ -57,8 +57,8 @@ fun Route.registerPTAuthRoutes() {
|
||||
}
|
||||
|
||||
get("/enterprise") {
|
||||
call.respondPt("查询企业信息失败") {
|
||||
PTConfigService.getEnterpriseInfo(call.requireCurrentUser().id) ?: emptyMap<String, String>()
|
||||
call.respondPtOrEmptyObject("查询企业信息失败") {
|
||||
PTConfigService.getEnterpriseInfo(call.requireCurrentUser().id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,12 +72,12 @@ fun Route.registerPTAuthRoutes() {
|
||||
}
|
||||
|
||||
get("/digital-account") {
|
||||
call.respondPt("查询数电账号失败") {
|
||||
call.respondPtOrEmptyObject("查询数电账号失败") {
|
||||
val currentUser = call.requireCurrentUser()
|
||||
if (currentUser.taxPayerNum == null) {
|
||||
throw BizException("-1", "请先完善用户信息", HttpStatusCode.OK)
|
||||
}
|
||||
PTConfigService.getDigitalAccount(currentUser.id) ?: emptyMap<String, String>()
|
||||
PTConfigService.getDigitalAccount(currentUser.id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,8 +91,8 @@ fun Route.registerPTAuthRoutes() {
|
||||
}
|
||||
|
||||
get("/preset") {
|
||||
call.respondPt("查询预设数据失败") {
|
||||
PTConfigService.getPresetData(call.requireCurrentUser().id) ?: emptyMap<String, String>()
|
||||
call.respondPtOrEmptyObject("查询预设数据失败") {
|
||||
PTConfigService.getPresetData(call.requireCurrentUser().id)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user