sync(theme-4): 同步 main 最新 API/Admin 与玩家端逻辑

从 main 同步站内信手动发送、媒体库选择、列表子路由重构等 API/Admin 改动;玩家端仅合并 ADMIN_CUSTOM 富文本、消息预览与充值截图压缩逻辑,保留 theme-4 样式。
This commit is contained in:
2026-06-22 14:12:40 +08:00
parent 5fbb1fd1f6
commit cffad00652
50 changed files with 4654 additions and 1186 deletions

View File

@@ -0,0 +1,27 @@
-- CreateTable
CREATE TABLE "player_message_broadcasts" (
"id" BIGSERIAL NOT NULL,
"title" VARCHAR(256) NOT NULL,
"body" TEXT NOT NULL,
"target_type" VARCHAR(16) NOT NULL,
"target_user_id" BIGINT,
"target_username" VARCHAR(64),
"recipient_count" INTEGER NOT NULL DEFAULT 0,
"created_by_id" BIGINT,
"created_by_username" VARCHAR(64),
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "player_message_broadcasts_pkey" PRIMARY KEY ("id")
);
-- AlterTable
ALTER TABLE "player_messages" ADD COLUMN "broadcast_id" BIGINT;
-- CreateIndex
CREATE INDEX "player_message_broadcasts_created_at_idx" ON "player_message_broadcasts"("created_at" DESC);
-- CreateIndex
CREATE INDEX "player_messages_broadcast_id_idx" ON "player_messages"("broadcast_id");
-- AddForeignKey
ALTER TABLE "player_messages" ADD CONSTRAINT "player_messages_broadcast_id_fkey" FOREIGN KEY ("broadcast_id") REFERENCES "player_message_broadcasts"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@@ -0,0 +1,9 @@
-- AlterTable
ALTER TABLE "player_message_broadcasts" ADD COLUMN "translations" JSONB;
-- Backfill existing rows as English content
UPDATE "player_message_broadcasts"
SET "translations" = jsonb_build_object(
'en-US', jsonb_build_object('title', "title", 'body', "body")
)
WHERE "translations" IS NULL;

View File

@@ -816,22 +816,44 @@ model DepositOrderAuditLog {
}
model PlayerMessage {
id BigInt @id @default(autoincrement())
userId BigInt @map("user_id")
type String @db.VarChar(32)
title String @db.VarChar(256)
body String @db.Text
payload Json?
readAt DateTime? @map("read_at")
createdAt DateTime @default(now()) @map("created_at")
id BigInt @id @default(autoincrement())
userId BigInt @map("user_id")
type String @db.VarChar(32)
title String @db.VarChar(256)
body String @db.Text
payload Json?
broadcastId BigInt? @map("broadcast_id")
readAt DateTime? @map("read_at")
createdAt DateTime @default(now()) @map("created_at")
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
broadcast PlayerMessageBroadcast? @relation(fields: [broadcastId], references: [id], onDelete: Cascade)
@@index([userId, createdAt(sort: Desc)])
@@index([userId, readAt])
@@index([broadcastId])
@@map("player_messages")
}
model PlayerMessageBroadcast {
id BigInt @id @default(autoincrement())
title String @db.VarChar(256)
body String @db.Text
translations Json? @map("translations")
targetType String @map("target_type") @db.VarChar(16)
targetUserId BigInt? @map("target_user_id")
targetUsername String? @map("target_username") @db.VarChar(64)
recipientCount Int @default(0) @map("recipient_count")
createdById BigInt? @map("created_by_id")
createdByUsername String? @map("created_by_username") @db.VarChar(64)
createdAt DateTime @default(now()) @map("created_at")
messages PlayerMessage[]
@@index([createdAt(sort: Desc)])
@@map("player_message_broadcasts")
}
// ============ System Config & Audit ============
model SystemConfig {