发信改为事务内每 300 人分批写入,避免全校群发一次插入过大;数据库异常现在返回明确的 503,不再只显示模糊 500。

校级、学院级管理员支持按学院、身份、行政班、教学班、姓名/学号/工号筛选,也可指定最多 500 名收件人。所有结果均由服务端重新校验权限。
接入 CKEditor 5,支持标题、列表、引用和链接;正文扩展为 MySQL longtext。
富文本在收件箱、详情弹窗和已发送记录中统一经 DOMPurify 净化后展示。
页面改用系统现有的冷白、靛蓝、青绿色令牌,新增“选择收件人 → 编辑内容”工作台和移动端适配。
This commit is contained in:
2026-07-27 12:53:10 +08:00 Unverified
parent 33ae991e86
commit 06d40a7bf1
13 changed files with 9180 additions and 221 deletions
@@ -980,7 +980,7 @@ public sealed class AppDbContext(DbContextOptions<AppDbContext> options)
builder.Entity<Notification>(entity =>
{
entity.Property(x => x.Title).HasMaxLength(200);
entity.Property(x => x.Content).HasMaxLength(1000);
entity.Property(x => x.Content).HasColumnType("longtext");
entity.Property(x => x.LinkUrl).HasMaxLength(300);
entity.HasIndex(x => new { x.UserId, x.IsRead });
entity.HasIndex(x => new { x.UserId, x.Category, x.CreatedAt });
@@ -996,7 +996,7 @@ public sealed class AppDbContext(DbContextOptions<AppDbContext> options)
{
entity.Property(x => x.SenderName).HasMaxLength(100);
entity.Property(x => x.Title).HasMaxLength(200);
entity.Property(x => x.Content).HasMaxLength(1000);
entity.Property(x => x.Content).HasColumnType("longtext");
entity.Property(x => x.AudienceName).HasMaxLength(200);
entity.Property(x => x.LinkUrl).HasMaxLength(300);
entity.HasIndex(x => new { x.SenderUserId, x.CreatedAt });
@@ -0,0 +1,54 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
{
/// <inheritdoc />
public partial class MessageRichContent : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "Content",
table: "Notifications",
type: "longtext",
nullable: false,
oldClrType: typeof(string),
oldType: "varchar(1000)",
oldMaxLength: 1000);
migrationBuilder.AlterColumn<string>(
name: "Content",
table: "MessageDispatches",
type: "longtext",
nullable: false,
oldClrType: typeof(string),
oldType: "varchar(1000)",
oldMaxLength: 1000);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "Content",
table: "Notifications",
type: "varchar(1000)",
maxLength: 1000,
nullable: false,
oldClrType: typeof(string),
oldType: "longtext");
migrationBuilder.AlterColumn<string>(
name: "Content",
table: "MessageDispatches",
type: "varchar(1000)",
maxLength: 1000,
nullable: false,
oldClrType: typeof(string),
oldType: "longtext");
}
}
}
@@ -2366,8 +2366,7 @@ namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
b.Property<string>("Content")
.IsRequired()
.HasMaxLength(1000)
.HasColumnType("varchar(1000)");
.HasColumnType("longtext");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
@@ -2413,8 +2412,7 @@ namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
b.Property<string>("Content")
.IsRequired()
.HasMaxLength(1000)
.HasColumnType("varchar(1000)");
.HasColumnType("longtext");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");