feat: 新增功能
- 移除 OpenApiService.GenerateContentAsync 的 isAsync 查询参数及其分支处理(不再在该接口直接创建并返回 ImageStore 任务 Id)。 - 保留 alt=sse 的代理处理逻辑。 - 在 ImageStoreTaskAggregateRoot 中新增字段: - Prompt:提示词(大文本) - ReferenceImageUrls:参考图 URL 列表(JSON 存储) - 兼容性提示:接口去掉了 isAsync 参数,调用方需相应调整异步任务创建流程。
This commit is contained in:
129
Yi.Abp.Net8/CLAUDE.md
Normal file
129
Yi.Abp.Net8/CLAUDE.md
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Yi.Abp.Net8 is a modular, multi-tenant SaaS platform built on ABP Framework 8.3.4 with .NET 8.0. It uses **SqlSugar** (not EF Core) as the ORM and follows Domain-Driven Design (DDD) principles. The platform includes AI/ML features (chat, models, agents, token tracking), RBAC, forum, messaging, and digital collectibles modules.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Solution Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
Yi.Abp.Net8/
|
||||||
|
├── src/ # Main application host
|
||||||
|
│ └── Yi.Abp.Web/ # ASP.NET Core 8.0 Web Host (port 19001)
|
||||||
|
├── framework/ # Framework layer (shared infrastructure)
|
||||||
|
│ ├── Yi.Framework.Core # Core utilities, JSON handling
|
||||||
|
│ ├── Yi.Framework.SqlSugarCore # SqlSugar ORM abstraction (v5.1.4.197-preview22)
|
||||||
|
│ ├── Yi.Framework.SqlSugarCore.Abstractions # Repository interfaces
|
||||||
|
│ ├── Yi.Framework.AspNetCore # ASP.NET Core extensions
|
||||||
|
│ ├── Yi.Framework.AspNetCore.Authentication.OAuth # QQ, Gitee OAuth
|
||||||
|
│ ├── Yi.Framework.Ddd.Application # DDD application base classes
|
||||||
|
│ ├── Yi.Framework.BackgroundWorkers.Hangfire # Job scheduling
|
||||||
|
│ ├── Yi.Framework.Caching.FreeRedis # Redis caching
|
||||||
|
│ └── Yi.Framework.SemanticKernel # AI/ML integration
|
||||||
|
├── module/ # Business modules (each follows 5-layer DDD pattern)
|
||||||
|
│ ├── ai-hub/ # AI services (chat, models, sessions, agents)
|
||||||
|
│ ├── rbac/ # Role-Based Access Control (core auth/authz)
|
||||||
|
│ ├── bbs/ # Forum/community
|
||||||
|
│ ├── chat-hub/ # Real-time messaging
|
||||||
|
│ ├── audit-logging/ # Audit trail tracking
|
||||||
|
│ ├── code-gen/ # Code generation
|
||||||
|
│ ├── tenant-management/ # Multi-tenancy support
|
||||||
|
│ ├── digital-collectibles/ # NFT/digital assets
|
||||||
|
│ └── ai-stock/ # AI-powered stock analysis
|
||||||
|
├── test/ # Unit tests (xUnit + NSubstitute + Shouldly)
|
||||||
|
├── client/ # HTTP API clients
|
||||||
|
└── tool/ # Development utilities
|
||||||
|
```
|
||||||
|
|
||||||
|
### Module Structure (DDD Layers)
|
||||||
|
|
||||||
|
Each module follows this pattern:
|
||||||
|
|
||||||
|
```
|
||||||
|
module/[feature]/
|
||||||
|
├── [Feature].Domain.Shared/ # Constants, enums, shared DTOs
|
||||||
|
├── [Feature].Domain/ # Entities, aggregates, domain services
|
||||||
|
├── [Feature].Application.Contracts/ # Service interfaces, DTOs
|
||||||
|
├── [Feature].Application/ # Application services (implementations)
|
||||||
|
└── [Feature].SqlSugarCore/ # Repository implementations, DbContext
|
||||||
|
```
|
||||||
|
|
||||||
|
**Dependency Flow:** Application → Domain + Application.Contracts → Domain.Shared → Framework
|
||||||
|
|
||||||
|
### Module Registration
|
||||||
|
|
||||||
|
All modules are registered in `src/Yi.Abp.Web/YiAbpWebModule.cs`. When adding a new module:
|
||||||
|
|
||||||
|
1. Add `DependsOn` attribute in `YiAbpWebModule`
|
||||||
|
2. Add conventional controller in `PreConfigureServices`:
|
||||||
|
```csharp
|
||||||
|
options.ConventionalControllers.Create(typeof(YiFramework[Feature]ApplicationModule).Assembly,
|
||||||
|
option => option.RemoteServiceName = "[service-name]");
|
||||||
|
```
|
||||||
|
|
||||||
|
### API Routing
|
||||||
|
|
||||||
|
All API routes use the unified prefix: `/api/app/{service-name}/{controller}/{action}`
|
||||||
|
|
||||||
|
Registered service names:
|
||||||
|
- `default` - Main application services
|
||||||
|
- `rbac` - Authentication, authorization, user/role management
|
||||||
|
- `ai-hub` - AI chat, models, sessions, agents
|
||||||
|
- `bbs` - Forum posts and comments
|
||||||
|
- `chat-hub` - Real-time messaging
|
||||||
|
- `tenant-management` - Multi-tenant configuration
|
||||||
|
- `code-gen` - Code generation utilities
|
||||||
|
- `digital-collectibles` - NFT/digital assets
|
||||||
|
- `ai-stock` - Stock analysis
|
||||||
|
|
||||||
|
## Database
|
||||||
|
|
||||||
|
**ORM:** SqlSugar (NOT Entity Framework Core)
|
||||||
|
|
||||||
|
**Configuration** (`appsettings.json`):
|
||||||
|
```json
|
||||||
|
"DbConnOptions": {
|
||||||
|
"Url": "DataSource=yi-abp-dev.db",
|
||||||
|
"DbType": "Sqlite", // Sqlite, Mysql, Sqlserver, Oracle, PostgreSQL
|
||||||
|
"EnabledCodeFirst": true, // Auto-create tables
|
||||||
|
"EnabledDbSeed": true, // Auto-seed data
|
||||||
|
"EnabledSaasMultiTenancy": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Multi-tenancy:** Tenant isolation via `HeaderTenantResolveContributor` (NOT cookie-based). Tenant is resolved from `__tenant` header.
|
||||||
|
|
||||||
|
## Key Technologies
|
||||||
|
|
||||||
|
| Component | Technology |
|
||||||
|
|-----------|-----------|
|
||||||
|
| Framework | ABP 8.3.4 |
|
||||||
|
| .NET Version | .NET 8.0 |
|
||||||
|
| ORM | SqlSugar 5.1.4.197-preview22 |
|
||||||
|
| Authentication | JWT Bearer + Refresh Tokens |
|
||||||
|
| OAuth | QQ, Gitee |
|
||||||
|
| Caching | FreeRedis (optional) |
|
||||||
|
| Background Jobs | Hangfire (in-memory or Redis) |
|
||||||
|
| Logging | Serilog (daily rolling files) |
|
||||||
|
| Testing | xUnit + NSubstitute + Shouldly |
|
||||||
|
| Container | Autofac |
|
||||||
|
|
||||||
|
## Important Notes
|
||||||
|
|
||||||
|
- **JSON Serialization:** Uses Microsoft's `System.Text.Json`, NOT Newtonsoft.Json. Date format handled via `DatetimeJsonConverter`.
|
||||||
|
- **Multi-tenancy:** Tenant resolved from `__tenant` header, NOT cookies.
|
||||||
|
- **Rate Limiting:** Disabled in development, enabled in production (1000 req/60s sliding window).
|
||||||
|
- **Swagger:** Available at `/swagger` in development.
|
||||||
|
- **Hangfire Dashboard:** Available at `/hangfire` (requires JWT authorization).
|
||||||
|
- **Background Workers:** Disabled in development (`AbpBackgroundWorkerOptions.IsEnabled = false`).
|
||||||
|
|
||||||
|
## Development Workflow
|
||||||
|
|
||||||
|
1. **Branch:** Main branch is `abp`, current development branch is `ai-hub`.
|
||||||
|
2. **Commit Convention:** Chinese descriptive messages with prefixes (`feat:`, `fix:`, `style:`).
|
||||||
|
3. **Testing:** Run `dotnet test` before committing.
|
||||||
|
4. **Building:** Use `dotnet build --no-restore` for faster builds after initial restore.
|
||||||
@@ -261,13 +261,11 @@ public class OpenApiService : ApplicationService
|
|||||||
/// 生成-Gemini (尊享服务专用)
|
/// 生成-Gemini (尊享服务专用)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input"></param>
|
/// <param name="input"></param>
|
||||||
/// <param name="isAsync"></param>
|
|
||||||
/// <param name="modelId"></param>
|
/// <param name="modelId"></param>
|
||||||
/// <param name="alt"></param>
|
/// <param name="alt"></param>
|
||||||
/// <param name="cancellationToken"></param>
|
/// <param name="cancellationToken"></param>
|
||||||
[HttpPost("openApi/v1beta/models/{modelId}:{action:regex(^(generateContent|streamGenerateContent)$)}")]
|
[HttpPost("openApi/v1beta/models/{modelId}:{action:regex(^(generateContent|streamGenerateContent)$)}")]
|
||||||
public async Task GenerateContentAsync([FromBody] JsonElement input,
|
public async Task GenerateContentAsync([FromBody] JsonElement input,
|
||||||
[FromQuery] bool isAsync,
|
|
||||||
[FromRoute] string modelId,
|
[FromRoute] string modelId,
|
||||||
[FromQuery] string? alt, CancellationToken cancellationToken)
|
[FromQuery] string? alt, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
@@ -298,18 +296,7 @@ public class OpenApiService : ApplicationService
|
|||||||
throw new UserFriendlyException("尊享token包用量不足,请先购买尊享token包");
|
throw new UserFriendlyException("尊享token包用量不足,请先购买尊享token包");
|
||||||
}
|
}
|
||||||
|
|
||||||
//如果异步,直接走job处理进行存储
|
|
||||||
if (isAsync)
|
|
||||||
{
|
|
||||||
var task = new ImageStoreTaskAggregateRoot();
|
|
||||||
await _imageStoreRepository.InsertAsync(task);
|
|
||||||
await _httpContextAccessor.HttpContext.Response.WriteAsJsonAsync(new
|
|
||||||
{
|
|
||||||
Id = task.Id
|
|
||||||
}, cancellationToken);
|
|
||||||
//todo 发送job,参数怎么办?需要先全存下来吗?全存下来,就要解析全部提示词 和 附件内容了
|
|
||||||
|
|
||||||
}
|
|
||||||
//ai网关代理httpcontext
|
//ai网关代理httpcontext
|
||||||
if (alt == "sse")
|
if (alt == "sse")
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,6 +7,18 @@ namespace Yi.Framework.AiHub.Domain.Entities.Chat;
|
|||||||
[SugarTable("Ai_ImageStoreTask")]
|
[SugarTable("Ai_ImageStoreTask")]
|
||||||
public class ImageStoreTaskAggregateRoot : FullAuditedAggregateRoot<Guid>
|
public class ImageStoreTaskAggregateRoot : FullAuditedAggregateRoot<Guid>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 提示词
|
||||||
|
/// </summary>
|
||||||
|
[SugarColumn(ColumnDataType = StaticConfig.CodeFirst_BigString)]
|
||||||
|
public string Prompt { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 参考图Url
|
||||||
|
/// </summary>
|
||||||
|
[SugarColumn(IsJson = true)]
|
||||||
|
public List<string> ReferenceImageUrls { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 图片绝对路径
|
/// 图片绝对路径
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user