432 lines
13 KiB
TypeScript
432 lines
13 KiB
TypeScript
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();
|
||
});
|