重构作业结构:优化实体模型、DTO映射和前端界面
Some checks failed
TechAct / explore-gitea-actions (push) Failing after 13s

- 重构AppMainStruct、AssignmentQuestion、Question等实体模型
- 更新相关DTO以匹配新的数据结构
- 优化前端页面布局和组件
- 添加全局信息和笔记功能相关代码
- 更新数据库迁移和程序配置
This commit is contained in:
SpecialX
2025-09-04 15:43:33 +08:00
parent 730b0ba04b
commit 6a65281850
58 changed files with 5459 additions and 244 deletions

View File

@@ -21,6 +21,7 @@ namespace TechHelper.Context
public DbSet<Submission> Submissions { get; set; }
public DbSet<SubmissionDetail> SubmissionDetails { get; set; }
public DbSet<QuestionContext> QuestionContexts { get; set; }
public DbSet<Global> Globals { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{

View File

@@ -2,6 +2,10 @@
using AutoMapper.Internal.Mappers;
using Entities.Contracts;
using Entities.DTO;
using Newtonsoft.Json;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace TechHelper.Context
{
@@ -23,13 +27,13 @@ namespace TechHelper.Context
public AutoMapperProFile()
{
CreateMap<UserForRegistrationDto, User>()
.ForMember(dest => dest.Id, opt => opt.Ignore())
.ForMember(dest => dest.UserName, opt => opt.MapFrom(src => src.Name))
.ForMember(dest => dest.Id, opt => opt.Ignore())
.ForMember(dest => dest.UserName, opt => opt.MapFrom(src => src.Name))
.ForMember(dest => dest.Email, opt => opt.MapFrom(src => src.Email))
.ForMember(dest => dest.PhoneNumber, opt => opt.MapFrom(src => src.PhoneNumber))
.ForMember(dest => dest.Address, opt => opt.MapFrom(src => src.HomeAddress))
.ForMember(dest => dest.PasswordHash, opt => opt.Ignore())
.ForMember(dest => dest.EmailConfirmed, opt => opt.Ignore());
.ForMember(dest => dest.Address, opt => opt.MapFrom(src => src.HomeAddress))
.ForMember(dest => dest.PasswordHash, opt => opt.Ignore())
.ForMember(dest => dest.EmailConfirmed, opt => opt.Ignore());
CreateMap<ClassDto, Class>()
.ForMember(d => d.Number, o => o.MapFrom(src => src.Class))
@@ -44,7 +48,7 @@ namespace TechHelper.Context
CreateMap<QuestionDto, Question>().ReverseMap();
CreateMap<QuestionContext, QuestionContextDto>().ReverseMap();
CreateMap<QuestionContext, QuestionContextDto>().ReverseMap();
@@ -52,7 +56,13 @@ namespace TechHelper.Context
// Submission
CreateMap<SubmissionDto, Submission>().ReverseMap();
CreateMap<SubmissionDetailDto, SubmissionDetail>().ReverseMap();
CreateMap<SubmissionDetailDto, SubmissionDetail>().ReverseMap();
CreateMap<SubjectTypeMetadataDto, Global>()
.ForMember(dest => dest.Info, opt => opt.MapFrom(src => JsonConvert.SerializeObject(src.Data)));
CreateMap<Global, SubjectTypeMetadataDto>()
.ForMember(dest => dest.Data, opt => opt.MapFrom(src => JsonConvert.DeserializeObject<Dictionary<string, (string Color, string DisplayName)>>(src.Info)));
}
}

View File

@@ -0,0 +1,91 @@
using Entities.DTO;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using TechHelper.Services;
namespace TechHelper.Server.Controllers
{
[Route("api/note")]
[ApiController]
public class NoteController : ControllerBase
{
private readonly INoteService _noteService;
// 通过依赖注入获取 NoteService
public NoteController(INoteService noteService)
{
_noteService = noteService;
}
/// <summary>
/// 获取所有全局数据。
/// GET: api/Note
/// </summary>
[HttpGet]
public async Task<IActionResult> GetAll([FromQuery] QueryParameter query)
{
var response = await _noteService.GetAllAsync(query);
return Ok(response);
}
/// <summary>
/// 根据 ID 获取单个全局数据。
/// GET: api/Note/{id}
/// </summary>
[HttpGet("{id}")]
public async Task<IActionResult> Get(byte id)
{
var response = await _noteService.GetAsync(id);
if (!response.Status)
{
return NotFound(response);
}
return Ok(response);
}
/// <summary>
/// 添加新的全局数据。
/// POST: api/Note
/// </summary>
[HttpPost]
public async Task<IActionResult> Add([FromBody] GlobalDto model)
{
var response = await _noteService.AddAsync(model);
if (!response.Status)
{
return BadRequest(response);
}
return Ok(response);
}
/// <summary>
/// 更新已存在的全局数据。
/// PUT: api/Note
/// </summary>
[HttpPut]
public async Task<IActionResult> Update([FromBody] GlobalDto model)
{
var response = await _noteService.UpdateAsync(model);
if (!response.Status)
{
return NotFound(response);
}
return Ok(response);
}
/// <summary>
/// 根据 ID 删除全局数据。
/// DELETE: api/Note/{id}
/// </summary>
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(byte id)
{
var response = await _noteService.DeleteAsync(id);
if (!response.Status)
{
return NotFound(response);
}
return Ok(response);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,93 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
namespace TechHelper.Server.Migrations
{
/// <inheritdoc />
public partial class question_qt_update : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("0775702a-5db7-4747-94d0-4376fad2b58b"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("37f41430-0cb7-44e5-988b-976200bd602d"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("df89b9a0-65ef-42dd-b2cb-e59997a72e70"));
migrationBuilder.AddColumn<string>(
name: "QType",
table: "questions",
type: "longtext",
nullable: false)
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.AddColumn<byte>(
name: "Type",
table: "assignment_questions",
type: "tinyint unsigned",
nullable: false,
defaultValue: (byte)0);
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("67de6514-79a5-4a9c-b54c-13cac296b0c6"), null, "Teacher", "TEACHER" },
{ new Guid("94f0d8d9-ffba-4e28-b578-8596363d42ae"), null, "Student", "STUDENT" },
{ new Guid("bf46ed67-2dc9-40f8-8717-37dd3572f274"), null, "Administrator", "ADMINISTRATOR" }
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("67de6514-79a5-4a9c-b54c-13cac296b0c6"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("94f0d8d9-ffba-4e28-b578-8596363d42ae"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("bf46ed67-2dc9-40f8-8717-37dd3572f274"));
migrationBuilder.DropColumn(
name: "QType",
table: "questions");
migrationBuilder.DropColumn(
name: "Type",
table: "assignment_questions");
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("0775702a-5db7-4747-94d0-4376fad2b58b"), null, "Teacher", "TEACHER" },
{ new Guid("37f41430-0cb7-44e5-988b-976200bd602d"), null, "Administrator", "ADMINISTRATOR" },
{ new Guid("df89b9a0-65ef-42dd-b2cb-e59997a72e70"), null, "Student", "STUDENT" }
});
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,89 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
namespace TechHelper.Server.Migrations
{
/// <inheritdoc />
public partial class question_qt_update_2 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("67de6514-79a5-4a9c-b54c-13cac296b0c6"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("94f0d8d9-ffba-4e28-b578-8596363d42ae"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("bf46ed67-2dc9-40f8-8717-37dd3572f274"));
migrationBuilder.CreateTable(
name: "global",
columns: table => new
{
id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Area = table.Column<byte>(type: "tinyint unsigned", nullable: false),
Info = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_global", x => x.id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("49854839-b861-4d42-bdbe-96b1a66c25ef"), null, "Teacher", "TEACHER" },
{ new Guid("5c7a7971-2610-4bce-9e41-0caffd5a5558"), null, "Student", "STUDENT" },
{ new Guid("83ff7de8-edc9-47f8-8de8-22f892ca6bb5"), null, "Administrator", "ADMINISTRATOR" }
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "global");
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("49854839-b861-4d42-bdbe-96b1a66c25ef"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("5c7a7971-2610-4bce-9e41-0caffd5a5558"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("83ff7de8-edc9-47f8-8de8-22f892ca6bb5"));
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("67de6514-79a5-4a9c-b54c-13cac296b0c6"), null, "Teacher", "TEACHER" },
{ new Guid("94f0d8d9-ffba-4e28-b578-8596363d42ae"), null, "Student", "STUDENT" },
{ new Guid("bf46ed67-2dc9-40f8-8717-37dd3572f274"), null, "Administrator", "ADMINISTRATOR" }
});
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,82 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
namespace TechHelper.Server.Migrations
{
/// <inheritdoc />
public partial class question_qt_update_3 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("49854839-b861-4d42-bdbe-96b1a66c25ef"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("5c7a7971-2610-4bce-9e41-0caffd5a5558"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("83ff7de8-edc9-47f8-8de8-22f892ca6bb5"));
migrationBuilder.AddColumn<byte>(
name: "SubjectArea",
table: "AspNetUsers",
type: "tinyint unsigned",
nullable: false,
defaultValue: (byte)0);
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("2670f35a-df0c-4071-8879-80eb99d138a1"), null, "Teacher", "TEACHER" },
{ new Guid("8c6c5e8e-ef00-444c-9c7c-cba5cd6f7043"), null, "Student", "STUDENT" },
{ new Guid("9eda9d90-0cd2-4fbe-b07e-f90bd01f32db"), null, "Administrator", "ADMINISTRATOR" }
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("2670f35a-df0c-4071-8879-80eb99d138a1"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("8c6c5e8e-ef00-444c-9c7c-cba5cd6f7043"));
migrationBuilder.DeleteData(
table: "AspNetRoles",
keyColumn: "Id",
keyValue: new Guid("9eda9d90-0cd2-4fbe-b07e-f90bd01f32db"));
migrationBuilder.DropColumn(
name: "SubjectArea",
table: "AspNetUsers");
migrationBuilder.InsertData(
table: "AspNetRoles",
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
values: new object[,]
{
{ new Guid("49854839-b861-4d42-bdbe-96b1a66c25ef"), null, "Teacher", "TEACHER" },
{ new Guid("5c7a7971-2610-4bce-9e41-0caffd5a5558"), null, "Student", "STUDENT" },
{ new Guid("83ff7de8-edc9-47f8-8de8-22f892ca6bb5"), null, "Administrator", "ADMINISTRATOR" }
});
}
}
}

View File

@@ -219,6 +219,9 @@ namespace TechHelper.Server.Migrations
.HasColumnType("varchar(1024)")
.HasColumnName("title");
b.Property<byte>("Type")
.HasColumnType("tinyint unsigned");
b.HasKey("Id");
b.HasIndex("AssignmentId");
@@ -332,6 +335,25 @@ namespace TechHelper.Server.Migrations
b.ToTable("class_teachers", (string)null);
});
modelBuilder.Entity("Entities.Contracts.Global", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)")
.HasColumnName("id");
b.Property<byte>("Area")
.HasColumnType("tinyint unsigned");
b.Property<string>("Info")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("global");
});
modelBuilder.Entity("Entities.Contracts.KeyPoint", b =>
{
b.Property<Guid>("Id")
@@ -445,6 +467,10 @@ namespace TechHelper.Server.Migrations
.HasColumnType("longtext")
.HasColumnName("options");
b.Property<string>("QType")
.IsRequired()
.HasColumnType("longtext");
b.Property<byte>("SubjectArea")
.HasMaxLength(100)
.HasColumnType("tinyint unsigned")
@@ -723,6 +749,9 @@ namespace TechHelper.Server.Migrations
b.Property<string>("SecurityStamp")
.HasColumnType("longtext");
b.Property<byte>("SubjectArea")
.HasColumnType("tinyint unsigned");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("tinyint(1)");
@@ -771,19 +800,19 @@ namespace TechHelper.Server.Migrations
b.HasData(
new
{
Id = new Guid("df89b9a0-65ef-42dd-b2cb-e59997a72e70"),
Id = new Guid("8c6c5e8e-ef00-444c-9c7c-cba5cd6f7043"),
Name = "Student",
NormalizedName = "STUDENT"
},
new
{
Id = new Guid("0775702a-5db7-4747-94d0-4376fad2b58b"),
Id = new Guid("2670f35a-df0c-4071-8879-80eb99d138a1"),
Name = "Teacher",
NormalizedName = "TEACHER"
},
new
{
Id = new Guid("37f41430-0cb7-44e5-988b-976200bd602d"),
Id = new Guid("9eda9d90-0cd2-4fbe-b07e-f90bd01f32db"),
Name = "Administrator",
NormalizedName = "ADMINISTRATOR"
});

View File

@@ -17,9 +17,9 @@ using Microsoft.OpenApi.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(); // <EFBFBD><EFBFBD><EFBFBD><EFBFBD> MVC <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD> API)
builder.Services.AddControllers(); // 添加 MVC 控制器服务 (用于 API)
// 2. <EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (DbContext)
// 2. 数据库服务 (DbContext)
builder.Services.AddDbContext<ApplicationContext>(options =>
options.UseMySql(
builder.Configuration.GetConnectionString("XSDB"),
@@ -34,17 +34,18 @@ builder.Services.AddDbContext<ApplicationContext>(options =>
.AddCustomRepository<ClassTeacher, ClassTeacherRepository>()
.AddCustomRepository<Question, QuestionRepository>()
.AddCustomRepository<QuestionContext, QuestionContextRepository>()
.AddCustomRepository<Submission, SubmissionRepository>();
.AddCustomRepository<Submission, SubmissionRepository>()
.AddCustomRepository<Global, GlobalRepository>();
builder.Services.AddAutoMapper(typeof(AutoMapperProFile).Assembly);
// 3. <EFBFBD><EFBFBD><EFBFBD>÷<EFBFBD><EFBFBD><EFBFBD> (IOptions)
// 3. 配置服务 (IOptions)
builder.Services.Configure<ApiConfiguration>(builder.Configuration.GetSection("ApiConfiguration"));
builder.Services.Configure<JwtConfiguration>(builder.Configuration.GetSection("JWTSettings"));
// 4. <EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> (Identity, JWT, <EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD> Auth)
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> ASP.NET Core Identity (<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD>ϵ<EFBFBD> Cookie <20><>֤<EFBFBD><D6A4><EFBFBD><EFBFBD>Ȩ<EFBFBD><C8A8><EFBFBD><EFBFBD>)
// 4. 认证和授权服务 (Identity, JWT, 自定义 Auth)
// 添加 ASP.NET Core Identity (包含默认的 Cookie 认证和授权服务)
builder.Services.AddIdentity<User, IdentityRole<Guid>>(opt =>
{
opt.User.AllowedUserNameCharacters = "";
@@ -60,25 +61,25 @@ builder.Services.Configure<DataProtectionTokenProviderOptions>(Options =>
});
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> JWT Bearer <EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// 添加 JWT Bearer 认证方案
var jwtSettings = builder.Configuration.GetSection("JWTSettings");
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; // <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ JWT Bearer
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; // <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ս<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ JWT Bearer
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; // 设置默认认证方案为 JWT Bearer
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; // 设置默认挑战方案为 JWT Bearer
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true, // <EFBFBD><EFBFBD>֤ǩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ValidateAudience = true, // <EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ValidateLifetime = true, // <EFBFBD><EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD>
ValidateIssuerSigningKey = true, // <EFBFBD><EFBFBD>֤ǩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ
ValidateIssuer = true, // 验证签发人
ValidateAudience = true, // 验证受众
ValidateLifetime = true, // 验证令牌有效期
ValidateIssuerSigningKey = true, // 验证签名密钥
ValidIssuer = jwtSettings["validIssuer"], // <EFBFBD>Ϸ<EFBFBD><EFBFBD><EFBFBD>ǩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ValidAudience = jwtSettings["validAudience"], // <EFBFBD>Ϸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings["securityKey"])) // ǩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ
ValidIssuer = jwtSettings["validIssuer"], // 合法的签发人
ValidAudience = jwtSettings["validAudience"], // 合法的受众
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings["securityKey"])) // 签名密钥
};
});
@@ -90,6 +91,7 @@ builder.Services.AddScoped<IExamService, ExamService>();
builder.Services.AddScoped<IUserSerivces, UserServices>();
builder.Services.AddScoped<ISubmissionServices, SubmissionServices>();
builder.Services.AddScoped<IExamRepository, ExamRepository>();
builder.Services.AddScoped<INoteService, NoteService>();
builder.Services.AddEndpointsApiExplorer();
@@ -128,7 +130,7 @@ builder.Services.AddCors(options =>
{
options.AddPolicy("AllowSpecificOrigin",
builder => builder
.WithOrigins("https://localhost:7047", "http://localhost:7047")
.WithOrigins("https://localhost:7047", "http://localhost:7047", "https://localhost:5001", "http://localhost:5001")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials());

View File

@@ -0,0 +1,17 @@
using Entities.Contracts;
using Microsoft.EntityFrameworkCore;
using SharedDATA.Api;
using TechHelper.Context;
namespace TechHelper.Repository
{
public class GlobalRepository : Repository<Global>, IRepository<Global>
{
public GlobalRepository(ApplicationContext dbContext) : base(dbContext)
{
}
}
}

View File

@@ -0,0 +1,13 @@
using Entities.Contracts;
using Entities.DTO;
using System.Net;
namespace TechHelper.Services
{
public interface INoteService : IBaseService<GlobalDto, byte>
{
}
}

View File

@@ -0,0 +1,107 @@
using AutoMapper;
using Entities.Contracts;
using Entities.DTO;
using Microsoft.AspNetCore.Identity;
using SharedDATA.Api;
using System.Net;
namespace TechHelper.Services
{
public class NoteService : INoteService
{
private readonly IUnitOfWork _work;
private readonly IMapper _mapper;
public NoteService(IUnitOfWork work)
{
_work = work;
}
public async Task<ApiResponse> AddAsync(GlobalDto model)
{
try
{
var globalEntity = new Global
{
Area = model.SubjectArea,
Info = model.Data
};
await _work.GetRepository<Global>().InsertAsync(globalEntity);
await _work.SaveChangesAsync();
return ApiResponse.Success("数据已成功添加。");
}
catch (Exception ex)
{
return ApiResponse.Error($"添加数据时发生错误: {ex.Message}");
}
}
public async Task<ApiResponse> DeleteAsync(byte id)
{
var globalRepo = _work.GetRepository<Global>();
var globalEntity = await globalRepo.GetFirstOrDefaultAsync(predicate: x => x.Area == (SubjectAreaEnum)id);
if (globalEntity == null)
{
return ApiResponse.Error("未找到要删除的数据。");
}
globalRepo.Delete(globalEntity);
await _work.SaveChangesAsync();
return ApiResponse.Success("数据已成功删除。");
}
public async Task<ApiResponse> GetAllAsync(QueryParameter query)
{
var repository = _work.GetRepository<Global>();
// 获取所有实体,并将其 Info 属性作为结果返回
var entities = await repository.GetAllAsync();
// 直接返回字符串列表
var resultData = entities.Select(e => e.Info).ToList();
return ApiResponse.Success("数据已成功检索。", resultData);
}
public async Task<ApiResponse> GetAsync(byte id)
{
var globalEntity = await _work.GetRepository<Global>().GetFirstOrDefaultAsync(predicate: x => x.Area == (SubjectAreaEnum)id);
if (globalEntity == null)
{
return ApiResponse.Error("未找到数据。");
}
// 直接返回 Info 字符串
return ApiResponse.Success("数据已成功检索。", globalEntity.Info);
}
public async Task<ApiResponse> UpdateAsync(GlobalDto model)
{
try
{
var repository = _work.GetRepository<Global>();
var existingEntity = await repository.GetFirstOrDefaultAsync(predicate: x => x.Area == (SubjectAreaEnum)model.SubjectArea);
if (existingEntity == null)
{
return ApiResponse.Error("未找到要更新的数据。");
}
// 直接将传入的字符串赋值给 Info 属性
existingEntity.Info = model.Data;
repository.Update(existingEntity);
await _work.SaveChangesAsync();
return ApiResponse.Success("数据已成功更新。");
}
catch (Exception ex)
{
return ApiResponse.Error($"更新数据时发生错误: {ex.Message}");
}
}
}
}

View File

@@ -23,6 +23,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.1" />
</ItemGroup>