From ba95d1798f376bbbae54aff2be700cc22dc3fab7 Mon Sep 17 00:00:00 2001 From: ccnetcore Date: Fri, 2 Jan 2026 21:32:48 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96AI=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E5=AD=98=E5=82=A8=E4=B8=8E=E8=AE=BF=E9=97=AE=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 统一图片存储服务地址常量,返回完整可访问URL - 图片上传接口支持匿名访问,并按日期创建存储目录 - ImageStoreTask 移除无用生成图片 Base64 字段,调整大字段存储配置 - 创建图片任务时补充 ModelId 信息 - 优先使用 Authorization 头部,避免覆盖已有认证信息 - 前端补充 Element Plus Descriptions 组件类型声明 --- .../Services/Chat/AiImageService.cs | 23 ++++++++++++++----- .../Chat/ImageStoreTaskAggregateRoot.cs | 9 ++------ .../Managers/AiGateWayManager.cs | 8 +++---- Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs | 9 ++++---- Yi.Ai.Vue3/types/components.d.ts | 2 ++ 5 files changed, 29 insertions(+), 22 deletions(-) diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/Chat/AiImageService.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/Chat/AiImageService.cs index 8f1325fa..2be038a6 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/Chat/AiImageService.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/Chat/AiImageService.cs @@ -98,7 +98,8 @@ public class AiImageService : ApplicationService ReferenceImagesUrl = new List(), TaskStatus = TaskStatusEnum.Processing, UserId = userId, - TokenId = input.TokenId + TokenId = input.TokenId, + ModelId = input.ModelId }; await _imageTaskRepository.InsertAsync(task); @@ -146,6 +147,7 @@ public class AiImageService : ApplicationService /// Base64图片数据(包含前缀如 data:image/png;base64,) /// 图片访问URL [HttpPost("ai-image/upload-base64")] + [AllowAnonymous] public async Task UploadBase64ToUrlAsync([FromBody] string base64Data) { if (string.IsNullOrWhiteSpace(base64Data)) @@ -194,22 +196,31 @@ public class AiImageService : ApplicationService throw new UserFriendlyException("Base64格式无效"); } - // 创建存储目录 - var uploadPath = Path.Combine(_webHostEnvironment.ContentRootPath, "wwwroot", "ai-images"); + // ============================== + // ✅ 按日期创建目录(yyyyMMdd) + // ============================== + var dateFolder = DateTime.Now.ToString("yyyyMMdd"); + var uploadPath = Path.Combine( + _webHostEnvironment.ContentRootPath, + "wwwroot", + "ai-images", + dateFolder + ); + if (!Directory.Exists(uploadPath)) { Directory.CreateDirectory(uploadPath); } - // 生成文件名并保存 + // 保存文件 var fileId = _guidGenerator.Create(); var fileName = $"{fileId}{extension}"; var filePath = Path.Combine(uploadPath, fileName); await File.WriteAllBytesAsync(filePath, imageBytes); - // 返回访问URL - return $"/ai-images/{fileName}"; + // 返回包含日期目录的访问URL + return $"/wwwroot/ai-images/{dateFolder}/{fileName}"; } /// diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/Chat/ImageStoreTaskAggregateRoot.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/Chat/ImageStoreTaskAggregateRoot.cs index 379333cd..37fe666b 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/Chat/ImageStoreTaskAggregateRoot.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Entities/Chat/ImageStoreTaskAggregateRoot.cs @@ -16,20 +16,15 @@ public class ImageStoreTaskAggregateRoot : FullAuditedAggregateRoot /// /// 参考图PrefixBase64(带前缀,如 data:image/png;base64,xxx) /// - [SugarColumn(IsJson = true)] + [SugarColumn(IsJson = true,ColumnDataType = StaticConfig.CodeFirst_BigString)] public List ReferenceImagesPrefixBase64 { get; set; } - + /// /// 参考图url /// [SugarColumn(IsJson = true)] public List ReferenceImagesUrl { get; set; } - - /// - /// 生成图片PrefixBase64(带前缀,如 data:image/png;base64,xxx) - /// - public string? StorePrefixBase64 { get; set; } /// /// 图片绝对路径 diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/AiGateWayManager.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/AiGateWayManager.cs index 497fcc3b..3ea535d8 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/AiGateWayManager.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/AiGateWayManager.cs @@ -976,7 +976,7 @@ public class AiGateWayManager : DomainService } } - + private const string ImageStoreHost = "http://localhost:19001/api/app"; /// /// Gemini 生成(Image)-非流式-缓存处理 /// 返回图片绝对路径 @@ -1010,12 +1010,11 @@ public class AiGateWayManager : DomainService //远程调用上传接口,将base64转换为URL var httpClient = LazyServiceProvider.LazyGetRequiredService().CreateClient(); // var uploadUrl = $"https://ccnetcore.com/prod-api/ai-hub/ai-image/upload-base64"; - var uploadUrl = $"http://localhost:19001/api/app/ai-image/upload-base64"; + var uploadUrl = $"{ImageStoreHost}/ai-image/upload-base64"; var content = new StringContent(JsonSerializer.Serialize(imageBase64), Encoding.UTF8, "application/json"); var uploadResponse = await httpClient.PostAsync(uploadUrl, content, cancellationToken); uploadResponse.EnsureSuccessStatusCode(); var storeUrl = await uploadResponse.Content.ReadAsStringAsync(cancellationToken); - storeUrl = storeUrl.Trim('"'); // 移除JSON字符串的引号 var tokenUsage = new ThorUsageResponse { @@ -1042,8 +1041,7 @@ public class AiGateWayManager : DomainService } //设置存储base64和url - imageStoreTask.StorePrefixBase64 = imageBase64; - imageStoreTask.SetSuccess(storeUrl); + imageStoreTask.SetSuccess($"{ImageStoreHost}{storeUrl}"); await _imageStoreTaskRepository.UpdateAsync(imageStoreTask); } diff --git a/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs b/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs index cc52d77f..9f21193b 100644 --- a/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs +++ b/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs @@ -113,7 +113,7 @@ namespace Yi.Abp.Web //本地开发环境,可以禁用作业执行 if (host.IsDevelopment()) { - Configure(options => { options.IsEnabled = false; }); + //Configure(options => { options.IsEnabled = false; }); } //请求日志 @@ -298,7 +298,8 @@ namespace Yi.Abp.Web } else { - if (messageContext.Request.Cookies.TryGetValue("Token", out var cookiesToken)) + if (!messageContext.Request.Headers.ContainsKey("Authorization") && + messageContext.Request.Cookies.TryGetValue("Token", out var cookiesToken)) { messageContext.Token = cookiesToken; } @@ -358,8 +359,8 @@ 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(); // app.ApplicationServices.GetRequiredService().SqlSugarClient.CodeFirst.InitTables(); //跨域 diff --git a/Yi.Ai.Vue3/types/components.d.ts b/Yi.Ai.Vue3/types/components.d.ts index 9ef439fb..16d28441 100644 --- a/Yi.Ai.Vue3/types/components.d.ts +++ b/Yi.Ai.Vue3/types/components.d.ts @@ -25,6 +25,8 @@ declare module 'vue' { ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem'] ElContainer: typeof import('element-plus/es')['ElContainer'] ElDatePicker: typeof import('element-plus/es')['ElDatePicker'] + ElDescriptions: typeof import('element-plus/es')['ElDescriptions'] + ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem'] ElDialog: typeof import('element-plus/es')['ElDialog'] ElDivider: typeof import('element-plus/es')['ElDivider'] ElDrawer: typeof import('element-plus/es')['ElDrawer']