add
This commit is contained in:
parent
6d14e4ecdc
commit
7047445c52
|
@ -98,11 +98,10 @@ export class PostService extends BaseTreeService<Prisma.PostDelegate> {
|
|||
async createCourse(
|
||||
args: {
|
||||
courseDetail: Prisma.PostCreateArgs;
|
||||
sections?: z.infer<typeof CourseMethodSchema.createSection>[];
|
||||
},
|
||||
params: { staff?: UserProfile; tx?: Prisma.TransactionClient },
|
||||
) {
|
||||
const { courseDetail, sections } = args;
|
||||
const { courseDetail } = args;
|
||||
// If no transaction is provided, create a new one
|
||||
if (!params.tx) {
|
||||
return await db.$transaction(async (tx) => {
|
||||
|
@ -112,20 +111,6 @@ export class PostService extends BaseTreeService<Prisma.PostDelegate> {
|
|||
console.log('courseDetail', courseDetail);
|
||||
const createdCourse = await this.create(courseDetail, courseParams);
|
||||
// If sections are provided, create them
|
||||
if (sections && sections.length > 0) {
|
||||
const sectionPromises = sections.map((section) =>
|
||||
this.createSection(
|
||||
{
|
||||
courseId: createdCourse.id,
|
||||
title: section.title,
|
||||
lectures: section.lectures,
|
||||
},
|
||||
courseParams,
|
||||
),
|
||||
);
|
||||
// Create all sections (and their lectures) in parallel
|
||||
await Promise.all(sectionPromises);
|
||||
}
|
||||
return createdCourse;
|
||||
});
|
||||
}
|
||||
|
@ -133,21 +118,6 @@ export class PostService extends BaseTreeService<Prisma.PostDelegate> {
|
|||
console.log('courseDetail', courseDetail);
|
||||
const createdCourse = await this.create(courseDetail, params);
|
||||
// If sections are provided, create them
|
||||
if (sections && sections.length > 0) {
|
||||
const sectionPromises = sections.map((section) =>
|
||||
this.createSection(
|
||||
{
|
||||
courseId: createdCourse.id,
|
||||
title: section.title,
|
||||
lectures: section.lectures,
|
||||
},
|
||||
params,
|
||||
),
|
||||
);
|
||||
// Create all sections (and their lectures) in parallel
|
||||
await Promise.all(sectionPromises);
|
||||
}
|
||||
|
||||
return createdCourse;
|
||||
}
|
||||
async create(
|
||||
|
|
|
@ -161,12 +161,12 @@ export async function setCourseInfo({ data }: { data: Post }) {
|
|||
sections.map((section) => section.id).includes(descendant.parentId)
|
||||
);
|
||||
});
|
||||
|
||||
const lectureCount = lectures?.length || 0;
|
||||
sections.forEach((section) => {
|
||||
section.lectures = lectures.filter(
|
||||
(lecture) => lecture.parentId === section.id,
|
||||
);
|
||||
});
|
||||
Object.assign(data, { sections });
|
||||
Object.assign(data, { sections, lectureCount });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ export class GenDevService {
|
|||
await this.generateDepartments(3, 6);
|
||||
await this.generateTerms(2, 6);
|
||||
await this.generateStaffs(4);
|
||||
await this.generateCourses();
|
||||
} catch (err) {
|
||||
this.logger.error(err);
|
||||
}
|
||||
|
@ -142,6 +143,64 @@ export class GenDevService {
|
|||
collectChildren(domainId);
|
||||
return children;
|
||||
}
|
||||
private async generateCourses(countPerCate: number = 3) {
|
||||
const titleList = [
|
||||
'计算机科学导论',
|
||||
'数据结构与算法',
|
||||
'网络安全',
|
||||
'机器学习',
|
||||
'数据库管理系统',
|
||||
'Web开发',
|
||||
'移动应用开发',
|
||||
'人工智能',
|
||||
'计算机网络',
|
||||
'操作系统',
|
||||
'数字信号处理',
|
||||
'无线通信',
|
||||
'信息论',
|
||||
'密码学',
|
||||
'计算机图形学',
|
||||
];
|
||||
|
||||
if (!this.counts.courseCount) {
|
||||
this.logger.log('Generating courses...');
|
||||
const depts = await db.department.findMany({
|
||||
select: { id: true, name: true },
|
||||
});
|
||||
const cates = await db.term.findMany({
|
||||
where: {
|
||||
taxonomy: { slug: TaxonomySlug.CATEGORY },
|
||||
},
|
||||
select: { id: true, name: true },
|
||||
});
|
||||
const total = cates.length * countPerCate;
|
||||
const levels = await db.term.findMany({
|
||||
where: {
|
||||
taxonomy: { slug: TaxonomySlug.LEVEL },
|
||||
},
|
||||
select: { id: true, name: true },
|
||||
});
|
||||
for (const cate of cates) {
|
||||
for (let i = 0; i < countPerCate; i++) {
|
||||
const randomTitle = `${titleList[Math.floor(Math.random() * titleList.length)]} ${Math.random().toString(36).substring(7)}`;
|
||||
const randomLevelId =
|
||||
levels[Math.floor(Math.random() * levels.length)].id;
|
||||
const randomDeptId =
|
||||
depts[Math.floor(Math.random() * depts.length)].id;
|
||||
|
||||
await this.createCourse(
|
||||
randomTitle,
|
||||
randomDeptId,
|
||||
cate.id,
|
||||
randomLevelId,
|
||||
);
|
||||
this.logger.log(
|
||||
`Generated ${this.deptGeneratedCount}/${total} departments`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private async generateStaffs(countPerDept: number = 3) {
|
||||
if (this.counts.staffCount === 1) {
|
||||
this.logger.log('Generating staffs...');
|
||||
|
@ -214,16 +273,19 @@ export class GenDevService {
|
|||
type: PostType.COURSE,
|
||||
title: title,
|
||||
updatedAt: dayjs().toDate(),
|
||||
// depts: {
|
||||
// connect: {
|
||||
// id: deptId,
|
||||
// },
|
||||
// },
|
||||
// terms:{
|
||||
// connect:[cateId,levelId].map
|
||||
// }
|
||||
depts: {
|
||||
connect: {
|
||||
id: deptId,
|
||||
},
|
||||
},
|
||||
terms: {
|
||||
connect: [cateId, levelId].map((id) => ({
|
||||
id: id,
|
||||
})),
|
||||
},
|
||||
},
|
||||
});
|
||||
return course;
|
||||
}
|
||||
private async createDepartment(
|
||||
name: string,
|
||||
|
|
|
@ -1,34 +1,44 @@
|
|||
import { db, getRandomElement, getRandomIntInRange, getRandomTimeInterval, } from '@nice/common';
|
||||
import {
|
||||
db,
|
||||
getRandomElement,
|
||||
getRandomIntInRange,
|
||||
getRandomTimeInterval,
|
||||
PostType,
|
||||
} from '@nice/common';
|
||||
import dayjs from 'dayjs';
|
||||
export interface DevDataCounts {
|
||||
deptCount: number;
|
||||
deptCount: number;
|
||||
|
||||
staffCount: number
|
||||
termCount: number
|
||||
staffCount: number;
|
||||
termCount: number;
|
||||
courseCount: number;
|
||||
}
|
||||
export async function getCounts(): Promise<DevDataCounts> {
|
||||
const counts = {
|
||||
deptCount: await db.department.count(),
|
||||
const counts = {
|
||||
deptCount: await db.department.count(),
|
||||
|
||||
staffCount: await db.staff.count(),
|
||||
termCount: await db.term.count(),
|
||||
};
|
||||
return counts;
|
||||
staffCount: await db.staff.count(),
|
||||
termCount: await db.term.count(),
|
||||
courseCount: await db.post.count({
|
||||
where: {
|
||||
type: PostType.COURSE,
|
||||
},
|
||||
}),
|
||||
};
|
||||
return counts;
|
||||
}
|
||||
export function capitalizeFirstLetter(string: string) {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
}
|
||||
export function getRandomImageLinks(count: number = 5): string[] {
|
||||
const baseUrl = 'https://picsum.photos/200/300?random=';
|
||||
const imageLinks: string[] = [];
|
||||
const baseUrl = 'https://picsum.photos/200/300?random=';
|
||||
const imageLinks: string[] = [];
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
// 生成随机数以确保每个链接都是唯一的
|
||||
const randomId = Math.floor(Math.random() * 1000);
|
||||
imageLinks.push(`${baseUrl}${randomId}`);
|
||||
}
|
||||
for (let i = 0; i < count; i++) {
|
||||
// 生成随机数以确保每个链接都是唯一的
|
||||
const randomId = Math.floor(Math.random() * 1000);
|
||||
imageLinks.push(`${baseUrl}${randomId}`);
|
||||
}
|
||||
|
||||
return imageLinks;
|
||||
return imageLinks;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ import { CourseContentFormHeader } from "./CourseContentFormHeader";
|
|||
import { CourseSectionEmpty } from "./CourseSectionEmpty";
|
||||
import { SortableSection } from "./SortableSection";
|
||||
import { LectureList } from "./LectureList";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
const CourseContentForm: React.FC = () => {
|
||||
const { editId } = useCourseEditor();
|
||||
|
@ -110,10 +111,11 @@ const CourseContentForm: React.FC = () => {
|
|||
icon={<PlusOutlined />}
|
||||
className="mt-4"
|
||||
onClick={() => {
|
||||
setItems([
|
||||
...items.filter((item) => !!item.id),
|
||||
{ id: null, title: "" },
|
||||
]);
|
||||
if (items.some((item) => item.id === null)) {
|
||||
toast.error("请先保存当前编辑章节");
|
||||
} else {
|
||||
setItems([...items, { id: null, title: "" }]);
|
||||
}
|
||||
}}>
|
||||
添加章节
|
||||
</Button>
|
||||
|
|
|
@ -38,6 +38,7 @@ import { useCourseEditor } from "../../context/CourseEditorContext";
|
|||
import { usePost } from "@nice/client";
|
||||
import { LectureData, SectionData } from "./interface";
|
||||
import { SortableLecture } from "./SortableLecture";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
interface LectureListProps {
|
||||
field: SectionData;
|
||||
|
@ -135,16 +136,20 @@ export const LectureList: React.FC<LectureListProps> = ({
|
|||
icon={<PlusOutlined />}
|
||||
className="mt-4"
|
||||
onClick={() => {
|
||||
setItems((prevItems) => [
|
||||
...prevItems.filter((item) => !!item.id),
|
||||
{
|
||||
id: null,
|
||||
title: "",
|
||||
meta: {
|
||||
type: LectureType.ARTICLE,
|
||||
},
|
||||
} as Lecture,
|
||||
]);
|
||||
if (items.some((item) => item.id === null)) {
|
||||
toast.error("请先保存当前编辑章节");
|
||||
} else {
|
||||
setItems((prevItems) => [
|
||||
...prevItems.filter((item) => !!item.id),
|
||||
{
|
||||
id: null,
|
||||
title: "",
|
||||
meta: {
|
||||
type: LectureType.ARTICLE,
|
||||
},
|
||||
} as Lecture,
|
||||
]);
|
||||
}
|
||||
}}>
|
||||
添加课时
|
||||
</Button>
|
||||
|
|
|
@ -78,4 +78,5 @@ export type CourseDto = Course & {
|
|||
enrollments?: Enrollment[];
|
||||
sections?: SectionDto[];
|
||||
terms: Term[];
|
||||
lectureCount?: number;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue