From c1c43c146493b00171d19d819c59e34f9c6f15a8 Mon Sep 17 00:00:00 2001 From: ccnetcore Date: Mon, 9 Feb 2026 23:24:41 +0800 Subject: [PATCH 1/6] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dapi=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Yi.Framework.AiHub.Domain.Shared/Enums/GoodsTypeEnum.cs | 4 ++-- Yi.Abp.Net8/src/Yi.Abp.Web/Program.cs | 2 ++ Yi.Ai.Vue3/src/pages/chat/api/index.vue | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain.Shared/Enums/GoodsTypeEnum.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain.Shared/Enums/GoodsTypeEnum.cs index 0ec815b3..5a9700ff 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain.Shared/Enums/GoodsTypeEnum.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain.Shared/Enums/GoodsTypeEnum.cs @@ -99,8 +99,8 @@ public enum GoodsTypeEnum [Price(83.7, 3, 27.9)] [DisplayName("YiXinVip 3 month", "3个月", "短期体验")] [GoodsCategory(GoodsCategoryType.Vip)] YiXinVip3 = 3, - [Price(114.5, 5, 22.9)] [DisplayName("YiXinVip 5 month", "5个月", "年度热销")] [GoodsCategory(GoodsCategoryType.Vip)] - YiXinVip5 = 15, + [Price(91.6, 4, 22.9)] [DisplayName("YiXinVip 4 month", "4个月", "年度热销")] [GoodsCategory(GoodsCategoryType.Vip)] + YiXinVip5 = 14, // 尊享包服务 - 需要VIP资格才能购买 [Price(188.9, 0, 1750)] diff --git a/Yi.Abp.Net8/src/Yi.Abp.Web/Program.cs b/Yi.Abp.Net8/src/Yi.Abp.Web/Program.cs index 1e0d9e1e..fdc67cc4 100644 --- a/Yi.Abp.Net8/src/Yi.Abp.Web/Program.cs +++ b/Yi.Abp.Net8/src/Yi.Abp.Web/Program.cs @@ -15,6 +15,8 @@ Log.Logger = new LoggerConfiguration() .MinimumLevel.Override("Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler", LogEventLevel.Warning) .MinimumLevel.Override("Microsoft.AspNetCore.Cors.Infrastructure.CorsService", LogEventLevel.Warning) .MinimumLevel.Override("Microsoft.AspNetCore.Authorization.DefaultAuthorizationService", LogEventLevel.Warning) + .MinimumLevel.Override("Microsoft.AspNetCore.Routing.EndpointMiddleware", LogEventLevel.Warning) + .MinimumLevel.Override("Hangfire.Server.ServerHeartbeatProcess", LogEventLevel.Warning) .Enrich.FromLogContext() .WriteTo.Async(c => c.File("logs/all/log-.txt", rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: LogEventLevel.Debug,outputTemplate:outputTemplate)) .WriteTo.Async(c => c.File("logs/error/errorlog-.txt", rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: LogEventLevel.Error,outputTemplate:outputTemplate)) diff --git a/Yi.Ai.Vue3/src/pages/chat/api/index.vue b/Yi.Ai.Vue3/src/pages/chat/api/index.vue index 9c38f18a..2e0cf3e9 100644 --- a/Yi.Ai.Vue3/src/pages/chat/api/index.vue +++ b/Yi.Ai.Vue3/src/pages/chat/api/index.vue @@ -148,7 +148,7 @@ async function copyText(text: string) { > -
+
curl {{ fullUrl }} \
   -H "Content-Type: application/json" \
   -H "Authorization: Bearer YOUR_API_KEY" \

From d463053c16afead3271bb34cd953e44cbb17f495 Mon Sep 17 00:00:00 2001
From: ccnetcore 
Date: Thu, 12 Feb 2026 16:00:26 +0800
Subject: [PATCH 2/6] =?UTF-8?q?chore:=20=E8=B0=83=E6=95=B4=20Hangfire=20?=
 =?UTF-8?q?=E7=9B=B8=E5=85=B3=E6=97=A5=E5=BF=97=E7=BA=A7=E5=88=AB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

降低 Hangfire.Redis.StackExchange 和 Hangfire.Processing 相关组件的日志输出级别为 Warning,减少无关日志噪音,提升日志可读性。
---
 Yi.Abp.Net8/src/Yi.Abp.Web/Program.cs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Yi.Abp.Net8/src/Yi.Abp.Web/Program.cs b/Yi.Abp.Net8/src/Yi.Abp.Web/Program.cs
index fdc67cc4..768a61b9 100644
--- a/Yi.Abp.Net8/src/Yi.Abp.Web/Program.cs
+++ b/Yi.Abp.Net8/src/Yi.Abp.Web/Program.cs
@@ -17,6 +17,8 @@ Log.Logger = new LoggerConfiguration()
     .MinimumLevel.Override("Microsoft.AspNetCore.Authorization.DefaultAuthorizationService", LogEventLevel.Warning)
     .MinimumLevel.Override("Microsoft.AspNetCore.Routing.EndpointMiddleware", LogEventLevel.Warning)
     .MinimumLevel.Override("Hangfire.Server.ServerHeartbeatProcess", LogEventLevel.Warning)
+    .MinimumLevel.Override("Hangfire.Redis.StackExchange.FetchedJobsWatcher", LogEventLevel.Warning)
+    .MinimumLevel.Override("Hangfire.Processing.BackgroundExecution", LogEventLevel.Warning)
     .Enrich.FromLogContext()
     .WriteTo.Async(c => c.File("logs/all/log-.txt", rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: LogEventLevel.Debug,outputTemplate:outputTemplate))
     .WriteTo.Async(c => c.File("logs/error/errorlog-.txt", rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: LogEventLevel.Error,outputTemplate:outputTemplate))

From d4d89b989c64ea22fe2d45861702f8d7e4008ec7 Mon Sep 17 00:00:00 2001
From: ccnetcore 
Date: Thu, 12 Feb 2026 17:36:31 +0800
Subject: [PATCH 3/6] =?UTF-8?q?feat:=20Token=20=E6=94=AF=E6=8C=81=E8=AF=B7?=
 =?UTF-8?q?=E6=B1=82=E6=97=A5=E5=BF=97=E5=BC=80=E5=85=B3=E5=B9=B6=E8=AE=B0?=
 =?UTF-8?q?=E5=BD=95=20OpenAPI=20=E8=AF=B7=E6=B1=82=E6=97=A5=E5=BF=97?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

新增 Token 的 IsEnableLog 字段,贯穿领域、应用与 DTO;在 OpenApiService 中根据 Token 配置异步记录请求日志,包含请求体、模型与接口类型,用于后续审计与分析。
---
 .../Dtos/Token/TokenGetListOutputDto.cs       |  5 ++
 .../Services/Chat/TokenService.cs             |  2 +
 .../Services/OpenApiService.cs                | 52 ++++++++++++++++++-
 .../OpenApi/MessageLogAggregateRoot.cs        | 49 +++++++++++++++++
 .../Entities/OpenApi/TokenAggregateRoot.cs    |  5 ++
 .../Managers/MessageLogManager.cs             | 34 ++++++++++++
 .../Managers/TokenManager.cs                  | 14 ++++-
 Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs  |  2 +-
 8 files changed, 160 insertions(+), 3 deletions(-)
 create mode 100644 Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/OpenApi/MessageLogAggregateRoot.cs
 create mode 100644 Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/MessageLogManager.cs

diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/Token/TokenGetListOutputDto.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/Token/TokenGetListOutputDto.cs
index 6358985b..bc694245 100644
--- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/Token/TokenGetListOutputDto.cs
+++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/Token/TokenGetListOutputDto.cs
@@ -40,6 +40,11 @@ public class TokenGetListOutputDto
     /// 
     public bool IsDisabled { get; set; }
 
+    /// 
+    /// 是否启用请求日志记录
+    /// 
+    public bool IsEnableLog { get; set; }
+
     /// 
     /// 创建时间
     /// 
diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/Chat/TokenService.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/Chat/TokenService.cs
index 204fda55..26aec796 100644
--- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/Chat/TokenService.cs
+++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/Chat/TokenService.cs
@@ -83,6 +83,7 @@ public class TokenService : ApplicationService
                 PremiumQuotaLimit = t.PremiumQuotaLimit,
                 PremiumUsedQuota = usedQuota,
                 IsDisabled = t.IsDisabled,
+                IsEnableLog = t.IsEnableLog,
                 CreationTime = t.CreationTime
             };
         }).ToList();
@@ -158,6 +159,7 @@ public class TokenService : ApplicationService
             PremiumQuotaLimit = token.PremiumQuotaLimit,
             PremiumUsedQuota = 0,
             IsDisabled = token.IsDisabled,
+            IsEnableLog = token.IsEnableLog,
             CreationTime = token.CreationTime
         };
     }
diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/OpenApiService.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/OpenApiService.cs
index 5e4b0cf9..92a06773 100644
--- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/OpenApiService.cs
+++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/OpenApiService.cs
@@ -1,12 +1,15 @@
 using System.Text.Json;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
 using Volo.Abp.Application.Services;
+using Volo.Abp.Uow;
 using Volo.Abp.Users;
 using Yi.Framework.AiHub.Domain.Entities;
 using Yi.Framework.AiHub.Domain.Entities.Chat;
 using Yi.Framework.AiHub.Domain.Entities.Model;
+using Yi.Framework.AiHub.Domain.Entities.OpenApi;
 using Yi.Framework.AiHub.Domain.Extensions;
 using Yi.Framework.AiHub.Domain.Managers;
 using Yi.Framework.AiHub.Domain.Shared.Consts;
@@ -33,10 +36,12 @@ public class OpenApiService : ApplicationService
     private readonly PremiumPackageManager _premiumPackageManager;
     private readonly ISqlSugarRepository _imageStoreRepository;
     private readonly ISqlSugarRepository _aiModelRepository;
+    private readonly IServiceScopeFactory _serviceScopeFactory;
     public OpenApiService(IHttpContextAccessor httpContextAccessor, ILogger logger,
         TokenManager tokenManager, AiGateWayManager aiGateWayManager,
         ModelManager modelManager, AiBlacklistManager aiBlacklistManager,
-        IAccountService accountService, PremiumPackageManager premiumPackageManager, ISqlSugarRepository imageStoreRepository, ISqlSugarRepository aiModelRepository)
+        IAccountService accountService, PremiumPackageManager premiumPackageManager, ISqlSugarRepository imageStoreRepository, ISqlSugarRepository aiModelRepository,
+        IServiceScopeFactory serviceScopeFactory)
     {
         _httpContextAccessor = httpContextAccessor;
         _logger = logger;
@@ -48,6 +53,7 @@ public class OpenApiService : ApplicationService
         _premiumPackageManager = premiumPackageManager;
         _imageStoreRepository = imageStoreRepository;
         _aiModelRepository = aiModelRepository;
+        _serviceScopeFactory = serviceScopeFactory;
     }
 
     /// 
@@ -91,6 +97,12 @@ public class OpenApiService : ApplicationService
                 null, tokenId,
                 CancellationToken.None);
         }
+
+        // 记录请求日志
+        if (tokenValidation.IsEnableLog)
+        {
+            FireAndForgetMessageLog(JsonSerializer.Serialize(input), tokenValidation.Token, tokenValidation.TokenName, input.Model, ModelApiTypeEnum.Completions);
+        }
     }
 
 
@@ -206,6 +218,12 @@ public class OpenApiService : ApplicationService
                 null, tokenId,
                 CancellationToken.None);
         }
+
+        // 记录请求日志
+        if (tokenValidation.IsEnableLog)
+        {
+            FireAndForgetMessageLog(JsonSerializer.Serialize(input), tokenValidation.Token, tokenValidation.TokenName, input.Model, ModelApiTypeEnum.Messages);
+        }
     }
 
 
@@ -258,6 +276,12 @@ public class OpenApiService : ApplicationService
                 null, tokenId,
                 CancellationToken.None);
         }
+
+        // 记录请求日志
+        if (tokenValidation.IsEnableLog)
+        {
+            FireAndForgetMessageLog(JsonSerializer.Serialize(input), tokenValidation.Token, tokenValidation.TokenName, input.Model, ModelApiTypeEnum.Responses);
+        }
     }
 
 
@@ -318,6 +342,12 @@ public class OpenApiService : ApplicationService
                 null, tokenId,
                 CancellationToken.None);
         }
+
+        // 记录请求日志
+        if (tokenValidation.IsEnableLog)
+        {
+            FireAndForgetMessageLog(input.GetRawText(), tokenValidation.Token, tokenValidation.TokenName, modelId, ModelApiTypeEnum.GenerateContent);
+        }
     }
 
     #region 私有
@@ -357,5 +387,25 @@ public class OpenApiService : ApplicationService
         }
     }
 
+    private void FireAndForgetMessageLog(string requestBody, string apiKey, string apiKeyName, string modelId, ModelApiTypeEnum apiType)
+    {
+        _ = Task.Run(async () =>
+        {
+            try
+            {
+                using var scope = _serviceScopeFactory.CreateScope();
+                var uowManager = scope.ServiceProvider.GetRequiredService();
+                var manager = scope.ServiceProvider.GetRequiredService();
+                using var uow = uowManager.Begin(requiresNew: true);
+                await manager.CreateAsync(requestBody, apiKey, apiKeyName, modelId, apiType);
+                await uow.CompleteAsync();
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError(ex, "记录消息日志失败, 请求体长度: {RequestBodyLength}", requestBody?.Length ?? 0);
+            }
+        });
+    }
+
     #endregion
 }
\ No newline at end of file
diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/OpenApi/MessageLogAggregateRoot.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/OpenApi/MessageLogAggregateRoot.cs
new file mode 100644
index 00000000..038e6316
--- /dev/null
+++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/OpenApi/MessageLogAggregateRoot.cs
@@ -0,0 +1,49 @@
+using SqlSugar;
+using Volo.Abp.Domain.Entities;
+using Yi.Framework.AiHub.Domain.Shared.Enums;
+
+namespace Yi.Framework.AiHub.Domain.Entities.OpenApi;
+
+[SugarTable("Ai_Message_Log")]
+public class MessageLogAggregateRoot : Entity
+{
+    /// 
+    /// 请求内容(httpbody)
+    /// 
+    [SugarColumn(ColumnDataType = "text")]
+    public string? RequestBody { get; set; }
+
+    /// 
+    /// 请求apikey
+    /// 
+    [SugarColumn(Length = 255)]
+    public string ApiKey { get; set; }
+
+    /// 
+    /// 请求apikey名称
+    /// 
+    [SugarColumn(Length = 255)]
+    public string ApiKeyName { get; set; }
+
+    /// 
+    /// 创建时间
+    /// 
+    public DateTime CreationTime { get; set; }
+
+    /// 
+    /// 模型id
+    /// 
+    [SugarColumn(Length = 64)]
+    public string ModelId { get; set; }
+
+    /// 
+    /// api类型
+    /// 
+    public ModelApiTypeEnum ApiType { get; set; }
+
+    /// 
+    /// api类型名称
+    /// 
+    [SugarColumn(Length = 16)]
+    public string ApiTypeName { get; set; }
+}
diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/OpenApi/TokenAggregateRoot.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/OpenApi/TokenAggregateRoot.cs
index d5217ca9..6fbe3656 100644
--- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/OpenApi/TokenAggregateRoot.cs
+++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/OpenApi/TokenAggregateRoot.cs
@@ -51,6 +51,11 @@ public class TokenAggregateRoot : FullAuditedAggregateRoot
     /// 
     public bool IsDisabled { get; set; }
 
+    /// 
+    /// 是否启用请求日志记录(仅数据库手动修改)
+    /// 
+    public bool IsEnableLog { get; set; }
+
     /// 
     /// 检查Token是否可用
     /// 
diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/MessageLogManager.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/MessageLogManager.cs
new file mode 100644
index 00000000..4737be73
--- /dev/null
+++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/MessageLogManager.cs
@@ -0,0 +1,34 @@
+using Volo.Abp.Domain.Services;
+using Yi.Framework.AiHub.Domain.Entities.OpenApi;
+using Yi.Framework.AiHub.Domain.Shared.Enums;
+using Yi.Framework.SqlSugarCore.Abstractions;
+
+namespace Yi.Framework.AiHub.Domain.Managers;
+
+public class MessageLogManager : DomainService
+{
+    private readonly ISqlSugarRepository _repository;
+
+    public MessageLogManager(ISqlSugarRepository repository)
+    {
+        _repository = repository;
+    }
+
+    /// 
+    /// 创建消息日志
+    /// 
+    public async Task CreateAsync(string requestBody, string apiKey, string apiKeyName, string modelId, ModelApiTypeEnum apiType)
+    {
+        var entity = new MessageLogAggregateRoot
+        {
+            RequestBody = requestBody,
+            ApiKey = apiKey,
+            ApiKeyName = apiKeyName,
+            ModelId = modelId,
+            ApiType = apiType,
+            ApiTypeName = apiType.ToString(),
+            CreationTime = DateTime.Now
+        };
+        await _repository.InsertAsync(entity);
+    }
+}
diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/TokenManager.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/TokenManager.cs
index 9dc1fad9..0145f671 100644
--- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/TokenManager.cs
+++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/TokenManager.cs
@@ -27,6 +27,16 @@ public class TokenValidationResult
     /// token
     /// 
     public string Token { get; set; }
+
+    /// 
+    /// Token名称
+    /// 
+    public string TokenName { get; set; }
+
+    /// 
+    /// 是否启用请求日志记录
+    /// 
+    public bool IsEnableLog { get; set; }
 }
 
 public class TokenManager : DomainService
@@ -117,7 +127,9 @@ public class TokenManager : DomainService
         {
             UserId = entity.UserId,
             TokenId = entity.Id,
-            Token = entity.Token
+            Token = entity.Token,
+            TokenName = entity.Name,
+            IsEnableLog = entity.IsEnableLog
         };
     }
 
diff --git a/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs b/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs
index afaa6969..e9f4e792 100644
--- a/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs
+++ b/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs
@@ -361,7 +361,7 @@ namespace Yi.Abp.Web
             var app = context.GetApplicationBuilder();
             app.UseRouting();
 
-            // app.ApplicationServices.GetRequiredService().SqlSugarClient.CodeFirst.InitTables();
+            //app.ApplicationServices.GetRequiredService().SqlSugarClient.CodeFirst.InitTables();
             // app.ApplicationServices.GetRequiredService().SqlSugarClient.CodeFirst.InitTables();
             // app.ApplicationServices.GetRequiredService().SqlSugarClient.CodeFirst.InitTables();
 

From 4ab4d7b6dbd8f530909d85d2301dae09fb257faf Mon Sep 17 00:00:00 2001
From: ccnetcore 
Date: Thu, 12 Feb 2026 18:09:45 +0800
Subject: [PATCH 4/6] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dmarkdown=E6=B8=B2?=
 =?UTF-8?q?=E6=9F=93=E8=84=9A=E6=9C=AC=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 Yi.Ai.Vue3/.claude/settings.local.json        |  4 +-
 .../src/components/MarkedMarkdown/index.vue   | 31 ++++++++++---
 .../components/TokenFormDialog.vue            | 45 ++++++++++++++++++-
 3 files changed, 71 insertions(+), 9 deletions(-)

diff --git a/Yi.Ai.Vue3/.claude/settings.local.json b/Yi.Ai.Vue3/.claude/settings.local.json
index 89b03152..842aaa71 100644
--- a/Yi.Ai.Vue3/.claude/settings.local.json
+++ b/Yi.Ai.Vue3/.claude/settings.local.json
@@ -10,7 +10,9 @@
       "Bash(npm install marked --save)",
       "Bash(pnpm add marked)",
       "Bash(pnpm lint:*)",
-      "Bash(pnpm list:*)"
+      "Bash(pnpm list:*)",
+      "Bash(pnpm vue-tsc:*)",
+      "Bash(pnpm build:*)"
     ],
     "deny": [],
     "ask": []
diff --git a/Yi.Ai.Vue3/src/components/MarkedMarkdown/index.vue b/Yi.Ai.Vue3/src/components/MarkedMarkdown/index.vue
index 6609df93..f0954924 100644
--- a/Yi.Ai.Vue3/src/components/MarkedMarkdown/index.vue
+++ b/Yi.Ai.Vue3/src/components/MarkedMarkdown/index.vue
@@ -10,11 +10,13 @@ import { useDesignStore } from '@/stores';
 interface Props {
   content: string;
   theme?: 'light' | 'dark' | 'auto';
+  sanitize?: boolean;
 }
 
 const props = withDefaults(defineProps(), {
   content: '',
   theme: 'auto',
+  sanitize: true,
 });
 
 const designStore = useDesignStore();
@@ -94,7 +96,12 @@ const renderer = {
 
   // 行内代码
   codespan(token: { text: string }) {
-    return `${token.text}`;
+    // 转义 HTML 标签,防止