chore: sync marketing pages, CMS extensions, tests and project docs

同步工作区剩余变更,主要包括:
- 营销页面组件与布局持续优化(about/news/services/solutions/team 等)
- 详情页四层叙事组件、布局组件、UI 组件调整
- CMS 数据模型、API 路由、权限、工作流、站内通知、媒体管理扩展
- 新增/补充单元测试与 E2E 测试(cms-workflow.spec.ts 等)
- ESLint 9 迁移、jest/tsconfig 配置更新、依赖调整
- 新增 ADR、CMS 评估文档、Release Review / Acceptance 报告
- 移除水墨装饰组件与大体积未使用字体文件
This commit is contained in:
张翔
2026-07-25 08:04:01 +08:00
parent e35090b914
commit 10404dbb36
208 changed files with 18107 additions and 8330 deletions
+99 -54
View File
@@ -8,69 +8,100 @@ datasource db {
url = env("DATABASE_URL")
}
// ============ 用户与认证 ============
model User {
id String @id @default(cuid())
username String @unique
id String @id @default(cuid())
username String @unique
password String
nickname String @default("")
avatar String @default("")
email String @default("")
phone String @default("")
status Int @default(1) // 1=正常, 0=禁用
role String @default("admin") // admin | editor
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
nickname String @default("")
avatar String @default("")
email String @default("")
phone String @default("")
status Int @default(1)
role String @default("admin")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
roles UserRole[]
}
// ============ 内容模型定义 ============
model Role {
id String @id @default(cuid())
code String @unique
name String
description String @default("")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
permissions Permission[]
users UserRole[]
}
model Permission {
id String @id @default(cuid())
roleCode String
modelCode String
action String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
role Role @relation(fields: [roleCode], references: [code], onDelete: Cascade)
@@unique([roleCode, modelCode, action])
@@index([modelCode])
@@index([action])
}
model UserRole {
id String @id @default(cuid())
userId String
roleCode String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
role Role @relation(fields: [roleCode], references: [code], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([userId, roleCode])
@@index([userId])
}
model ContentModel {
id String @id @default(cuid())
code String @unique
id String @id @default(cuid())
code String @unique
name String
description String @default("")
fields String // JSON: FieldDefinition[]
isPageType Boolean @default(false)
urlPattern String @default("")
hasVersions Boolean @default(false)
hasDraft Boolean @default(false)
icon String @default("")
sortOrder Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
description String @default("")
fields String
isPageType Boolean @default(false)
urlPattern String @default("")
hasVersions Boolean @default(false)
hasDraft Boolean @default(false)
icon String @default("")
sortOrder Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
items ContentItem[]
}
// ============ 内容条目 ============
model ContentItem {
id String @id @default(cuid())
id String @id @default(cuid())
modelId String
modelCode String
title String
slug String @default("")
status String @default("draft") // draft | published | archived
data String // JSON: Record<string, unknown>
version Int @default(1)
sortOrder Int @default(0)
slug String @default("")
locale String @default("zh-CN")
status String @default("draft")
data String
version Int @default(1)
sortOrder Int @default(0)
publishedAt DateTime?
createdBy String @default("system")
updatedBy String @default("system")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
createdBy String @default("system")
updatedBy String @default("system")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
model ContentModel @relation(fields: [modelId], references: [id])
@@unique([modelCode, slug])
@@unique([modelCode, slug, locale])
@@index([modelCode])
@@index([status])
@@index([locale])
}
// ============ 内容区域 ============
model ContentZone {
id String @id @default(cuid())
code String @unique
@@ -78,17 +109,15 @@ model ContentZone {
description String @default("")
pageCode String @default("")
zoneKey String @default("")
allowedModels String @default("[]") // JSON: string[]
items String @default("[]") // JSON: ContentZoneItem[]
settings String @default("{}") // JSON: ContentZoneSettings
allowedModels String @default("[]")
items String @default("[]")
settings String @default("{}")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([pageCode])
}
// ============ 媒体资源 ============
model MediaAsset {
id String @id @default(cuid())
name String
@@ -99,22 +128,38 @@ model MediaAsset {
width Int @default(0)
height Int @default(0)
alt String @default("")
storageType String @default("local") // local | oss | s3
storageType String @default("local")
derivatives String @default("{}")
createdBy String @default("system")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
// ============ 操作日志 ============
model Notification {
id String @id @default(cuid())
userId String
type String
title String
message String
relatedItemId String @default("")
relatedModelCode String @default("")
read Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([userId])
@@index([read])
@@index([createdAt])
}
model AuditLog {
id String @id @default(cuid())
module String // model | item | zone | theme | media
module String
targetId String
action String // create | update | delete | publish | unpublish
action String
operator String
beforeData String @default("{}") // JSON
afterData String @default("{}") // JSON
beforeData String @default("{}")
afterData String @default("{}")
ip String @default("")
userAgent String @default("")
createdAt DateTime @default(now())
@@ -122,4 +167,4 @@ model AuditLog {
@@index([module])
@@index([targetId])
@@index([createdAt])
}
}