chore: 全面规范化代码,遵循 CLAUDE.md 编码规范
- C# 文件命名改为 snake_case(28 个文件重命名) - C# 类转换为主构造函数(8 个类) - 空 catch 添加异常类型(2 处) - 新建 GlobalUsings.cs(Health.Infrastructure、Health.WebApi) - Flutter 移除 go_router,改用 Riverpod 路由栈 - Flutter 移除 flutter_secure_storage,改用 sqflite 持久化 - 修复 Flutter 构建路径(Flutter SDK 迁至 D 盘) - 后端端口改为 0.0.0.0:5000,支持局域网访问
This commit is contained in:
@@ -1,29 +1,20 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Health.Infrastructure.AI;
|
||||
|
||||
/// <summary>
|
||||
/// DeepSeek LLM 客户端(对话 + Tool Calling)
|
||||
/// </summary>
|
||||
public sealed class DeepSeekClient
|
||||
public sealed class DeepSeekClient(HttpClient http, IConfiguration config)
|
||||
{
|
||||
private readonly HttpClient _http;
|
||||
private readonly string _model;
|
||||
private readonly JsonSerializerOptions _jsonOptions;
|
||||
|
||||
public DeepSeekClient(HttpClient http, IConfiguration config)
|
||||
private readonly HttpClient _http = http;
|
||||
private readonly string _model = config["DEEPSEEK_MODEL"] ?? "deepseek-chat";
|
||||
private readonly JsonSerializerOptions _jsonOptions = new()
|
||||
{
|
||||
_http = http;
|
||||
_model = config["DEEPSEEK_MODEL"] ?? "deepseek-chat";
|
||||
_jsonOptions = new()
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
|
||||
PropertyNameCaseInsensitive = true
|
||||
};
|
||||
}
|
||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
|
||||
PropertyNameCaseInsensitive = true
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 流式 Chat Completions
|
||||
@@ -96,22 +87,15 @@ public sealed class DeepSeekClient
|
||||
/// <summary>
|
||||
/// 千问 VL 视觉客户端(食物识别 + 报告解读)
|
||||
/// </summary>
|
||||
public sealed class QwenVisionClient
|
||||
public sealed class QwenVisionClient(HttpClient http, IConfiguration config)
|
||||
{
|
||||
private readonly HttpClient _http;
|
||||
private readonly string _model;
|
||||
private readonly JsonSerializerOptions _jsonOptions;
|
||||
|
||||
public QwenVisionClient(HttpClient http, IConfiguration config)
|
||||
private readonly HttpClient _http = http;
|
||||
private readonly string _model = config["QWEN_VISION_MODEL"] ?? "qwen-vl-max";
|
||||
private readonly JsonSerializerOptions _jsonOptions = new()
|
||||
{
|
||||
_http = http;
|
||||
_model = config["QWEN_VISION_MODEL"] ?? "qwen-vl-max";
|
||||
_jsonOptions = new()
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
|
||||
PropertyNameCaseInsensitive = true
|
||||
};
|
||||
}
|
||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
|
||||
PropertyNameCaseInsensitive = true
|
||||
};
|
||||
|
||||
public async Task<ChatCompletionResponse> VisionAsync(
|
||||
string systemPrompt,
|
||||
@@ -1,33 +1,30 @@
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Health.Infrastructure.AI;
|
||||
|
||||
/// <summary>
|
||||
/// OpenAI 兼容协议 HTTP 客户端,统一调用 DeepSeek / 千问 VL
|
||||
/// </summary>
|
||||
public sealed class OpenAiCompatibleClient
|
||||
public sealed class OpenAiCompatibleClient(string baseUrl, string apiKey, string model)
|
||||
{
|
||||
private readonly HttpClient _http;
|
||||
private readonly string _model;
|
||||
private readonly JsonSerializerOptions _jsonOptions;
|
||||
|
||||
public OpenAiCompatibleClient(string baseUrl, string apiKey, string model)
|
||||
private readonly HttpClient _http = CreateHttpClient(baseUrl, apiKey);
|
||||
private readonly string _model = model;
|
||||
private readonly JsonSerializerOptions _jsonOptions = new()
|
||||
{
|
||||
_http = new HttpClient
|
||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
|
||||
PropertyNameCaseInsensitive = true
|
||||
};
|
||||
|
||||
private static HttpClient CreateHttpClient(string baseUrl, string apiKey)
|
||||
{
|
||||
var client = new HttpClient
|
||||
{
|
||||
BaseAddress = new Uri(baseUrl.TrimEnd('/') + "/"),
|
||||
Timeout = TimeSpan.FromSeconds(60)
|
||||
};
|
||||
_http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
|
||||
_http.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
_model = model;
|
||||
_jsonOptions = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
|
||||
PropertyNameCaseInsensitive = true
|
||||
};
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
|
||||
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1,5 +1,3 @@
|
||||
using Health.Domain.Enums;
|
||||
|
||||
namespace Health.Infrastructure.AI;
|
||||
|
||||
/// <summary>
|
||||
@@ -1,4 +1,3 @@
|
||||
using Health.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
@@ -7,9 +6,8 @@ namespace Health.Infrastructure.Data;
|
||||
/// <summary>
|
||||
/// 应用程序数据库上下文
|
||||
/// </summary>
|
||||
public sealed class AppDbContext : DbContext
|
||||
public sealed class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options)
|
||||
{
|
||||
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
|
||||
|
||||
// 核心业务表
|
||||
public DbSet<User> Users => Set<User>();
|
||||
@@ -1,5 +1,3 @@
|
||||
using Health.Domain.Entities;
|
||||
|
||||
namespace Health.Infrastructure.Data;
|
||||
|
||||
/// <summary>
|
||||
@@ -1,5 +1,3 @@
|
||||
using Health.Domain.Entities;
|
||||
using Health.Domain.Enums;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Health.Infrastructure.Data;
|
||||
4
backend/src/Health.Infrastructure/GlobalUsings.cs
Normal file
4
backend/src/Health.Infrastructure/GlobalUsings.cs
Normal file
@@ -0,0 +1,4 @@
|
||||
global using Health.Domain.Entities;
|
||||
global using Health.Domain.Enums;
|
||||
global using System.Text;
|
||||
global using System.Text.Json;
|
||||
@@ -3,25 +3,17 @@ using Microsoft.IdentityModel.Tokens;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace Health.Infrastructure.Services;
|
||||
|
||||
/// <summary>
|
||||
/// JWT Token 生成与验证服务
|
||||
/// </summary>
|
||||
public sealed class JwtProvider
|
||||
public sealed class JwtProvider(IConfiguration configuration)
|
||||
{
|
||||
private readonly string _secret;
|
||||
private readonly string _issuer;
|
||||
private readonly string _audience;
|
||||
|
||||
public JwtProvider(IConfiguration configuration)
|
||||
{
|
||||
_secret = configuration["JWT_SECRET"] ?? "dev-secret-key-change-in-production-min-32-chars!!";
|
||||
_issuer = configuration["JWT_ISSUER"] ?? "health-manager";
|
||||
_audience = configuration["JWT_AUDIENCE"] ?? "health-manager-app";
|
||||
}
|
||||
private readonly string _secret = configuration["JWT_SECRET"] ?? "dev-secret-key-change-in-production-min-32-chars!!";
|
||||
private readonly string _issuer = configuration["JWT_ISSUER"] ?? "health-manager";
|
||||
private readonly string _audience = configuration["JWT_AUDIENCE"] ?? "health-manager-app";
|
||||
|
||||
/// <summary>
|
||||
/// 生成 access_token(30 分钟有效)
|
||||
Reference in New Issue
Block a user