using Dpz.Core.Service.Network.Models;
using Dpz.Core.Web.Pager;

namespace Dpz.Core.Web.Controllers;

[CheckAuthorize]
public class AiChatController(IAiChatService aiChatService, ILogger<AiChatController> logger)
    : Controller
{
    public async Task<IActionResult> Index()
    {
        // 获取用户的会话列表
        var sessions = await aiChatService.GetSessionListAsync(User.RequiredUserId);
        IPagedList<VmAiChatRecord> records = PagedList<VmAiChatRecord>.Empty();
        string? defaultSessionId = null;
        AiModel? aiModel = null;

        // 第一个会话作为默认会话
        if (sessions.Count > 0)
        {
            defaultSessionId = sessions[0].SessionId;
            records = await aiChatService.GetSessionMessagesAsync(defaultSessionId, 1, 500);
            if (Enum.TryParse(sessions[0].ModelType, out AiModel modelType))
            {
                aiModel = modelType;
            }
        }
        var model = new AiChatModel(
            sessions,
            defaultSessionId,
            aiModel ?? AiModel.Gpt5Mini,
            records
        );
        return View(model);
    }

    /// <summary>
    /// 获取会话列表
    /// </summary>
    [HttpGet]
    public async Task<IActionResult> Sessions()
    {
        var sessions = await aiChatService.GetSessionListAsync(User.RequiredUserId);
        return Json(new ResultInfo(true, sessions));
    }

    /// <summary>
    /// 删除会话
    /// </summary>
    [HttpDelete]
    public async Task<IActionResult> DeleteSession(string sessionId)
    {
        var result = await aiChatService.DeleteSessionAsync(User.RequiredUserId, sessionId);
        return Json(new ResultInfo(result));
    }

    [HttpGet]
    public async Task<IActionResult> ChatMessages(
        string? sessionId,
        int pageIndex = 1,
        int pageSize = 500
    )
    {
        if (string.IsNullOrEmpty(sessionId))
        {
            return PartialView(
                "_ChatMessages",
                new AiChatMessageModel(null, AiModel.Gpt5Mini, PagedList<VmAiChatRecord>.Empty())
            );
        }

        var session = await aiChatService.GetSessionAsync(User.RequiredUserId, sessionId);
        if (session == null)
        {
            return NotFound();
        }
        var messages = await aiChatService.GetSessionMessagesAsync(sessionId, pageIndex, pageSize);

        AiModel? aiModel = null;
        if (Enum.TryParse(session.ModelType, out AiModel modelType))
        {
            aiModel = modelType;
        }
        var model = new AiChatMessageModel(sessionId, aiModel ?? AiModel.Gpt5Mini, messages);

        return PartialView("_ChatMessages", model);
    }

    /// <summary>
    /// 更新会话名称
    /// </summary>
    [HttpPut]
    public async Task<IActionResult> UpdateSessionName(string sessionId, string newName)
    {
        var result = await aiChatService.UpdateSessionNameAsync(
            User.RequiredUserId,
            sessionId,
            newName
        );
        return Json(new ResultInfo(result));
    }

    /// <summary>
    /// 获取会话详情
    /// </summary>
    [HttpGet]
    public async Task<IActionResult> GetSessionModelType(string sessionId)
    {
        var session = await aiChatService.GetSessionAsync(User.RequiredUserId, sessionId);
        if (session == null)
        {
            return Json(ResultInfo.ToFail("会话不存在"));
        }

        if (!Enum.TryParse(session.ModelType, out AiModel modelType))
        {
            modelType = AiModel.Gpt5Mini;
        }

        return Json(new ResultInfo(true, (int)modelType));
    }

    /// <summary>
    /// 更新会话模型
    /// </summary>
    [HttpPut]
    public async Task<IActionResult> UpdateSessionModelType(string sessionId, AiModel modelType)
    {
        // 更新会话的模型类型
        var updated = await aiChatService.UpdateSessionModelTypeAsync(
            User.RequiredUserId,
            sessionId,
            modelType.ToString()
        );
        logger.LogInformation(
            "Updated model type to {ModelValue} for session {SessionId}",
            modelType,
            sessionId
        );
        return Json(new ResultInfo(updated));
    }

    [HttpPost]
    public async Task<IActionResult> CancelMessage(
        [FromQuery] string? sessionId = null,
        [FromQuery] string? connectionId = null
    )
    {
        if (string.IsNullOrWhiteSpace(sessionId))
        {
            logger.LogWarning("Session id is null or empty");
            return BadRequest("Session id is null or empty");
        }
        if (string.IsNullOrWhiteSpace(connectionId))
        {
            logger.LogWarning("connection id null or empty");
            return BadRequest("connection id null or empty");
        }
        // 精确取消指定会话的流
        var tokenKey = $"{sessionId}_{connectionId}";
        if (WebToolsExtensions.CancellationTokens.TryRemove(tokenKey, out var cts))
        {
            try
            {
                await cts.CancelAsync();
                logger.LogInformation(
                    "Stream message cancellation requested and executed, Token Key: {TokenKey}",
                    tokenKey
                );
                return Ok();
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "Error cancelling stream, Token Key: {TokenKey}", tokenKey);
                return BadRequest(ex.Message);
            }
            finally
            {
                cts.Dispose();
            }
        }

        logger.LogWarning(
            "No active stream found for cancellation, Token Key: {TokenKey}",
            tokenKey
        );
        return BadRequest($"No active stream found for cancellation, Token Key: {tokenKey}");
    }

    /// <summary>
    /// 删除消息
    /// </summary>
    /// <param name="messageId"></param>
    /// <returns></returns>
    [HttpDelete]
    public async Task<IActionResult> DeleteMessage(string messageId)
    {
        var result = await aiChatService.DeleteMessageAsync(messageId, User.RequiredUserId);
        if (result.Success)
        {
            return Json(new ResultInfo(true));
        }
        return Json(new ResultInfo(false, result.Message));
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

AiChatController 功能解析

这个控制器是一个 ASP.NET Core MVC 控制器,用于处理与AI聊天相关的各种操作。以下是其主要功能:

主要功能概述

  1. 会话管理

    • 获取会话列表
    • 删除会话
    • 更新会话名称
    • 获取和更新会话使用的AI模型类型
  2. 消息管理

    • 获取聊天消息记录
    • 删除单条消息
    • 取消正在进行的消息流
  3. 视图渲染

    • 主页面视图
    • 聊天消息部分视图

详细功能说明

1. 主页面 (Index)

  • 获取用户的所有聊天会话列表
  • 默认显示第一个会话的消息记录
  • 设置默认的AI模型类型(默认为Gpt5Mini)
  • 返回包含会话列表、默认会话ID、AI模型和消息记录的视图模型

2. 会话相关操作

  • Sessions: 获取当前用户的所有会话列表(JSON格式)
  • DeleteSession: 删除指定会话
  • UpdateSessionName: 更新会话名称
  • GetSessionModelType: 获取会话使用的AI模型类型
  • UpdateSessionModelType: 更新会话使用的AI模型类型

3. 消息相关操作

  • ChatMessages: 获取指定会话的消息记录(分页显示)
  • DeleteMessage: 删除单条消息
  • CancelMessage: 取消正在进行的消息流(通过取消令牌实现)

4. 其他特性

  • 控制器使用 [CheckAuthorize] 属性,表示所有操作都需要授权
  • 使用依赖注入获取 IAiChatServiceILogger 服务
  • 包含详细的日志记录,便于调试和问题追踪
  • 使用强类型视图模型传递数据到视图
  • 部分操作返回JSON格式的结果(如会话列表、操作结果等)

技术特点

  1. 异步编程:所有方法都是异步的,使用 async/await 模式
  2. 分页处理:使用 IPagedList 处理消息记录的分页
  3. 强类型模型:使用特定的视图模型(如 AiChatModel, AiChatMessageModel
  4. 错误处理:通过日志记录和返回适当的HTTP状态码处理错误
  5. RESTful风格:使用适当的HTTP方法(GET, POST, PUT, DELETE)

这个控制器为前端提供了一个完整的API接口,用于管理AI聊天会话和消息。

评论加载中...