feat: 扩展网络层API和WebSocket消息处理

- 扩展ApiService添加回忆录状态和任务状态接口
- 优化WebSocketClient连接管理
- 增强WebSocketMessage消息类型支持
- 更新MemoirModels数据模型
This commit is contained in:
iammm0
2026-01-22 17:58:30 +08:00
parent 58bd42f814
commit 7f4c3ffb9f
4 changed files with 155 additions and 19 deletions

View File

@@ -95,7 +95,6 @@ class ApiService(
return try {
val response = client.get("$BASE_URL/api/chapters") {
contentType(ContentType.Application.Json)
parameter("user_id", userId)
}
Result.success(response.body())
} catch (e: Exception) {
@@ -261,5 +260,46 @@ class ApiService(
Result.success(Unit)
}
}
// ==================== 回忆录状态相关API ====================
suspend fun getMemoirState(): Result<com.huaga.life_echo.network.models.MemoirStateDto> {
return try {
val response = client.get("$BASE_URL/api/memoir-state") {
contentType(ContentType.Application.Json)
}
Result.success(response.body())
} catch (e: Exception) {
Result.failure(Exception("获取回忆录状态失败: ${e.message}", e))
}
}
// ==================== 任务状态相关API ====================
suspend fun getTasksStatus(): Result<com.huaga.life_echo.network.models.TasksStatusDto> {
return try {
val response = client.get("$BASE_URL/api/tasks/status") {
contentType(ContentType.Application.Json)
}
Result.success(response.body())
} catch (e: Exception) {
Result.failure(Exception("获取任务状态失败: ${e.message}", e))
}
}
suspend fun clearTasks(): Result<Unit> {
return try {
val response = client.delete("$BASE_URL/api/tasks/clear") {
contentType(ContentType.Application.Json)
}
if (response.status.isSuccess()) {
Result.success(Unit)
} else {
Result.failure(Exception("清除任务失败: ${response.status}"))
}
} catch (e: Exception) {
Result.failure(Exception("清除任务失败: ${e.message}", e))
}
}
}

View File

@@ -11,6 +11,10 @@ import io.ktor.http.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.*
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put
import kotlinx.serialization.json.putJsonObject
class WebSocketClient {
private val client = HttpClient(Android) {
@@ -74,7 +78,7 @@ class WebSocketClient {
sendMessage(WebSocketMessage(
type = MessageType.connect,
conversation_id = conversationId,
data = mapOf("status" to "connected")
data = buildJsonObject { put("status", JsonPrimitive("connected")) }
))
} catch (e: Exception) {
@@ -118,7 +122,7 @@ class WebSocketClient {
sendMessage(WebSocketMessage(
type = MessageType.audio_chunk,
conversation_id = conversationId,
data = mapOf("audio_base64" to base64Audio)
data = buildJsonObject { put("audio_base64", JsonPrimitive(base64Audio)) }
))
}
@@ -126,14 +130,15 @@ class WebSocketClient {
sendMessage(WebSocketMessage(
type = MessageType.text,
conversation_id = conversationId,
data = mapOf("text" to text)
data = buildJsonObject { put("text", JsonPrimitive(text)) }
))
}
suspend fun sendEndConversation(conversationId: String) {
sendMessage(WebSocketMessage(
type = MessageType.end_conversation,
conversation_id = conversationId
conversation_id = conversationId,
data = buildJsonObject { }
))
}
@@ -146,7 +151,7 @@ class WebSocketClient {
sendMessage(WebSocketMessage(
type = MessageType.cancel_generation,
conversation_id = conversationId,
data = mapOf("action" to "cancel")
data = buildJsonObject { put("action", JsonPrimitive("cancel")) }
))
}

View File

@@ -1,6 +1,9 @@
package com.huaga.life_echo.network
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.buildJsonObject
@Serializable
enum class MessageType {
@@ -23,7 +26,58 @@ enum class MessageType {
data class WebSocketMessage(
val type: MessageType,
val conversation_id: String? = null,
val data: Map<String, String> = emptyMap(),
val data: JsonObject = buildJsonObject { },
val timestamp: String? = null
)
) {
/**
* 获取data中的字符串值
*/
fun getString(key: String): String? {
return data[key]?.let {
if (it is JsonPrimitive) {
try {
it.content
} catch (e: Exception) {
null
}
} else {
null
}
}
}
/**
* 获取data中的整数值
*/
fun getInt(key: String): Int? {
return data[key]?.let {
if (it is JsonPrimitive) {
try {
it.content.toIntOrNull()
} catch (e: Exception) {
null
}
} else {
null
}
}
}
/**
* 获取data中的布尔值
*/
fun getBoolean(key: String): Boolean? {
return data[key]?.let {
if (it is JsonPrimitive) {
try {
it.content.toBooleanStrictOrNull()
} catch (e: Exception) {
null
}
} else {
null
}
}
}
}

View File

@@ -6,30 +6,31 @@ import kotlinx.serialization.Serializable
* 回忆录相关的数据模型
*/
// 书籍信息DTO扩展版
// 书籍信息DTO匹配服务器格式
@Serializable
data class BookDto(
val id: String,
val userId: String,
val title: String,
val subtitle: String? = null,
val totalPages: Int,
val totalWords: Int,
val updatedAt: Long,
val lastUpdatedAt: Long? = null
val total_pages: Int? = null,
val total_words: Int? = null,
val cover_image_url: String? = null,
val has_update: Boolean = false,
val last_update_chapter_id: String? = null
)
// 章节信息DTO扩展版
// 章节信息DTO匹配服务器格式
@Serializable
data class ChapterDto(
val id: String,
val title: String,
val content: String,
val orderIndex: Int,
val order_index: Int,
val status: String, // "draft", "partial", "completed"
val category: String,
val pageCount: Int? = null,
val updatedAt: Long? = null
val images: List<String> = emptyList(),
val updated_at: String? = null,
val is_new: Boolean = false,
val source_segments: List<String> = emptyList()
)
// 章节内容详情DTO
@@ -45,3 +46,39 @@ data class ChapterContentDto(
val updatedAt: Long,
val quotes: List<String> = emptyList() // 引用内容列表
)
// 回忆录状态DTO
@Serializable
data class MemoirStateDto(
val current_stage: String,
val covered_stages: List<String> = emptyList(),
val slots: Map<String, Map<String, SlotInfo>> = emptyMap()
)
@Serializable
data class SlotInfo(
val snippet: String? = null,
val filled: Boolean = false
)
// 任务状态DTO
@Serializable
data class TasksStatusDto(
val total: Int,
val pending: Int,
val running: Int,
val success: Int,
val failure: Int,
val all_completed: Boolean,
val tasks: List<TaskInfoDto> = emptyList()
)
@Serializable
data class TaskInfoDto(
val task_id: String,
val task_type: String = "memoir",
val status: String, // "pending", "running", "success", "failure"
val created_at: String? = null,
val updated_at: String? = null,
val result: Map<String, String>? = null
)