Files
stu-ai-demo/prisma/seed.ts

180 lines
8.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { PrismaClient } from '@prisma/client'
import bcrypt from 'bcryptjs'
import { Permissions, ALL_PERMISSIONS } from '../src/constants/permissions'
import fs from 'fs'
import path from 'path'
const prisma = new PrismaClient()
// 解析 JSON 文件并导入院系数据
async function importDepartments() {
const jsonPath = path.join(__dirname, 'init_data', '院系.json')
const jsonContent = fs.readFileSync(jsonPath, 'utf-8')
const departments = JSON.parse(jsonContent)
console.log(`开始导入 ${departments.length} 个院系...`)
await Promise.all(
departments.map((dept: any) => {
return prisma.dept.upsert({
where: { code: dept.id },
update: {
name: dept.name,
fullName: dept.full_name,
},
create: {
code: dept.id,
name: dept.name,
fullName: dept.full_name,
},
})
})
)
console.log('院系数据导入完成')
}
async function main() {
console.log('开始数据库初始化...')
// 插入权限
for (const permName of ALL_PERMISSIONS) {
await prisma.permission.upsert({
where: { name: permName },
update: {},
create: { name: permName },
})
}
// 角色与权限映射
const rolePermissionsMap: Record<string, string[]> = {
系统管理员: ALL_PERMISSIONS,
}
// 插入角色
for (const [roleName, perms] of Object.entries(rolePermissionsMap)) {
await prisma.role.upsert({
where: { name: roleName },
update: {},
create: {
name: roleName,
permissions: {
connect: perms.map((name) => ({ name })),
},
},
})
}
await importDepartments()
// 创建测试用户
const usersToCreate = [
{ id: 'user1', name: '用户甲', status: '在校', deptCode: '00001', roleNames: [] },
{ id: 'sys_admin', name: '系统管理员', status: '在校', deptCode: '00001', roleNames: ['系统管理员'] },
{ id: 'super_admin', password: process.env.SUPER_ADMIN_PASSWORD, name: '超级管理员', status: '在校', deptCode: '00001', roleNames: [], isSuperAdmin: true },
{ id: 'unknown', name: '未知用户', status: '在校', deptCode: '00001', roleNames: [] },
]
for (const u of usersToCreate) {
const password = await bcrypt.hash(u.password ?? '123456', 12)
await prisma.user.upsert({
where: { id: u.id },
update: {
name: u.name,
status: u.status,
deptCode: u.deptCode,
password,
isSuperAdmin: u.isSuperAdmin ?? false,
roles: {
set: u.roleNames.map((name) => ({ name })),
},
},
create: {
id: u.id,
name: u.name,
status: u.status,
deptCode: u.deptCode,
password,
isSuperAdmin: u.isSuperAdmin ?? false,
roles: {
connect: u.roleNames.map((name) => ({ name })),
},
},
})
}
// 插入文件类型(仅开发环境)
const fileTypes = [
{ id: 'COMPONENT_UI', name: 'UI组件', description: '使用"use client"不涉及复杂数据获取专注于UI和交互通用性强' },
{ id: 'COMPONENT_FEATURE', name: '业务组件', description: '使用"use client"不涉及复杂数据获取专注于UI和交互与业务关联性强' },
{ id: 'COMPONENT_PAGE', name: '页面组件', description: 'src/app下的page.tsx文件是页面的主入口' },
{ id: 'COMPONENT_LAYOUT', name: '布局组件', description: '不对应某个特定页面的前端组件,例如定义页面布局的文件' },
{ id: 'COMPONENT_REF', name: '组件关联文件', description: '前端组件相关的其他文件例如定义表格列属性的columns.tsx文件' },
{ id: 'API_TRPC', name: 'tRPC API', description: '基于tRPC的API' },
{ id: 'API_NEXT', name: 'NextJS原生API', description: '直接基于NextJS框架构建的API' },
{ id: 'BACKGROUND_JOB', name: '后台任务', description: '执行后台任务的文件(worker/queue)' },
{ id: 'HOOK', name: 'React Hook', description: '文件名以use开头导出自定义React Hook' },
{ id: 'UTIL', name: '工具函数', description: '提供纯函数、常量等通用工具' },
{ id: 'SCHEMA', name: '数据模式', description: '定义数据长什么样的文件,通常用于保证前后端数据的一致性,对数据进行校验' },
{ id: 'STYLES', name: '样式文件', description: '全局或局部样式文件' },
{ id: 'ASSET', name: '资源文件', description: '图片(包括svg)、视频、音频、文本等' },
{ id: 'TYPE_DEFINITION', name: '类型定义', description: '主要用于导出TypeScript类型和常量' },
{ id: 'GENERATE', name: '自动生成', description: '自动生成的文件' },
{ id: 'SCRIPT', name: '脚本文件', description: '独立于项目单独运行的文件例如prisma/seed.ts' },
{ id: 'FRAMEWORK', name: '框架配置', description: '各种前端库约定俗成的配置文件例如schema.prisma' },
{ id: 'CONFIG', name: '项目配置', description: '项目级别的配置文件通常位于项目根目录下例如package.json' },
{ id: 'OTHER', name: '其他', description: '无法归入以上分类的文件' },
]
for (let index = 0; index < fileTypes.length; index++) {
const fileType = fileTypes[index]
await prisma.devFileType.upsert({
where: { id: fileType.id },
update: {
name: fileType.name,
description: fileType.description,
order: (index + 1) * 10,
},
create: {...fileType, order: (index + 1) * 10},
})
}
console.log('文件类型数据初始化完成')
// 插入依赖包类型(仅开发环境)
const pkgTypes = [
{ id: 'CORE_FRAMEWORK', name: '核心框架', description: '构成应用程序骨架的基础技术决定了项目的基本结构和运行方式例如next、react、react-dom、vue、angular、svelte、remix、solid-js、nuxt、gatsby。' },
{ id: 'UI_INTERACTION', name: 'UI & 交互', description: '负责构建用户界面、处理用户交互和视觉呈现的所有库例如radix-ui/react-xxx、shadcn/ui、@dnd-kit/core、@tanstack/react-table、react-hook-form、lucide-react、framer-motion、antd、mui、chakra-ui、bootstrap、tailwindcss、emotion、styled-components、react-select、react-datepicker、react-toastify、react-icons。' },
{ id: 'API_DATA_COMMS', name: 'API & 数据通信', description: '负责前后端数据交换、API定义和请求例如@trpc/server、@trpc/client、@tanstack/react-query、axios、graphql-request、apollo-client、ws。' },
{ id: 'DATA_LAYER', name: '数据层', description: '负责与数据库、缓存、对象存储等进行交互,例如@prisma/client、ioredis、minio、mongoose、typeorm、sequelize、knex、redis、mongodb、pg、mysql、sqlite3、firebase、supabase。' },
{ id: 'BACKGROUND_JOBS', name: '后台任务', description: '用于处理异步、长时间运行或计划任务例如bullmq、agenda、node-cron、bree、bull、kue、bee-queue、sqs-consumer、rabbitmq、bull-board、bull-arena。' },
{ id: 'SECURITY_AUTH', name: '安全 & 认证', description: '负责用户身份验证、授权和数据加密例如next-auth、bcryptjs、jsonwebtoken、passport、oauth2orize、casl、argon2、express-session、helmet、csrf、@auth0/auth0-react。' },
{ id: 'AI_LLM', name: 'AI & 大模型', description: '专门用于与大型语言模型或其他AI服务进行交互例如ai、@ai-sdk/openai、@ai-sdk/anthropic、openai、@huggingface/inference、langchain、replicate、cohere-ai、stability-sdk、transformers、vertex-ai。' },
{ id: 'UTILITIES', name: '通用工具', description: '提供特定功能的辅助函数库如日期处理、状态管理、验证等例如zod、date-fns、nanoid、lodash、ramda、moment、uuid、joi、yup、clsx、tailwind-merge、deepmerge、numeral、dayjs、chalk、debug、dotenv。' },
{ id: 'NODEJS_CORE', name: 'Node.js核心', description: 'Node.js运行时内置的模块用于底层操作如文件系统、路径处理等例如fs、path、child_process、util、module、os、http、crypto、events、stream、process、net、url、assert。' },
]
for (let index = 0; index < pkgTypes.length; index++) {
const pkgType = pkgTypes[index]
await prisma.devPkgType.upsert({
where: { id: pkgType.id },
update: {
name: pkgType.name,
description: pkgType.description,
order: (index + 1) * 10,
},
create: {...pkgType, order: (index + 1) * 10},
})
}
console.log('依赖包类型数据初始化完成')
console.log('数据库初始化完成')
}
main()
.then(async () => {
await prisma.$disconnect()
})
.catch(async (e) => {
console.error(e)
await prisma.$disconnect()
process.exit(1)
})