feat: 新增门户功能并重构资源展示组件
- 新增门户(Portal)数据模型与后端 API 端点 - 新增个人资料页面,支持用户更新昵称 - 重构前端资源卡片组件,支持显示 GitHub 版本信息与加速下载链接 - 在登录/注册页面添加 GitHub OAuth 支持 - 更新环境变量示例文件,添加前后端配置项 - 优化导航栏响应式设计,添加移动端菜单 - 添加页脚组件,包含备案信息 - 更新 Prisma 数据模型,适配 Better Auth 并添加种子数据 - 统一前后端 API URL 配置,支持环境变量覆盖
This commit is contained in:
@@ -11,49 +11,54 @@ datasource db {
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
name String?
|
||||
email String? @unique
|
||||
emailVerified DateTime?
|
||||
phone String? @unique
|
||||
phoneVerified DateTime?
|
||||
name String
|
||||
email String @unique
|
||||
emailVerified Boolean
|
||||
image String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
accounts Account[]
|
||||
createdAt DateTime
|
||||
updatedAt DateTime
|
||||
sessions Session[]
|
||||
accounts Account[]
|
||||
posts Post[]
|
||||
comments Comment[]
|
||||
|
||||
@@map("users")
|
||||
}
|
||||
|
||||
model Account {
|
||||
id String @id @default(cuid())
|
||||
userId String @map("user_id")
|
||||
type String
|
||||
provider String
|
||||
providerAccountId String @map("provider_account_id")
|
||||
refresh_token String?
|
||||
access_token String?
|
||||
expires_at Int?
|
||||
token_type String?
|
||||
scope String?
|
||||
id_token String?
|
||||
session_state String?
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([provider, providerAccountId])
|
||||
@@map("accounts")
|
||||
}
|
||||
|
||||
model Session {
|
||||
id String @id @default(cuid())
|
||||
sessionToken String @unique @map("session_token")
|
||||
userId String @map("user_id")
|
||||
expires DateTime
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
id String @id @default(cuid())
|
||||
expiresAt DateTime
|
||||
token String @unique
|
||||
createdAt DateTime
|
||||
updatedAt DateTime
|
||||
ipAddress String?
|
||||
userAgent String?
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
}
|
||||
|
||||
@@map("sessions")
|
||||
model Account {
|
||||
id String @id @default(cuid())
|
||||
accountId String
|
||||
providerId String
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
accessToken String?
|
||||
refreshToken String?
|
||||
idToken String?
|
||||
accessTokenExpiresAt DateTime?
|
||||
refreshTokenExpiresAt DateTime?
|
||||
scope String?
|
||||
password String?
|
||||
createdAt DateTime
|
||||
updatedAt DateTime
|
||||
}
|
||||
|
||||
model Verification {
|
||||
id String @id @default(cuid())
|
||||
identifier String
|
||||
value String
|
||||
expiresAt DateTime
|
||||
createdAt DateTime?
|
||||
updatedAt DateTime?
|
||||
}
|
||||
|
||||
model Post {
|
||||
@@ -66,21 +71,36 @@ model Post {
|
||||
updatedAt DateTime @updatedAt
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
comments Comment[]
|
||||
|
||||
@@map("posts")
|
||||
}
|
||||
|
||||
model Resource {
|
||||
id String @id @default(cuid())
|
||||
title String
|
||||
description String?
|
||||
url String
|
||||
icon String?
|
||||
image String?
|
||||
category String?
|
||||
githubRepo String?
|
||||
downloadCdn String?
|
||||
downloadOriginal String?
|
||||
version String?
|
||||
background Boolean @default(false)
|
||||
order Int @default(0)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model Portal {
|
||||
id String @id @default(cuid())
|
||||
title String
|
||||
description String?
|
||||
url String
|
||||
description String?
|
||||
icon String?
|
||||
category String?
|
||||
background Boolean @default(false)
|
||||
order Int @default(0)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@map("resources")
|
||||
}
|
||||
|
||||
model Comment {
|
||||
@@ -92,15 +112,4 @@ model Comment {
|
||||
updatedAt DateTime @updatedAt
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
post Post @relation(fields: [postId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("comments")
|
||||
}
|
||||
|
||||
model VerificationToken {
|
||||
identifier String
|
||||
token String @unique
|
||||
expires DateTime
|
||||
|
||||
@@unique([identifier, token])
|
||||
@@map("verification_tokens")
|
||||
}
|
||||
|
||||
246
backend/prisma/seed.ts
Normal file
246
backend/prisma/seed.ts
Normal file
@@ -0,0 +1,246 @@
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
import { PrismaPg } from "@prisma/adapter-pg";
|
||||
import pg from "pg";
|
||||
|
||||
const connectionString = process.env.DATABASE_URL;
|
||||
const pool = new pg.Pool({ connectionString });
|
||||
const adapter = new PrismaPg(pool);
|
||||
|
||||
const prisma = new PrismaClient({ adapter });
|
||||
|
||||
const portalData = [
|
||||
{
|
||||
title: '中文论坛',
|
||||
url: 'https://forum.hlae.site',
|
||||
description: 'HLAE中文交流社区',
|
||||
icon: 'pi pi-comments',
|
||||
background: true,
|
||||
},
|
||||
{
|
||||
title: '官方Wiki',
|
||||
url: 'https://github.com/advancedfx/advancedfx/wiki',
|
||||
description: '权威,但是英文 orz',
|
||||
icon: 'pi pi-book',
|
||||
background: true,
|
||||
},
|
||||
{
|
||||
title: '新版文档',
|
||||
url: 'https://doc.hlae.site',
|
||||
description: '新版 advancedfx 文档,建设中',
|
||||
icon: 'pi pi-bookmark',
|
||||
background: true,
|
||||
},
|
||||
{
|
||||
title: '官方Discord',
|
||||
url: 'https://discord.gg/NGp8qhN',
|
||||
description: '和开发者近距离交流',
|
||||
icon: 'pi pi-discord',
|
||||
background: true,
|
||||
},
|
||||
{
|
||||
title: '问题与建议提交',
|
||||
url: 'https://github.com/advancedfx/advancedfx/issues',
|
||||
description: 'tnnd 为什么不更新',
|
||||
icon: 'pi pi-question-circle',
|
||||
background: true,
|
||||
},
|
||||
{
|
||||
title: 'HUD生成器',
|
||||
url: 'https://hud.hlae.site',
|
||||
description: '击杀信息和准星生成工具',
|
||||
icon: 'pi pi-wrench',
|
||||
background: true,
|
||||
},
|
||||
{
|
||||
title: '击杀信息生成',
|
||||
url: '/hud/deathmsg',
|
||||
description: 'CS2 · CS 击杀信息生成工具(测试)',
|
||||
icon: 'pi pi-sliders-h',
|
||||
background: true,
|
||||
},
|
||||
{
|
||||
title: 'HLTV',
|
||||
url: 'https://hltv.org/',
|
||||
description: 'CSGO新闻、数据、录像',
|
||||
icon: 'pi pi-video',
|
||||
background: true,
|
||||
},
|
||||
]
|
||||
|
||||
const resourceData = [
|
||||
{
|
||||
title: 'HLAE',
|
||||
githubRepo: 'advancedfx/advancedfx',
|
||||
url: 'https://github.com/advancedfx/advancedfx',
|
||||
description: '起源游戏影片制作工具',
|
||||
background: false,
|
||||
downloadCdn: 'https://api.upup.cool/get/hlae',
|
||||
downloadOriginal: 'https://github.com/advancedfx/advancedfx/releases/latest',
|
||||
image: '/icon/hlae.png',
|
||||
},
|
||||
{
|
||||
title: 'FFmpeg',
|
||||
githubRepo: 'GyanD/codexffmpeg',
|
||||
url: 'https://ffmpeg.org',
|
||||
description: '免费开源的全能媒体转码工具',
|
||||
background: false,
|
||||
downloadCdn: 'https://api.upup.cool/get/ffmpeg',
|
||||
downloadOriginal: 'https://github.com/GyanD/codexffmpeg/releases/latest',
|
||||
image: '/icon/ffmpeg.webp',
|
||||
},
|
||||
{
|
||||
title: 'CFG预设 For CS2',
|
||||
githubRepo: 'Purple-CSGO/CS2-Config-Presets',
|
||||
url: 'https://cfg.upup.cool/v2',
|
||||
description: '适用于CS2各场景的Config预设',
|
||||
background: true,
|
||||
downloadCdn: 'https://api.upup.cool/get/cs2-cfg',
|
||||
downloadOriginal: 'https://github.com/Purple-CSGO/CS2-Config-Presets/releases/latest',
|
||||
icon: 'pi pi-github',
|
||||
},
|
||||
{
|
||||
title: 'CS Demo Manager',
|
||||
githubRepo: 'akiver/CS-Demo-Manager',
|
||||
url: 'https://cs-demo-manager.com',
|
||||
description: 'CS录像分析观看工具',
|
||||
background: true,
|
||||
downloadCdn: 'https://api.upup.cool/get/csdm',
|
||||
downloadOriginal: 'https://github.com/akiver/CS-Demo-Manager/releases/latest',
|
||||
image: '/icon/csdm.svg',
|
||||
},
|
||||
{
|
||||
title: 'CS工具箱',
|
||||
githubRepo: 'plsgo/cstb',
|
||||
url: 'https://cstb.upup.cool',
|
||||
description: '一个为CS游戏各个方面带来便利的工具集合',
|
||||
background: true,
|
||||
downloadCdn: 'https://api.upup.cool/get/cstb',
|
||||
downloadOriginal: 'https://github.com/plsgo/cstb/releases/latest',
|
||||
image: '/icon/cstb.png',
|
||||
},
|
||||
{
|
||||
title: 'HLAE Studio',
|
||||
githubRepo: 'One-Studio/HLAE-Studio',
|
||||
url: 'https://github.com/One-Studio/HLAE-Studio',
|
||||
description: 'HLAE环境配置更新工具',
|
||||
version: 'v1.1.0',
|
||||
background: true,
|
||||
downloadCdn: 'https://api.upup.cool/get/hlae-studio',
|
||||
downloadOriginal: 'https://github.com/One-Studio/HLAE-Studio/releases/latest',
|
||||
image: '/icon/hlae-studio.png',
|
||||
},
|
||||
{
|
||||
title: 'CFG预设',
|
||||
githubRepo: 'Purple-CSGO/CSGO-Config-Presets',
|
||||
url: 'https://cfg.upup.cool',
|
||||
description: '适用于CSGO各场景的Config预设',
|
||||
background: true,
|
||||
downloadCdn: 'https://api.upup.cool/get/csgo-cfg',
|
||||
downloadOriginal: 'https://github.com/Purple-CSGO/CSGO-Config-Presets/releases/latest',
|
||||
icon: 'pi pi-github',
|
||||
},
|
||||
{
|
||||
title: 'nskinz',
|
||||
githubRepo: 'advancedfx/nSkinz',
|
||||
url: 'https://github.com/advancedfx/nskinz',
|
||||
description: 'CSGO皮肤修改替换插件 advancedfx维护版本',
|
||||
background: true,
|
||||
downloadCdn: 'https://api.upup.cool/repo/advancedfx/nSkinz/&&&&.zip',
|
||||
downloadOriginal: 'https://github.com/advancedfx/nSkinz/releases/latest',
|
||||
icon: 'pi pi-github',
|
||||
},
|
||||
{
|
||||
title: 'MIGI',
|
||||
url: 'https://zoolsmith.github.io/MIGI3',
|
||||
description: 'CSGO资源修改工具',
|
||||
background: false,
|
||||
downloadCdn: 'https://cdn.upup.cool/https://github.com/ZooLSmith/MIGI3/blob/main/migi.exe',
|
||||
downloadOriginal: 'https://github.com/ZooLSmith/MIGI3/blob/main/migi.exe',
|
||||
image: '/icon/migi.png',
|
||||
},
|
||||
{
|
||||
title: 'Voukoder',
|
||||
url: 'https://www.voukoder.org',
|
||||
description: 'PR、AE、Vegas等软件的编码导出插件',
|
||||
background: true,
|
||||
downloadOriginal: 'https://www.voukoder.org/forum/thread/783-downloads-instructions/',
|
||||
image: '/icon/voukoder.png',
|
||||
},
|
||||
{
|
||||
title: 'ReShade AFX',
|
||||
githubRepo: 'advancedfx/ReShade_advancedfx',
|
||||
url: 'https://github.com/advancedfx/ReShade_advancedfx',
|
||||
description: '连接HLAE录制的ReShade插件',
|
||||
background: false,
|
||||
downloadCdn: 'https://api.upup.cool/get/reshade-afx',
|
||||
downloadOriginal: 'https://github.com/advancedfx/ReShade_advancedfx/releases/latest',
|
||||
image: '/icon/reshade.png',
|
||||
},
|
||||
{
|
||||
title: 'ReShade',
|
||||
url: 'https://reshade.me',
|
||||
description: '重塑你的游戏画面',
|
||||
background: false,
|
||||
downloadOriginal: 'https://reshade.me',
|
||||
image: '/icon/reshade.png',
|
||||
},
|
||||
{
|
||||
title: 'ShanaEncoder',
|
||||
url: 'https://shana.pe.kr/shanaencoder_summary',
|
||||
description: '方便好用的转码压制图形工具',
|
||||
background: true,
|
||||
downloadOriginal: 'https://shana.pe.kr/shanaencoder_download',
|
||||
icon: 'pi pi-github',
|
||||
},
|
||||
{
|
||||
title: 'SRadar',
|
||||
githubRepo: 'zuoshipinSHEKL/SRadar',
|
||||
url: 'https://sdr.hlae.cn',
|
||||
description: 'Shekl制作的简易雷达',
|
||||
background: true,
|
||||
downloadCdn: 'https://api.upup.cool/get/sradar',
|
||||
downloadOriginal: 'https://github.com/zuoshipinSHEKL/SRadar/releases/latest',
|
||||
icon: 'pi pi-map',
|
||||
},
|
||||
]
|
||||
|
||||
async function main() {
|
||||
console.log('Start seeding ...')
|
||||
|
||||
await prisma.portal.deleteMany()
|
||||
await prisma.resource.deleteMany()
|
||||
|
||||
for (let i = 0; i < portalData.length; i++) {
|
||||
const portal = portalData[i]
|
||||
const p = await prisma.portal.create({
|
||||
data: {
|
||||
...portal,
|
||||
order: i,
|
||||
},
|
||||
})
|
||||
console.log(`Created portal with id: ${p.id}`)
|
||||
}
|
||||
|
||||
for (let i = 0; i < resourceData.length; i++) {
|
||||
const resource = resourceData[i]
|
||||
const r = await prisma.resource.create({
|
||||
data: {
|
||||
...resource,
|
||||
order: i,
|
||||
},
|
||||
})
|
||||
console.log(`Created resource with id: ${r.id}`)
|
||||
}
|
||||
|
||||
console.log('Seeding finished.')
|
||||
}
|
||||
|
||||
main()
|
||||
.then(async () => {
|
||||
await prisma.$disconnect()
|
||||
})
|
||||
.catch(async (e) => {
|
||||
console.error(e)
|
||||
await prisma.$disconnect()
|
||||
process.exit(1)
|
||||
})
|
||||
Reference in New Issue
Block a user