kindergarten_java/reading-platform-backend/prisma/seed.ts
2026-02-28 16:41:39 +08:00

432 lines
13 KiB
TypeScript
Raw Permalink 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 * as bcrypt from 'bcrypt';
const prisma = new PrismaClient();
async function main() {
console.log('开始种子数据...');
// 1. 创建测试租户
const tenant = await prisma.tenant.upsert({
where: { id: 1 },
update: {},
create: {
name: '阳光幼儿园',
address: '北京市朝阳区xxx街道',
contactPerson: '张园长',
contactPhone: '13800138000',
packageType: 'STANDARD',
teacherQuota: 20,
studentQuota: 200,
storageQuota: BigInt(5368709120), // 5GB
startDate: '2024-01-01',
expireDate: '2025-12-31',
status: 'ACTIVE',
},
});
console.log('创建租户:', tenant.name);
// 2. 创建教师账号
const passwordHash = await bcrypt.hash('123456', 10);
const teacher = await prisma.teacher.upsert({
where: { loginAccount: 'teacher1' },
update: {},
create: {
tenantId: tenant.id,
name: '李老师',
phone: '13900139000',
email: 'teacher1@example.com',
loginAccount: 'teacher1',
passwordHash: passwordHash,
status: 'ACTIVE',
},
});
console.log('创建教师:', teacher.name);
// 3. 创建班级
const class1 = await prisma.class.upsert({
where: { id: 1 },
update: {},
create: {
tenantId: tenant.id,
name: '中一班',
grade: 'MIDDLE',
teacherId: teacher.id,
studentCount: 25,
},
});
console.log('创建班级:', class1.name);
const class2 = await prisma.class.upsert({
where: { id: 2 },
update: {},
create: {
tenantId: tenant.id,
name: '大一班',
grade: 'BIG',
teacherId: teacher.id,
studentCount: 30,
},
});
console.log('创建班级:', class2.name);
// 4. 更新教师的班级关联
await prisma.teacher.update({
where: { id: teacher.id },
data: {
classIds: JSON.stringify([class1.id, class2.id]),
},
});
// 5. 创建示例学生
const students = [
{ name: '小明', gender: 'MALE', classId: class1.id },
{ name: '小红', gender: 'FEMALE', classId: class1.id },
{ name: '小华', gender: 'MALE', classId: class1.id },
{ name: '小丽', gender: 'FEMALE', classId: class2.id },
{ name: '小强', gender: 'MALE', classId: class2.id },
];
for (const studentData of students) {
await prisma.student.upsert({
where: {
id: students.indexOf(studentData) + 1,
},
update: {},
create: {
tenantId: tenant.id,
classId: studentData.classId,
name: studentData.name,
gender: studentData.gender,
},
});
}
console.log('创建学生:', students.length, '名');
// 6. 创建示例课程包
const course = await prisma.course.upsert({
where: { id: 1 },
update: {},
create: {
name: '好饿的毛毛虫',
description: '这是一本经典的绘本,讲述了一只毛毛虫从孵化到变成蝴蝶的故事。通过这个故事,孩子们可以学习到星期的概念、数字的认知,以及毛毛虫变蝴蝶的科学知识。',
pictureBookName: '好饿的毛毛虫',
gradeTags: JSON.stringify(['SMALL', 'MIDDLE']),
domainTags: JSON.stringify(['LANGUAGE', 'SCIENCE', 'MATH']),
duration: 30,
status: 'PUBLISHED',
version: '1.0',
coverImagePath: '/uploads/covers/caterpillar.jpg',
},
});
console.log('创建课程:', course.name);
// 7. 创建课程脚本6步教学流程
const scripts = [
{
stepIndex: 1,
stepName: '阅读导入',
stepType: 'INTRODUCTION',
duration: 5,
objective: '激发幼儿阅读兴趣,建立阅读期待',
teacherScript: '小朋友们,今天我们要认识一位新朋友——一只小小的毛毛虫。你们见过毛毛虫吗?它长什么样子呢?让我们一起来看看这只特别的毛毛虫的故事吧!',
interactionPoints: JSON.stringify([
'展示毛毛虫图片或玩偶',
'引导幼儿分享见过的毛毛虫',
'预测故事内容',
]),
},
{
stepIndex: 2,
stepName: '绘本共读',
stepType: 'READING',
duration: 10,
objective: '理解故事内容,发展语言能力',
teacherScript: '(逐页讲述)从前,有一颗小小的蛋躺在叶子上...月光下,一条又小又饿的毛毛虫从蛋里爬了出来...',
interactionPoints: JSON.stringify([
'提问预测',
'模仿毛毛虫吃东西的动作',
'一起数食物的数量',
]),
},
{
stepIndex: 3,
stepName: '理解讨论',
stepType: 'DISCUSSION',
duration: 5,
objective: '加深对故事的理解,发展思维能力',
teacherScript: '小朋友们,毛毛虫吃了哪些东西呢?为什么最后它肚子痛了?它最后变成了什么?',
interactionPoints: JSON.stringify([
'回顾毛毛虫吃的食物',
'讨论健康饮食的重要性',
'讨论毛毛虫的成长变化',
]),
},
{
stepIndex: 4,
stepName: '互动游戏',
stepType: 'ACTIVITY',
duration: 5,
objective: '通过游戏巩固学习内容',
teacherScript: '现在我们来玩一个游戏,老师说出星期几,小朋友们来模仿毛毛虫吃了什么!',
interactionPoints: JSON.stringify([
'星期与食物配对游戏',
'毛毛虫动作模仿',
'食物分类活动',
]),
},
{
stepIndex: 5,
stepName: '创意表达',
stepType: 'CREATIVE',
duration: 3,
objective: '发展创造力和表达能力',
teacherScript: '如果你是毛毛虫,你想吃什么?画一画你心目中的毛毛虫吧!',
interactionPoints: JSON.stringify([
'自由绘画',
'分享作品',
'创意表达',
]),
},
{
stepIndex: 6,
stepName: '总结延伸',
stepType: 'SUMMARY',
duration: 2,
objective: '总结学习内容,激发延伸探索兴趣',
teacherScript: '今天我们认识了一只可爱的毛毛虫,它从一颗小蛋,变成毛毛虫,最后变成了漂亮的蝴蝶!回家后可以和爸爸妈妈一起找找看,还有哪些动物会变形呢?',
interactionPoints: JSON.stringify([
'总结毛毛虫的成长过程',
'布置家庭延伸任务',
'预告下次活动',
]),
},
];
for (const script of scripts) {
await prisma.courseScript.upsert({
where: {
courseId_stepIndex: {
courseId: course.id,
stepIndex: script.stepIndex,
},
},
update: {},
create: {
courseId: course.id,
...script,
sortOrder: script.stepIndex,
},
});
}
console.log('创建课程脚本:', scripts.length, '个步骤');
// 8. 创建逐页配置(为绘本共读步骤添加)
const pages = [
{ pageNumber: 1, questions: '你们看到了什么?这是什么颜色的?', teacherNotes: '引导观察封面' },
{ pageNumber: 2, questions: '蛋在哪里?是谁的蛋呢?', teacherNotes: '引入故事悬念' },
{ pageNumber: 3, questions: '毛毛虫从蛋里出来了!它说了什么?', teacherNotes: '模仿毛毛虫的声音' },
{ pageNumber: 4, questions: '星期一,毛毛虫吃了什么?吃了几个?', teacherNotes: '学习星期和数字' },
{ pageNumber: 5, questions: '星期二,它又吃了什么?', teacherNotes: '继续学习星期' },
];
const readingScript = await prisma.courseScript.findFirst({
where: { courseId: course.id, stepType: 'READING' },
});
if (readingScript) {
for (const page of pages) {
await prisma.courseScriptPage.upsert({
where: {
scriptId_pageNumber: {
scriptId: readingScript.id,
pageNumber: page.pageNumber,
},
},
update: {},
create: {
scriptId: readingScript.id,
...page,
},
});
}
console.log('创建逐页配置:', pages.length, '页');
}
// 9. 创建延伸活动
const activities = [
{
name: '毛毛虫手偶制作',
domain: 'ART',
activityType: 'HANDICRAFT',
duration: 20,
onlineMaterials: JSON.stringify(['毛毛虫模板PDF', '制作视频']),
offlineMaterials: '彩纸、剪刀、胶水、眼睛贴纸',
activityGuide: '1. 准备材料\n2. 按照模板剪裁\n3. 粘贴组装\n4. 添加装饰',
objectives: JSON.stringify(['锻炼手部精细动作', '培养创造力', '巩固毛毛虫认知']),
sortOrder: 1,
},
{
name: '健康饮食分类',
domain: 'SCIENCE',
activityType: 'GAME',
duration: 15,
onlineMaterials: JSON.stringify(['食物卡片PPT']),
offlineMaterials: '食物图片卡片、分类筐',
activityGuide: '1. 展示各种食物图片\n2. 讨论健康与不健康食物\n3. 进行分类游戏',
objectives: JSON.stringify(['认识健康饮食', '学习分类', '培养健康饮食习惯']),
sortOrder: 2,
},
{
name: '蝴蝶的生命周期',
domain: 'SCIENCE',
activityType: 'EXPLORATION',
duration: 25,
onlineMaterials: JSON.stringify(['蝴蝶生长视频', '生命周期图']),
offlineMaterials: '绘本、放大镜、观察记录本',
activityGuide: '1. 观看蝴蝶生长视频\n2. 讨论四个阶段\n3. 绘制生命周期图',
objectives: JSON.stringify(['了解变态发育', '培养科学探究精神', '学习观察记录']),
sortOrder: 3,
},
];
for (const activity of activities) {
await prisma.courseActivity.upsert({
where: { id: activities.indexOf(activity) + 1 },
update: {},
create: {
courseId: course.id,
...activity,
},
});
}
console.log('创建延伸活动:', activities.length, '个');
// 10. 为租户授权课程
const tenantCourse = await prisma.tenantCourse.upsert({
where: {
tenantId_courseId: {
tenantId: tenant.id,
courseId: course.id,
},
},
update: {},
create: {
tenantId: tenant.id,
courseId: course.id,
authorized: true,
authorizedAt: new Date(),
},
});
console.log('授权课程给租户:', tenant.id, '->', course.id);
// 11. 创建第二个示例课程
const course2 = await prisma.course.upsert({
where: { id: 2 },
update: {},
create: {
name: '猜猜我有多爱你',
description: '这是一本关于爱的温暖绘本,小兔子和大兔子用各种方式表达彼此的爱。通过这个故事,孩子们可以学习到表达爱的方式,感受亲情的温暖。',
pictureBookName: '猜猜我有多爱你',
gradeTags: JSON.stringify(['MIDDLE', 'BIG']),
domainTags: JSON.stringify(['LANGUAGE', 'SOCIAL']),
duration: 25,
status: 'PUBLISHED',
version: '1.0',
coverImagePath: '/uploads/covers/love.jpg',
},
});
console.log('创建课程:', course2.name);
// 为第二个课程创建简化脚本
const scripts2 = [
{
stepIndex: 1,
stepName: '导入环节',
stepType: 'INTRODUCTION',
duration: 3,
objective: '引入爱的主题',
teacherScript: '小朋友们,你们爱爸爸妈妈吗?你们是怎么表达爱的呢?',
interactionPoints: JSON.stringify(['分享表达爱的方式']),
},
{
stepIndex: 2,
stepName: '绘本共读',
stepType: 'READING',
duration: 10,
objective: '理解故事,感受爱的表达',
teacherScript: '小栗色兔子该上床睡觉了,可是他紧紧地抓住大栗色兔子的长耳朵不放...',
interactionPoints: JSON.stringify(['模仿动作', '感受爱的比较']),
},
{
stepIndex: 3,
stepName: '情感讨论',
stepType: 'DISCUSSION',
duration: 5,
objective: '表达自己的感受',
teacherScript: '小兔子和大兔子谁的爱更多呢?你们觉得呢?',
interactionPoints: JSON.stringify(['讨论爱的深度', '分享感受']),
},
{
stepIndex: 4,
stepName: '爱的表达',
stepType: 'ACTIVITY',
duration: 5,
objective: '学会表达爱',
teacherScript: '让我们也来学学小兔子,用手臂来量量我们有多爱爸爸妈妈!',
interactionPoints: JSON.stringify(['肢体表达', '语言表达']),
},
];
for (const script of scripts2) {
await prisma.courseScript.upsert({
where: {
courseId_stepIndex: {
courseId: course2.id,
stepIndex: script.stepIndex,
},
},
update: {},
create: {
courseId: course2.id,
...script,
sortOrder: script.stepIndex,
},
});
}
// 授权第二个课程
await prisma.tenantCourse.upsert({
where: {
tenantId_courseId: {
tenantId: tenant.id,
courseId: course2.id,
},
},
update: {},
create: {
tenantId: tenant.id,
courseId: course2.id,
authorized: true,
authorizedAt: new Date(),
},
});
console.log('授权课程给租户:', tenant.id, '->', course2.id);
console.log('\n种子数据创建完成');
console.log('====================');
console.log('测试账号信息:');
console.log('超管: admin / 123456');
console.log('教师: teacher1 / 123456');
console.log('====================');
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});