411 lines
13 KiB
Plaintext
411 lines
13 KiB
Plaintext
generator client {
|
|
provider = "prisma-client-js"
|
|
}
|
|
|
|
datasource db {
|
|
provider = "postgresql"
|
|
url = env("DATABASE_URL")
|
|
}
|
|
|
|
model AdminUser {
|
|
id String @id @default(uuid())
|
|
email String @unique
|
|
name String
|
|
passwordHash String
|
|
role String @default("admin")
|
|
isActive Boolean @default(true)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
auditLogs AuditLog[]
|
|
assignedLeads Lead[] @relation("LeadAssignee")
|
|
}
|
|
|
|
model MediaAsset {
|
|
id String @id @default(uuid())
|
|
url String @unique
|
|
name String?
|
|
mimeType String?
|
|
sizeBytes Int?
|
|
group String?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
model HeroSlide {
|
|
id String @id @default(uuid())
|
|
title String
|
|
kicker String?
|
|
actionLabel String?
|
|
image String
|
|
targetType String?
|
|
targetValue String?
|
|
sortOrder Int @default(0)
|
|
isActive Boolean @default(true)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
model Destination {
|
|
id String @id @default(uuid())
|
|
name String @unique
|
|
slug String @unique
|
|
region String?
|
|
image String?
|
|
isHot Boolean @default(false)
|
|
sortOrder Int @default(0)
|
|
isActive Boolean @default(true)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
aliases DestinationAlias[]
|
|
products Product[]
|
|
}
|
|
|
|
model DestinationAlias {
|
|
id String @id @default(uuid())
|
|
alias String
|
|
destinationId String
|
|
destination Destination @relation(fields: [destinationId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([alias, destinationId])
|
|
}
|
|
|
|
model ThemeCard {
|
|
id String @id @default(uuid())
|
|
label String
|
|
image String
|
|
targetType String?
|
|
targetValue String?
|
|
sortOrder Int @default(0)
|
|
isActive Boolean @default(true)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
model CtaBanner {
|
|
id String @id @default(uuid())
|
|
alt String
|
|
image String
|
|
targetType String
|
|
targetValue String?
|
|
sortOrder Int @default(0)
|
|
isActive Boolean @default(true)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
model DestinationPageConfig {
|
|
id String @id @default("destination-home")
|
|
recommendedProductIds Json
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
model SearchPageConfig {
|
|
id String @id @default("search-page")
|
|
title String
|
|
subtitle String
|
|
placeholder String
|
|
modules Json @default("{}")
|
|
popularKeywords Json
|
|
groups Json
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
model HomeModule {
|
|
id String @id
|
|
label String
|
|
templateType String @default("explore")
|
|
content Json?
|
|
publishedConfig Json?
|
|
sortOrder Int @default(0)
|
|
isActive Boolean @default(true)
|
|
isSystem Boolean @default(false)
|
|
isDeleted Boolean @default(false)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
model Product {
|
|
id String @id @default(uuid())
|
|
sourceId Int? @unique
|
|
title String
|
|
subtitle String?
|
|
destinationId String?
|
|
destination Destination? @relation(fields: [destinationId], references: [id], onDelete: SetNull)
|
|
priceAmount Int?
|
|
priceUnit String @default("起/人")
|
|
pricingTiers Json?
|
|
tags String[]
|
|
coverImage String?
|
|
summary String?
|
|
durationDays Int?
|
|
durationNights Int?
|
|
departureDates String[] @default([])
|
|
remainingSpots Int?
|
|
recommendation String?
|
|
keyFacts Json?
|
|
contentBlocks Json?
|
|
detailSections Json?
|
|
status String @default("published")
|
|
sortWeight Int @default(0)
|
|
publishedAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
images ProductImage[]
|
|
campaignLinks CampaignProduct[]
|
|
leads Lead[]
|
|
favorites MiniProgramFavorite[]
|
|
histories MiniProgramHistory[]
|
|
orders Order[]
|
|
}
|
|
|
|
model ProductImage {
|
|
id String @id @default(uuid())
|
|
productId String
|
|
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
|
|
url String
|
|
alt String?
|
|
sortOrder Int @default(0)
|
|
}
|
|
|
|
model Campaign {
|
|
id String @id @default(uuid())
|
|
slug String @unique
|
|
title String
|
|
description String?
|
|
coverImage String?
|
|
status String @default("published")
|
|
startsAt DateTime?
|
|
endsAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
products CampaignProduct[]
|
|
}
|
|
|
|
model CampaignProduct {
|
|
campaignId String
|
|
productId String
|
|
sortOrder Int @default(0)
|
|
campaign Campaign @relation(fields: [campaignId], references: [id], onDelete: Cascade)
|
|
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
|
|
|
|
@@id([campaignId, productId])
|
|
}
|
|
|
|
model Lead {
|
|
id String @id @default(uuid())
|
|
requestType String @default("custom")
|
|
userId String?
|
|
user MiniProgramUser? @relation(fields: [userId], references: [id], onDelete: SetNull)
|
|
wecomContactId String?
|
|
wecomContact WecomExternalContact? @relation(fields: [wecomContactId], references: [id], onDelete: SetNull)
|
|
destination String?
|
|
phone String
|
|
contactName String?
|
|
wechat String?
|
|
travelDate DateTime?
|
|
peopleCount Int?
|
|
adultCount Int?
|
|
childCount Int?
|
|
roomType String?
|
|
plan String?
|
|
addOns String[] @default([])
|
|
budgetMin Int?
|
|
budgetMax Int?
|
|
note String?
|
|
sourcePage String?
|
|
sourceTheme String?
|
|
sourceProductId String?
|
|
sourceProduct Product? @relation(fields: [sourceProductId], references: [id], onDelete: SetNull)
|
|
adminNote String?
|
|
processed Boolean @default(false)
|
|
status String @default("new")
|
|
assignedUserId String?
|
|
assignedUser AdminUser? @relation("LeadAssignee", fields: [assignedUserId], references: [id], onDelete: SetNull)
|
|
followups LeadFollowup[]
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@index([userId, createdAt])
|
|
@@index([phone])
|
|
@@index([requestType, status, createdAt])
|
|
@@index([wecomContactId])
|
|
}
|
|
|
|
model LeadFollowup {
|
|
id String @id @default(uuid())
|
|
leadId String
|
|
lead Lead @relation(fields: [leadId], references: [id], onDelete: Cascade)
|
|
content String
|
|
nextAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
}
|
|
|
|
model MiniProgramUser {
|
|
id String @id @default(uuid())
|
|
appId String
|
|
openId String
|
|
unionId String?
|
|
nickname String?
|
|
avatarUrl String?
|
|
phone String?
|
|
phoneAuthorizedAt DateTime?
|
|
note String?
|
|
source String @default("mini_program")
|
|
status String @default("active")
|
|
customerId String? @unique
|
|
customer Customer? @relation(fields: [customerId], references: [id], onDelete: SetNull)
|
|
firstSeenAt DateTime @default(now())
|
|
lastLoginAt DateTime @default(now())
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
leads Lead[]
|
|
favorites MiniProgramFavorite[]
|
|
histories MiniProgramHistory[]
|
|
wecomContacts WecomExternalContact[]
|
|
h5AuthTickets H5AuthTicket[]
|
|
|
|
@@unique([appId, openId])
|
|
@@index([phone])
|
|
@@index([status, lastLoginAt])
|
|
}
|
|
|
|
model H5AuthTicket {
|
|
id String @id @default(uuid())
|
|
tokenHash String @unique
|
|
userId String
|
|
user MiniProgramUser @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
expiresAt DateTime
|
|
consumedAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
|
|
@@index([expiresAt])
|
|
@@index([userId, createdAt])
|
|
}
|
|
|
|
model MiniProgramFavorite {
|
|
id String @id @default(uuid())
|
|
userId String
|
|
productId String
|
|
user MiniProgramUser @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
|
|
createdAt DateTime @default(now())
|
|
|
|
@@unique([userId, productId])
|
|
@@index([productId])
|
|
}
|
|
|
|
model MiniProgramHistory {
|
|
id String @id @default(uuid())
|
|
userId String
|
|
productId String
|
|
viewCount Int @default(1)
|
|
lastViewedAt DateTime @default(now())
|
|
user MiniProgramUser @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([userId, productId])
|
|
@@index([userId, lastViewedAt])
|
|
}
|
|
|
|
model Customer {
|
|
id String @id @default(uuid())
|
|
phone String? @unique
|
|
name String?
|
|
wechat String?
|
|
note String?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
miniProgramUser MiniProgramUser?
|
|
orders Order[]
|
|
wecomContacts WecomExternalContact[]
|
|
}
|
|
|
|
model WecomContactWay {
|
|
id String @id @default(uuid())
|
|
configId String @unique
|
|
type Int @default(1)
|
|
scene Int @default(1)
|
|
style Int @default(1)
|
|
remark String?
|
|
state String?
|
|
wecomUserId String?
|
|
enabled Boolean @default(true)
|
|
lastSyncedAt DateTime?
|
|
lastSyncError String?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
externalContacts WecomExternalContact[]
|
|
}
|
|
|
|
model WecomExternalContact {
|
|
id String @id @default(uuid())
|
|
externalUserId String
|
|
wecomUserId String
|
|
contactWayId String?
|
|
contactWay WecomContactWay? @relation(fields: [contactWayId], references: [id], onDelete: SetNull)
|
|
miniProgramUserId String?
|
|
miniProgramUser MiniProgramUser? @relation(fields: [miniProgramUserId], references: [id], onDelete: SetNull)
|
|
customerId String?
|
|
customer Customer? @relation(fields: [customerId], references: [id], onDelete: SetNull)
|
|
name String?
|
|
avatarUrl String?
|
|
type Int?
|
|
gender Int?
|
|
unionId String?
|
|
corpName String?
|
|
position String?
|
|
remark String?
|
|
description String?
|
|
profile Json?
|
|
status String @default("active")
|
|
addedAt DateTime?
|
|
lastEventAt DateTime @default(now())
|
|
deletedAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
leads Lead[]
|
|
|
|
@@unique([externalUserId, wecomUserId])
|
|
@@index([status, lastEventAt])
|
|
@@index([miniProgramUserId])
|
|
@@index([customerId])
|
|
@@index([contactWayId])
|
|
}
|
|
|
|
model Order {
|
|
id String @id @default(uuid())
|
|
customerId String?
|
|
customer Customer? @relation(fields: [customerId], references: [id], onDelete: SetNull)
|
|
productId String?
|
|
product Product? @relation(fields: [productId], references: [id], onDelete: SetNull)
|
|
status String @default("draft")
|
|
travelDate DateTime?
|
|
amount Int?
|
|
note String?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
model SiteVersion {
|
|
id String @id @default(uuid())
|
|
title String
|
|
status String @default("draft")
|
|
snapshot Json
|
|
publishedAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
}
|
|
|
|
model AuditLog {
|
|
id String @id @default(uuid())
|
|
actorId String?
|
|
actor AdminUser? @relation(fields: [actorId], references: [id], onDelete: SetNull)
|
|
action String
|
|
entity String
|
|
entityId String?
|
|
before Json?
|
|
after Json?
|
|
createdAt DateTime @default(now())
|
|
}
|