系统完善
This commit is contained in:
parent
54f6daea62
commit
39b49bd808
33
.gitignore
vendored
Normal file
33
.gitignore
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
pnpm-lock.yaml
|
||||||
|
*/node_modules
|
||||||
|
*/dist/*
|
||||||
|
dist.zip
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
package-lock.json
|
||||||
|
*/package-lock.json
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
|
||||||
|
/auto-imports.d.ts
|
||||||
|
/components.d.ts
|
||||||
|
/typed-router.d.ts
|
||||||
|
/locale.d.ts
|
||||||
|
|
||||||
|
stats.html
|
||||||
@ -1,4 +1,4 @@
|
|||||||
DATABASE_URL="file:/Users/retirado/ccProgram/reading-platform-backend/dev.db"
|
DATABASE_URL="file:./dev.db"
|
||||||
NODE_ENV=development
|
NODE_ENV=development
|
||||||
PORT=3000
|
PORT=3000
|
||||||
JWT_SECRET="your-super-secret-jwt-key"
|
JWT_SECRET="your-super-secret-jwt-key"
|
||||||
|
|||||||
BIN
reading-platform-backend/dist/.DS_Store
vendored
BIN
reading-platform-backend/dist/.DS_Store
vendored
Binary file not shown.
@ -1 +0,0 @@
|
|||||||
export {};
|
|
||||||
420
reading-platform-backend/dist/prisma/seed.js
vendored
420
reading-platform-backend/dist/prisma/seed.js
vendored
@ -1,420 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
||||||
if (k2 === undefined) k2 = k;
|
|
||||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
||||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
||||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
||||||
}
|
|
||||||
Object.defineProperty(o, k2, desc);
|
|
||||||
}) : (function(o, m, k, k2) {
|
|
||||||
if (k2 === undefined) k2 = k;
|
|
||||||
o[k2] = m[k];
|
|
||||||
}));
|
|
||||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
||||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
||||||
}) : function(o, v) {
|
|
||||||
o["default"] = v;
|
|
||||||
});
|
|
||||||
var __importStar = (this && this.__importStar) || function (mod) {
|
|
||||||
if (mod && mod.__esModule) return mod;
|
|
||||||
var result = {};
|
|
||||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
||||||
__setModuleDefault(result, mod);
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
const client_1 = require("@prisma/client");
|
|
||||||
const bcrypt = __importStar(require("bcrypt"));
|
|
||||||
const prisma = new client_1.PrismaClient();
|
|
||||||
async function main() {
|
|
||||||
console.log('开始种子数据...');
|
|
||||||
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),
|
|
||||||
startDate: '2024-01-01',
|
|
||||||
expireDate: '2025-12-31',
|
|
||||||
status: 'ACTIVE',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
console.log('创建租户:', tenant.name);
|
|
||||||
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);
|
|
||||||
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);
|
|
||||||
await prisma.teacher.update({
|
|
||||||
where: { id: teacher.id },
|
|
||||||
data: {
|
|
||||||
classIds: JSON.stringify([class1.id, class2.id]),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
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, '名');
|
|
||||||
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);
|
|
||||||
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, '个步骤');
|
|
||||||
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, '页');
|
|
||||||
}
|
|
||||||
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, '个');
|
|
||||||
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);
|
|
||||||
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();
|
|
||||||
});
|
|
||||||
//# sourceMappingURL=seed.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
@ -1,2 +0,0 @@
|
|||||||
export declare class AppModule {
|
|
||||||
}
|
|
||||||
64
reading-platform-backend/dist/src/app.module.js
vendored
64
reading-platform-backend/dist/src/app.module.js
vendored
@ -1,64 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.AppModule = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const config_1 = require("@nestjs/config");
|
|
||||||
const throttler_1 = require("@nestjs/throttler");
|
|
||||||
const prisma_module_1 = require("./database/prisma.module");
|
|
||||||
const auth_module_1 = require("./modules/auth/auth.module");
|
|
||||||
const course_module_1 = require("./modules/course/course.module");
|
|
||||||
const tenant_module_1 = require("./modules/tenant/tenant.module");
|
|
||||||
const common_module_1 = require("./modules/common/common.module");
|
|
||||||
const file_upload_module_1 = require("./modules/file-upload/file-upload.module");
|
|
||||||
const teacher_course_module_1 = require("./modules/teacher-course/teacher-course.module");
|
|
||||||
const lesson_module_1 = require("./modules/lesson/lesson.module");
|
|
||||||
const school_module_1 = require("./modules/school/school.module");
|
|
||||||
const resource_module_1 = require("./modules/resource/resource.module");
|
|
||||||
const growth_module_1 = require("./modules/growth/growth.module");
|
|
||||||
const task_module_1 = require("./modules/task/task.module");
|
|
||||||
const parent_module_1 = require("./modules/parent/parent.module");
|
|
||||||
const notification_module_1 = require("./modules/notification/notification.module");
|
|
||||||
const export_module_1 = require("./modules/export/export.module");
|
|
||||||
const admin_module_1 = require("./modules/admin/admin.module");
|
|
||||||
let AppModule = class AppModule {
|
|
||||||
};
|
|
||||||
exports.AppModule = AppModule;
|
|
||||||
exports.AppModule = AppModule = __decorate([
|
|
||||||
(0, common_1.Module)({
|
|
||||||
imports: [
|
|
||||||
config_1.ConfigModule.forRoot({
|
|
||||||
isGlobal: true,
|
|
||||||
envFilePath: `.env.${process.env.NODE_ENV || 'development'}`,
|
|
||||||
}),
|
|
||||||
throttler_1.ThrottlerModule.forRoot([
|
|
||||||
{
|
|
||||||
ttl: 60000,
|
|
||||||
limit: 100,
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
prisma_module_1.PrismaModule,
|
|
||||||
auth_module_1.AuthModule,
|
|
||||||
course_module_1.CourseModule,
|
|
||||||
tenant_module_1.TenantModule,
|
|
||||||
common_module_1.CommonModule,
|
|
||||||
file_upload_module_1.FileUploadModule,
|
|
||||||
teacher_course_module_1.TeacherCourseModule,
|
|
||||||
lesson_module_1.LessonModule,
|
|
||||||
school_module_1.SchoolModule,
|
|
||||||
resource_module_1.ResourceModule,
|
|
||||||
growth_module_1.GrowthModule,
|
|
||||||
task_module_1.TaskModule,
|
|
||||||
parent_module_1.ParentModule,
|
|
||||||
notification_module_1.NotificationModule,
|
|
||||||
export_module_1.ExportModule,
|
|
||||||
admin_module_1.AdminModule,
|
|
||||||
],
|
|
||||||
})
|
|
||||||
], AppModule);
|
|
||||||
//# sourceMappingURL=app.module.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"app.module.js","sourceRoot":"","sources":["../../src/app.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,2CAA6D;AAC7D,iDAAoD;AACpD,4DAAwD;AACxD,4DAAwD;AACxD,kEAA8D;AAC9D,kEAA8D;AAC9D,kEAA8D;AAC9D,iFAA4E;AAC5E,0FAAqF;AACrF,kEAA8D;AAC9D,kEAA8D;AAC9D,wEAAoE;AACpE,kEAA8D;AAC9D,4DAAwD;AACxD,kEAA8D;AAC9D,oFAAgF;AAChF,kEAA8D;AAC9D,+DAA2D;AAuCpD,IAAM,SAAS,GAAf,MAAM,SAAS;CAAG,CAAA;AAAZ,8BAAS;oBAAT,SAAS;IArCrB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YAEP,qBAAY,CAAC,OAAO,CAAC;gBACnB,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE,QAAQ,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,aAAa,EAAE;aAC7D,CAAC;YAGF,2BAAe,CAAC,OAAO,CAAC;gBACtB;oBACE,GAAG,EAAE,KAAK;oBACV,KAAK,EAAE,GAAG;iBACX;aACF,CAAC;YAGF,4BAAY;YAGZ,wBAAU;YACV,4BAAY;YACZ,4BAAY;YACZ,4BAAY;YACZ,qCAAgB;YAChB,2CAAmB;YACnB,4BAAY;YACZ,4BAAY;YACZ,gCAAc;YACd,4BAAY;YACZ,wBAAU;YACV,4BAAY;YACZ,wCAAkB;YAClB,4BAAY;YACZ,0BAAW;SACZ;KACF,CAAC;GACW,SAAS,CAAG"}
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
import { ExceptionFilter, ArgumentsHost } from '@nestjs/common';
|
|
||||||
export declare class HttpExceptionFilter implements ExceptionFilter {
|
|
||||||
private readonly logger;
|
|
||||||
catch(exception: unknown, host: ArgumentsHost): void;
|
|
||||||
}
|
|
||||||
@ -1,70 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
||||||
if (k2 === undefined) k2 = k;
|
|
||||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
||||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
||||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
||||||
}
|
|
||||||
Object.defineProperty(o, k2, desc);
|
|
||||||
}) : (function(o, m, k, k2) {
|
|
||||||
if (k2 === undefined) k2 = k;
|
|
||||||
o[k2] = m[k];
|
|
||||||
}));
|
|
||||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
||||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
||||||
}) : function(o, v) {
|
|
||||||
o["default"] = v;
|
|
||||||
});
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
var __importStar = (this && this.__importStar) || function (mod) {
|
|
||||||
if (mod && mod.__esModule) return mod;
|
|
||||||
var result = {};
|
|
||||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
||||||
__setModuleDefault(result, mod);
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
var HttpExceptionFilter_1;
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.HttpExceptionFilter = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const fs = __importStar(require("fs"));
|
|
||||||
const path = __importStar(require("path"));
|
|
||||||
let HttpExceptionFilter = HttpExceptionFilter_1 = class HttpExceptionFilter {
|
|
||||||
constructor() {
|
|
||||||
this.logger = new common_1.Logger(HttpExceptionFilter_1.name);
|
|
||||||
}
|
|
||||||
catch(exception, host) {
|
|
||||||
const ctx = host.switchToHttp();
|
|
||||||
const response = ctx.getResponse();
|
|
||||||
const request = ctx.getRequest();
|
|
||||||
const status = exception instanceof common_1.HttpException
|
|
||||||
? exception.getStatus()
|
|
||||||
: common_1.HttpStatus.INTERNAL_SERVER_ERROR;
|
|
||||||
const message = exception instanceof common_1.HttpException
|
|
||||||
? exception.getResponse()
|
|
||||||
: { message: 'Internal server error', statusCode: 500 };
|
|
||||||
const errorLog = {
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
path: request.url,
|
|
||||||
method: request.method,
|
|
||||||
body: request.body,
|
|
||||||
status,
|
|
||||||
exception: exception instanceof Error ? exception.message : String(exception),
|
|
||||||
stack: exception instanceof Error ? exception.stack : undefined,
|
|
||||||
};
|
|
||||||
const logPath = path.join(process.cwd(), 'error.log');
|
|
||||||
fs.appendFileSync(logPath, JSON.stringify(errorLog, null, 2) + '\n');
|
|
||||||
this.logger.error('Exception caught', errorLog);
|
|
||||||
response.status(status).json(message);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.HttpExceptionFilter = HttpExceptionFilter;
|
|
||||||
exports.HttpExceptionFilter = HttpExceptionFilter = HttpExceptionFilter_1 = __decorate([
|
|
||||||
(0, common_1.Catch)()
|
|
||||||
], HttpExceptionFilter);
|
|
||||||
//# sourceMappingURL=http-exception.filter.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"http-exception.filter.js","sourceRoot":"","sources":["../../../../src/common/filters/http-exception.filter.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAA0G;AAE1G,uCAAyB;AACzB,2CAA6B;AAGtB,IAAM,mBAAmB,2BAAzB,MAAM,mBAAmB;IAAzB;QACY,WAAM,GAAG,IAAI,eAAM,CAAC,qBAAmB,CAAC,IAAI,CAAC,CAAC;IAoCjE,CAAC;IAlCC,KAAK,CAAC,SAAkB,EAAE,IAAmB;QAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,EAAY,CAAC;QAC7C,MAAM,OAAO,GAAG,GAAG,CAAC,UAAU,EAAW,CAAC;QAE1C,MAAM,MAAM,GACV,SAAS,YAAY,sBAAa;YAChC,CAAC,CAAC,SAAS,CAAC,SAAS,EAAE;YACvB,CAAC,CAAC,mBAAU,CAAC,qBAAqB,CAAC;QAEvC,MAAM,OAAO,GACX,SAAS,YAAY,sBAAa;YAChC,CAAC,CAAC,SAAS,CAAC,WAAW,EAAE;YACzB,CAAC,CAAC,EAAE,OAAO,EAAE,uBAAuB,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC;QAE5D,MAAM,QAAQ,GAAG;YACf,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,IAAI,EAAE,OAAO,CAAC,GAAG;YACjB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,MAAM;YACN,SAAS,EAAE,SAAS,YAAY,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC;YAC7E,KAAK,EAAE,SAAS,YAAY,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;SAChE,CAAC;QAGF,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC;QACtD,EAAE,CAAC,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAGrE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;QAEhD,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;CACF,CAAA;AArCY,kDAAmB;8BAAnB,mBAAmB;IAD/B,IAAA,cAAK,GAAE;GACK,mBAAmB,CAqC/B"}
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
export declare class PrismaModule {
|
|
||||||
}
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.PrismaModule = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const prisma_service_1 = require("./prisma.service");
|
|
||||||
let PrismaModule = class PrismaModule {
|
|
||||||
};
|
|
||||||
exports.PrismaModule = PrismaModule;
|
|
||||||
exports.PrismaModule = PrismaModule = __decorate([
|
|
||||||
(0, common_1.Global)(),
|
|
||||||
(0, common_1.Module)({
|
|
||||||
providers: [prisma_service_1.PrismaService],
|
|
||||||
exports: [prisma_service_1.PrismaService],
|
|
||||||
})
|
|
||||||
], PrismaModule);
|
|
||||||
//# sourceMappingURL=prisma.module.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"prisma.module.js","sourceRoot":"","sources":["../../../src/database/prisma.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAgD;AAChD,qDAAiD;AAO1C,IAAM,YAAY,GAAlB,MAAM,YAAY;CAAG,CAAA;AAAf,oCAAY;uBAAZ,YAAY;IALxB,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC;QACN,SAAS,EAAE,CAAC,8BAAa,CAAC;QAC1B,OAAO,EAAE,CAAC,8BAAa,CAAC;KACzB,CAAC;GACW,YAAY,CAAG"}
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
import { OnModuleInit, OnModuleDestroy } from '@nestjs/common';
|
|
||||||
import { PrismaClient } from '@prisma/client';
|
|
||||||
export declare class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
|
|
||||||
onModuleInit(): Promise<void>;
|
|
||||||
onModuleDestroy(): Promise<void>;
|
|
||||||
cleanDatabase(): Promise<void>;
|
|
||||||
}
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.PrismaService = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const client_1 = require("@prisma/client");
|
|
||||||
let PrismaService = class PrismaService extends client_1.PrismaClient {
|
|
||||||
async onModuleInit() {
|
|
||||||
await this.$connect();
|
|
||||||
console.log('✅ Database connected successfully');
|
|
||||||
}
|
|
||||||
async onModuleDestroy() {
|
|
||||||
await this.$disconnect();
|
|
||||||
console.log('👋 Database disconnected');
|
|
||||||
}
|
|
||||||
async cleanDatabase() {
|
|
||||||
if (process.env.NODE_ENV === 'production') {
|
|
||||||
throw new Error('Cannot clean database in production');
|
|
||||||
}
|
|
||||||
await this.studentRecord.deleteMany();
|
|
||||||
await this.lessonFeedback.deleteMany();
|
|
||||||
await this.lesson.deleteMany();
|
|
||||||
await this.tenantCourse.deleteMany();
|
|
||||||
await this.courseScriptPage.deleteMany();
|
|
||||||
await this.courseScript.deleteMany();
|
|
||||||
await this.courseActivity.deleteMany();
|
|
||||||
await this.courseResource.deleteMany();
|
|
||||||
await this.course.deleteMany();
|
|
||||||
await this.student.deleteMany();
|
|
||||||
await this.class.deleteMany();
|
|
||||||
await this.teacher.deleteMany();
|
|
||||||
await this.tenant.deleteMany();
|
|
||||||
await this.tag.deleteMany();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.PrismaService = PrismaService;
|
|
||||||
exports.PrismaService = PrismaService = __decorate([
|
|
||||||
(0, common_1.Injectable)()
|
|
||||||
], PrismaService);
|
|
||||||
//# sourceMappingURL=prisma.service.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"prisma.service.js","sourceRoot":"","sources":["../../../src/database/prisma.service.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAA2E;AAC3E,2CAA8C;AAGvC,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,qBAAY;IAC7C,KAAK,CAAC,YAAY;QAChB,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;IAC1C,CAAC;IAGD,KAAK,CAAC,aAAa;QACjB,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACzD,CAAC;QAGD,MAAM,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,CAAC;QACtC,MAAM,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE,CAAC;QACvC,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QAC/B,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,CAAC;QACrC,MAAM,IAAI,CAAC,gBAAgB,CAAC,UAAU,EAAE,CAAC;QACzC,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,CAAC;QACrC,MAAM,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE,CAAC;QACvC,MAAM,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE,CAAC;QACvC,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QAC/B,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QAChC,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;QAC9B,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QAChC,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QAC/B,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;IAC9B,CAAC;CACF,CAAA;AAjCY,sCAAa;wBAAb,aAAa;IADzB,IAAA,mBAAU,GAAE;GACA,aAAa,CAiCzB"}
|
|
||||||
1
reading-platform-backend/dist/src/main.d.ts
vendored
1
reading-platform-backend/dist/src/main.d.ts
vendored
@ -1 +0,0 @@
|
|||||||
export {};
|
|
||||||
51
reading-platform-backend/dist/src/main.js
vendored
51
reading-platform-backend/dist/src/main.js
vendored
@ -1,51 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
const core_1 = require("@nestjs/core");
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const config_1 = require("@nestjs/config");
|
|
||||||
const path_1 = require("path");
|
|
||||||
const app_module_1 = require("./app.module");
|
|
||||||
const http_exception_filter_1 = require("./common/filters/http-exception.filter");
|
|
||||||
async function bootstrap() {
|
|
||||||
const app = await core_1.NestFactory.create(app_module_1.AppModule, {
|
|
||||||
logger: ['error', 'warn', 'log', 'debug', 'verbose'],
|
|
||||||
});
|
|
||||||
app.useBodyParser('json', { limit: '1500mb' });
|
|
||||||
app.useBodyParser('urlencoded', { limit: '1500mb', extended: true });
|
|
||||||
const configService = app.get(config_1.ConfigService);
|
|
||||||
app.useGlobalPipes(new common_1.ValidationPipe({
|
|
||||||
whitelist: true,
|
|
||||||
forbidNonWhitelisted: true,
|
|
||||||
transform: true,
|
|
||||||
transformOptions: {
|
|
||||||
enableImplicitConversion: true,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
app.useGlobalFilters(new http_exception_filter_1.HttpExceptionFilter());
|
|
||||||
app.enableCors({
|
|
||||||
origin: configService.get('FRONTEND_URL') || 'http://localhost:5173',
|
|
||||||
credentials: true,
|
|
||||||
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
|
|
||||||
allowedHeaders: 'Content-Type, Accept, Authorization',
|
|
||||||
});
|
|
||||||
const uploadsPath = (0, path_1.join)(__dirname, '..', '..', 'uploads');
|
|
||||||
app.useStaticAssets(uploadsPath, {
|
|
||||||
prefix: '/uploads/',
|
|
||||||
});
|
|
||||||
app.setGlobalPrefix('api/v1');
|
|
||||||
const port = configService.get('PORT') || 3000;
|
|
||||||
await app.listen(port);
|
|
||||||
console.log(`
|
|
||||||
╔═════════════════════════════════════════════════════╗
|
|
||||||
║ ║
|
|
||||||
║ 🚀 幼儿阅读教学服务平台后端启动成功 ║
|
|
||||||
║ ║
|
|
||||||
║ 📍 Local: http://localhost:${port} ║
|
|
||||||
║ 📍 API: http://localhost:${port}/api/v1 ║
|
|
||||||
║ 📍 Prisma: npx prisma studio ║
|
|
||||||
║ ║
|
|
||||||
╚═════════════════════════════════════════════════════╝
|
|
||||||
`);
|
|
||||||
}
|
|
||||||
bootstrap();
|
|
||||||
//# sourceMappingURL=main.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/main.ts"],"names":[],"mappings":";;AAAA,uCAA2C;AAC3C,2CAAwD;AACxD,2CAA+C;AAE/C,+BAA4B;AAC5B,6CAAyC;AAEzC,kFAA6E;AAE7E,KAAK,UAAU,SAAS;IACtB,MAAM,GAAG,GAAG,MAAM,kBAAW,CAAC,MAAM,CAAyB,sBAAS,EAAE;QACtE,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,CAAC;KACrD,CAAC,CAAC;IAIH,GAAG,CAAC,aAAa,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC/C,GAAG,CAAC,aAAa,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAErE,MAAM,aAAa,GAAG,GAAG,CAAC,GAAG,CAAC,sBAAa,CAAC,CAAC;IAG7C,GAAG,CAAC,cAAc,CAChB,IAAI,uBAAc,CAAC;QACjB,SAAS,EAAE,IAAI;QACf,oBAAoB,EAAE,IAAI;QAC1B,SAAS,EAAE,IAAI;QACf,gBAAgB,EAAE;YAChB,wBAAwB,EAAE,IAAI;SAC/B;KACF,CAAC,CACH,CAAC;IAGF,GAAG,CAAC,gBAAgB,CAAC,IAAI,2CAAmB,EAAE,CAAC,CAAC;IAMhD,GAAG,CAAC,UAAU,CAAC;QACb,MAAM,EAAE,aAAa,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,uBAAuB;QACpE,WAAW,EAAE,IAAI;QACjB,OAAO,EAAE,wCAAwC;QACjD,cAAc,EAAE,qCAAqC;KACtD,CAAC,CAAC;IAIH,MAAM,WAAW,GAAG,IAAA,WAAI,EAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAC3D,GAAG,CAAC,eAAe,CAAC,WAAW,EAAE;QAC/B,MAAM,EAAE,WAAW;KACpB,CAAC,CAAC;IAGH,GAAG,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IAE9B,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAS,MAAM,CAAC,IAAI,IAAI,CAAC;IACvD,MAAM,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAEvB,OAAO,CAAC,GAAG,CAAC;;;;;yCAK2B,IAAI;yCACJ,IAAI;;;;GAI1C,CAAC,CAAC;AACL,CAAC;AAED,SAAS,EAAE,CAAC"}
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
import { AdminSettingsService } from './admin-settings.service';
|
|
||||||
export declare class AdminSettingsController {
|
|
||||||
private readonly settingsService;
|
|
||||||
constructor(settingsService: AdminSettingsService);
|
|
||||||
getAllSettings(): Promise<{
|
|
||||||
[x: string]: any;
|
|
||||||
}>;
|
|
||||||
updateSettings(data: Record<string, any>): Promise<{
|
|
||||||
[x: string]: any;
|
|
||||||
}>;
|
|
||||||
getBasicSettings(): Promise<{
|
|
||||||
systemName: any;
|
|
||||||
systemDesc: any;
|
|
||||||
contactPhone: any;
|
|
||||||
contactEmail: any;
|
|
||||||
systemLogo: any;
|
|
||||||
}>;
|
|
||||||
updateBasicSettings(data: Record<string, any>): Promise<{
|
|
||||||
[x: string]: any;
|
|
||||||
}>;
|
|
||||||
getSecuritySettings(): Promise<{
|
|
||||||
passwordStrength: any;
|
|
||||||
maxLoginAttempts: any;
|
|
||||||
tokenExpire: any;
|
|
||||||
forceHttps: any;
|
|
||||||
}>;
|
|
||||||
updateSecuritySettings(data: Record<string, any>): Promise<{
|
|
||||||
[x: string]: any;
|
|
||||||
}>;
|
|
||||||
getNotificationSettings(): Promise<{
|
|
||||||
emailEnabled: any;
|
|
||||||
smtpHost: any;
|
|
||||||
smtpPort: any;
|
|
||||||
fromEmail: any;
|
|
||||||
smsEnabled: any;
|
|
||||||
}>;
|
|
||||||
updateNotificationSettings(data: Record<string, any>): Promise<{
|
|
||||||
[x: string]: any;
|
|
||||||
}>;
|
|
||||||
getStorageSettings(): Promise<{
|
|
||||||
type: any;
|
|
||||||
maxFileSize: any;
|
|
||||||
allowedTypes: any;
|
|
||||||
}>;
|
|
||||||
updateStorageSettings(data: Record<string, any>): Promise<{
|
|
||||||
[x: string]: any;
|
|
||||||
}>;
|
|
||||||
getTenantDefaults(): Promise<{
|
|
||||||
defaultTeacherQuota: any;
|
|
||||||
defaultStudentQuota: any;
|
|
||||||
enableAutoExpire: any;
|
|
||||||
notifyBeforeDays: any;
|
|
||||||
}>;
|
|
||||||
}
|
|
||||||
@ -1,137 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
||||||
};
|
|
||||||
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
||||||
return function (target, key) { decorator(target, key, paramIndex); }
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.AdminSettingsController = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const admin_settings_service_1 = require("./admin-settings.service");
|
|
||||||
const jwt_auth_guard_1 = require("../common/guards/jwt-auth.guard");
|
|
||||||
const roles_guard_1 = require("../common/guards/roles.guard");
|
|
||||||
const roles_decorator_1 = require("../common/decorators/roles.decorator");
|
|
||||||
let AdminSettingsController = class AdminSettingsController {
|
|
||||||
constructor(settingsService) {
|
|
||||||
this.settingsService = settingsService;
|
|
||||||
}
|
|
||||||
async getAllSettings() {
|
|
||||||
return this.settingsService.getSettings();
|
|
||||||
}
|
|
||||||
async updateSettings(data) {
|
|
||||||
return this.settingsService.updateSettings(data);
|
|
||||||
}
|
|
||||||
async getBasicSettings() {
|
|
||||||
return this.settingsService.getBasicSettings();
|
|
||||||
}
|
|
||||||
async updateBasicSettings(data) {
|
|
||||||
return this.settingsService.updateSettings(data);
|
|
||||||
}
|
|
||||||
async getSecuritySettings() {
|
|
||||||
return this.settingsService.getSecuritySettings();
|
|
||||||
}
|
|
||||||
async updateSecuritySettings(data) {
|
|
||||||
return this.settingsService.updateSettings(data);
|
|
||||||
}
|
|
||||||
async getNotificationSettings() {
|
|
||||||
return this.settingsService.getNotificationSettings();
|
|
||||||
}
|
|
||||||
async updateNotificationSettings(data) {
|
|
||||||
return this.settingsService.updateSettings(data);
|
|
||||||
}
|
|
||||||
async getStorageSettings() {
|
|
||||||
return this.settingsService.getStorageSettings();
|
|
||||||
}
|
|
||||||
async updateStorageSettings(data) {
|
|
||||||
return this.settingsService.updateSettings(data);
|
|
||||||
}
|
|
||||||
async getTenantDefaults() {
|
|
||||||
return this.settingsService.getTenantDefaults();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.AdminSettingsController = AdminSettingsController;
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)(),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", []),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], AdminSettingsController.prototype, "getAllSettings", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Put)(),
|
|
||||||
__param(0, (0, common_1.Body)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [Object]),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], AdminSettingsController.prototype, "updateSettings", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)('basic'),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", []),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], AdminSettingsController.prototype, "getBasicSettings", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Put)('basic'),
|
|
||||||
__param(0, (0, common_1.Body)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [Object]),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], AdminSettingsController.prototype, "updateBasicSettings", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)('security'),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", []),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], AdminSettingsController.prototype, "getSecuritySettings", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Put)('security'),
|
|
||||||
__param(0, (0, common_1.Body)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [Object]),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], AdminSettingsController.prototype, "updateSecuritySettings", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)('notification'),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", []),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], AdminSettingsController.prototype, "getNotificationSettings", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Put)('notification'),
|
|
||||||
__param(0, (0, common_1.Body)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [Object]),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], AdminSettingsController.prototype, "updateNotificationSettings", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)('storage'),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", []),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], AdminSettingsController.prototype, "getStorageSettings", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Put)('storage'),
|
|
||||||
__param(0, (0, common_1.Body)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [Object]),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], AdminSettingsController.prototype, "updateStorageSettings", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)('tenant-defaults'),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", []),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], AdminSettingsController.prototype, "getTenantDefaults", null);
|
|
||||||
exports.AdminSettingsController = AdminSettingsController = __decorate([
|
|
||||||
(0, common_1.Controller)('admin/settings'),
|
|
||||||
(0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard, roles_guard_1.RolesGuard),
|
|
||||||
(0, roles_decorator_1.Roles)('admin'),
|
|
||||||
__metadata("design:paramtypes", [admin_settings_service_1.AdminSettingsService])
|
|
||||||
], AdminSettingsController);
|
|
||||||
//# sourceMappingURL=admin-settings.controller.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"admin-settings.controller.js","sourceRoot":"","sources":["../../../../src/modules/admin/admin-settings.controller.ts"],"names":[],"mappings":"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"}
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
import { PrismaService } from '../../database/prisma.service';
|
|
||||||
export declare class AdminSettingsService {
|
|
||||||
private prisma;
|
|
||||||
private settings;
|
|
||||||
constructor(prisma: PrismaService);
|
|
||||||
getSettings(): Promise<{
|
|
||||||
[x: string]: any;
|
|
||||||
}>;
|
|
||||||
getSetting(key: string): Promise<any>;
|
|
||||||
updateSettings(data: Record<string, any>): Promise<{
|
|
||||||
[x: string]: any;
|
|
||||||
}>;
|
|
||||||
getBasicSettings(): Promise<{
|
|
||||||
systemName: any;
|
|
||||||
systemDesc: any;
|
|
||||||
contactPhone: any;
|
|
||||||
contactEmail: any;
|
|
||||||
systemLogo: any;
|
|
||||||
}>;
|
|
||||||
getSecuritySettings(): Promise<{
|
|
||||||
passwordStrength: any;
|
|
||||||
maxLoginAttempts: any;
|
|
||||||
tokenExpire: any;
|
|
||||||
forceHttps: any;
|
|
||||||
}>;
|
|
||||||
getNotificationSettings(): Promise<{
|
|
||||||
emailEnabled: any;
|
|
||||||
smtpHost: any;
|
|
||||||
smtpPort: any;
|
|
||||||
fromEmail: any;
|
|
||||||
smsEnabled: any;
|
|
||||||
}>;
|
|
||||||
getStorageSettings(): Promise<{
|
|
||||||
type: any;
|
|
||||||
maxFileSize: any;
|
|
||||||
allowedTypes: any;
|
|
||||||
}>;
|
|
||||||
getTenantDefaults(): Promise<{
|
|
||||||
defaultTeacherQuota: any;
|
|
||||||
defaultStudentQuota: any;
|
|
||||||
enableAutoExpire: any;
|
|
||||||
notifyBeforeDays: any;
|
|
||||||
}>;
|
|
||||||
}
|
|
||||||
@ -1,105 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.AdminSettingsService = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const prisma_service_1 = require("../../database/prisma.service");
|
|
||||||
let AdminSettingsService = class AdminSettingsService {
|
|
||||||
constructor(prisma) {
|
|
||||||
this.prisma = prisma;
|
|
||||||
this.settings = {
|
|
||||||
systemName: '幼儿阅读教学服务平台',
|
|
||||||
systemDesc: '',
|
|
||||||
contactPhone: '',
|
|
||||||
contactEmail: '',
|
|
||||||
systemLogo: '',
|
|
||||||
passwordStrength: 'medium',
|
|
||||||
maxLoginAttempts: 5,
|
|
||||||
tokenExpire: '7d',
|
|
||||||
forceHttps: false,
|
|
||||||
emailEnabled: true,
|
|
||||||
smtpHost: '',
|
|
||||||
smtpPort: 465,
|
|
||||||
smtpUser: '',
|
|
||||||
smtpPassword: '',
|
|
||||||
fromEmail: '',
|
|
||||||
smsEnabled: false,
|
|
||||||
storageType: 'local',
|
|
||||||
maxFileSize: 100,
|
|
||||||
allowedTypes: '.jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.ppt,.pptx',
|
|
||||||
defaultTeacherQuota: 20,
|
|
||||||
defaultStudentQuota: 200,
|
|
||||||
enableAutoExpire: true,
|
|
||||||
notifyBeforeDays: 30,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
async getSettings() {
|
|
||||||
return { ...this.settings };
|
|
||||||
}
|
|
||||||
async getSetting(key) {
|
|
||||||
return this.settings[key];
|
|
||||||
}
|
|
||||||
async updateSettings(data) {
|
|
||||||
for (const key of Object.keys(data)) {
|
|
||||||
if (key in this.settings) {
|
|
||||||
this.settings[key] = data[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return { ...this.settings };
|
|
||||||
}
|
|
||||||
async getBasicSettings() {
|
|
||||||
return {
|
|
||||||
systemName: this.settings.systemName,
|
|
||||||
systemDesc: this.settings.systemDesc,
|
|
||||||
contactPhone: this.settings.contactPhone,
|
|
||||||
contactEmail: this.settings.contactEmail,
|
|
||||||
systemLogo: this.settings.systemLogo,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
async getSecuritySettings() {
|
|
||||||
return {
|
|
||||||
passwordStrength: this.settings.passwordStrength,
|
|
||||||
maxLoginAttempts: this.settings.maxLoginAttempts,
|
|
||||||
tokenExpire: this.settings.tokenExpire,
|
|
||||||
forceHttps: this.settings.forceHttps,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
async getNotificationSettings() {
|
|
||||||
return {
|
|
||||||
emailEnabled: this.settings.emailEnabled,
|
|
||||||
smtpHost: this.settings.smtpHost,
|
|
||||||
smtpPort: this.settings.smtpPort,
|
|
||||||
fromEmail: this.settings.fromEmail,
|
|
||||||
smsEnabled: this.settings.smsEnabled,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
async getStorageSettings() {
|
|
||||||
return {
|
|
||||||
type: this.settings.storageType,
|
|
||||||
maxFileSize: this.settings.maxFileSize,
|
|
||||||
allowedTypes: this.settings.allowedTypes,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
async getTenantDefaults() {
|
|
||||||
return {
|
|
||||||
defaultTeacherQuota: this.settings.defaultTeacherQuota,
|
|
||||||
defaultStudentQuota: this.settings.defaultStudentQuota,
|
|
||||||
enableAutoExpire: this.settings.enableAutoExpire,
|
|
||||||
notifyBeforeDays: this.settings.notifyBeforeDays,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.AdminSettingsService = AdminSettingsService;
|
|
||||||
exports.AdminSettingsService = AdminSettingsService = __decorate([
|
|
||||||
(0, common_1.Injectable)(),
|
|
||||||
__metadata("design:paramtypes", [prisma_service_1.PrismaService])
|
|
||||||
], AdminSettingsService);
|
|
||||||
//# sourceMappingURL=admin-settings.service.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"admin-settings.service.js","sourceRoot":"","sources":["../../../../src/modules/admin/admin-settings.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,kEAA8D;AAIvD,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IAoC/B,YAAoB,MAAqB;QAArB,WAAM,GAAN,MAAM,CAAe;QAnCjC,aAAQ,GAAwB;YAEtC,UAAU,EAAE,YAAY;YACxB,UAAU,EAAE,EAAE;YACd,YAAY,EAAE,EAAE;YAChB,YAAY,EAAE,EAAE;YAChB,UAAU,EAAE,EAAE;YAGd,gBAAgB,EAAE,QAAQ;YAC1B,gBAAgB,EAAE,CAAC;YACnB,WAAW,EAAE,IAAI;YACjB,UAAU,EAAE,KAAK;YAGjB,YAAY,EAAE,IAAI;YAClB,QAAQ,EAAE,EAAE;YACZ,QAAQ,EAAE,GAAG;YACb,QAAQ,EAAE,EAAE;YACZ,YAAY,EAAE,EAAE;YAChB,SAAS,EAAE,EAAE;YACb,UAAU,EAAE,KAAK;YAGjB,WAAW,EAAE,OAAO;YACpB,WAAW,EAAE,GAAG;YAChB,YAAY,EAAE,iDAAiD;YAG/D,mBAAmB,EAAE,EAAE;YACvB,mBAAmB,EAAE,GAAG;YACxB,gBAAgB,EAAE,IAAI;YACtB,gBAAgB,EAAE,EAAE;SACrB,CAAC;IAE0C,CAAC;IAE7C,KAAK,CAAC,WAAW;QACf,OAAO,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,GAAW;QAC1B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,IAAyB;QAE5C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,IAAI,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACzB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;QACD,OAAO,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,OAAO;YACL,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU;YACpC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU;YACpC,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY;YACxC,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY;YACxC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU;SACrC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,mBAAmB;QACvB,OAAO;YACL,gBAAgB,EAAE,IAAI,CAAC,QAAQ,CAAC,gBAAgB;YAChD,gBAAgB,EAAE,IAAI,CAAC,QAAQ,CAAC,gBAAgB;YAChD,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW;YACtC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU;SACrC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,uBAAuB;QAC3B,OAAO;YACL,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY;YACxC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ;YAChC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ;YAChC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS;YAClC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU;SACrC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW;YAC/B,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW;YACtC,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,YAAY;SACzC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,iBAAiB;QACrB,OAAO;YACL,mBAAmB,EAAE,IAAI,CAAC,QAAQ,CAAC,mBAAmB;YACtD,mBAAmB,EAAE,IAAI,CAAC,QAAQ,CAAC,mBAAmB;YACtD,gBAAgB,EAAE,IAAI,CAAC,QAAQ,CAAC,gBAAgB;YAChD,gBAAgB,EAAE,IAAI,CAAC,QAAQ,CAAC,gBAAgB;SACjD,CAAC;IACJ,CAAC;CACF,CAAA;AArGY,oDAAoB;+BAApB,oBAAoB;IADhC,IAAA,mBAAU,GAAE;qCAqCiB,8BAAa;GApC9B,oBAAoB,CAqGhC"}
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
import { AdminStatsService } from './admin-stats.service';
|
|
||||||
export declare class AdminStatsController {
|
|
||||||
private readonly statsService;
|
|
||||||
constructor(statsService: AdminStatsService);
|
|
||||||
getStats(): Promise<{
|
|
||||||
tenantCount: number;
|
|
||||||
activeTenantCount: number;
|
|
||||||
courseCount: number;
|
|
||||||
publishedCourseCount: number;
|
|
||||||
studentCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
lessonCount: number;
|
|
||||||
monthlyLessons: number;
|
|
||||||
}>;
|
|
||||||
getTrendData(): Promise<{
|
|
||||||
month: string;
|
|
||||||
tenantCount: number;
|
|
||||||
lessonCount: number;
|
|
||||||
studentCount: number;
|
|
||||||
}[]>;
|
|
||||||
getActiveTenants(limit?: string): Promise<{
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
lessonCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
studentCount: number;
|
|
||||||
}[]>;
|
|
||||||
getPopularCourses(limit?: string): Promise<{
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
}[]>;
|
|
||||||
getRecentActivities(limit?: string): Promise<{
|
|
||||||
time: string;
|
|
||||||
id: number;
|
|
||||||
type: string;
|
|
||||||
title: string;
|
|
||||||
description?: string;
|
|
||||||
}[]>;
|
|
||||||
}
|
|
||||||
@ -1,84 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
||||||
};
|
|
||||||
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
||||||
return function (target, key) { decorator(target, key, paramIndex); }
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.AdminStatsController = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const admin_stats_service_1 = require("./admin-stats.service");
|
|
||||||
const jwt_auth_guard_1 = require("../common/guards/jwt-auth.guard");
|
|
||||||
const roles_guard_1 = require("../common/guards/roles.guard");
|
|
||||||
const roles_decorator_1 = require("../common/decorators/roles.decorator");
|
|
||||||
let AdminStatsController = class AdminStatsController {
|
|
||||||
constructor(statsService) {
|
|
||||||
this.statsService = statsService;
|
|
||||||
}
|
|
||||||
async getStats() {
|
|
||||||
return this.statsService.getStats();
|
|
||||||
}
|
|
||||||
async getTrendData() {
|
|
||||||
return this.statsService.getTrendData();
|
|
||||||
}
|
|
||||||
async getActiveTenants(limit) {
|
|
||||||
const limitNum = limit ? parseInt(limit, 10) : 5;
|
|
||||||
return this.statsService.getActiveTenants(limitNum);
|
|
||||||
}
|
|
||||||
async getPopularCourses(limit) {
|
|
||||||
const limitNum = limit ? parseInt(limit, 10) : 5;
|
|
||||||
return this.statsService.getPopularCourses(limitNum);
|
|
||||||
}
|
|
||||||
async getRecentActivities(limit) {
|
|
||||||
const limitNum = limit ? parseInt(limit, 10) : 10;
|
|
||||||
return this.statsService.getRecentActivities(limitNum);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.AdminStatsController = AdminStatsController;
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)(),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", []),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], AdminStatsController.prototype, "getStats", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)('trend'),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", []),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], AdminStatsController.prototype, "getTrendData", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)('tenants/active'),
|
|
||||||
__param(0, (0, common_1.Query)('limit')),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [String]),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], AdminStatsController.prototype, "getActiveTenants", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)('courses/popular'),
|
|
||||||
__param(0, (0, common_1.Query)('limit')),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [String]),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], AdminStatsController.prototype, "getPopularCourses", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)('activities'),
|
|
||||||
__param(0, (0, common_1.Query)('limit')),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [String]),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], AdminStatsController.prototype, "getRecentActivities", null);
|
|
||||||
exports.AdminStatsController = AdminStatsController = __decorate([
|
|
||||||
(0, common_1.Controller)('admin/stats'),
|
|
||||||
(0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard, roles_guard_1.RolesGuard),
|
|
||||||
(0, roles_decorator_1.Roles)('admin'),
|
|
||||||
__metadata("design:paramtypes", [admin_stats_service_1.AdminStatsService])
|
|
||||||
], AdminStatsController);
|
|
||||||
//# sourceMappingURL=admin-stats.controller.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"admin-stats.controller.js","sourceRoot":"","sources":["../../../../src/modules/admin/admin-stats.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAmE;AACnE,+DAA0D;AAC1D,oEAA+D;AAC/D,8DAA0D;AAC1D,0EAA6D;AAKtD,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IAC/B,YAA6B,YAA+B;QAA/B,iBAAY,GAAZ,YAAY,CAAmB;IAAG,CAAC;IAG1D,AAAN,KAAK,CAAC,QAAQ;QACZ,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC;IACtC,CAAC;IAGK,AAAN,KAAK,CAAC,YAAY;QAChB,OAAO,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC;IAC1C,CAAC;IAGK,AAAN,KAAK,CAAC,gBAAgB,CAAiB,KAAc;QACnD,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACjD,OAAO,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IACtD,CAAC;IAGK,AAAN,KAAK,CAAC,iBAAiB,CAAiB,KAAc;QACpD,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACjD,OAAO,IAAI,CAAC,YAAY,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACvD,CAAC;IAGK,AAAN,KAAK,CAAC,mBAAmB,CAAiB,KAAc;QACtD,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAClD,OAAO,IAAI,CAAC,YAAY,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IACzD,CAAC;CACF,CAAA;AA9BY,oDAAoB;AAIzB;IADL,IAAA,YAAG,GAAE;;;;oDAGL;AAGK;IADL,IAAA,YAAG,EAAC,OAAO,CAAC;;;;wDAGZ;AAGK;IADL,IAAA,YAAG,EAAC,gBAAgB,CAAC;IACE,WAAA,IAAA,cAAK,EAAC,OAAO,CAAC,CAAA;;;;4DAGrC;AAGK;IADL,IAAA,YAAG,EAAC,iBAAiB,CAAC;IACE,WAAA,IAAA,cAAK,EAAC,OAAO,CAAC,CAAA;;;;6DAGtC;AAGK;IADL,IAAA,YAAG,EAAC,YAAY,CAAC;IACS,WAAA,IAAA,cAAK,EAAC,OAAO,CAAC,CAAA;;;;+DAGxC;+BA7BU,oBAAoB;IAHhC,IAAA,mBAAU,EAAC,aAAa,CAAC;IACzB,IAAA,kBAAS,EAAC,6BAAY,EAAE,wBAAU,CAAC;IACnC,IAAA,uBAAK,EAAC,OAAO,CAAC;qCAE8B,uCAAiB;GADjD,oBAAoB,CA8BhC"}
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
import { PrismaService } from '../../database/prisma.service';
|
|
||||||
export declare class AdminStatsService {
|
|
||||||
private prisma;
|
|
||||||
constructor(prisma: PrismaService);
|
|
||||||
getStats(): Promise<{
|
|
||||||
tenantCount: number;
|
|
||||||
activeTenantCount: number;
|
|
||||||
courseCount: number;
|
|
||||||
publishedCourseCount: number;
|
|
||||||
studentCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
lessonCount: number;
|
|
||||||
monthlyLessons: number;
|
|
||||||
}>;
|
|
||||||
private getThisMonthLessonCount;
|
|
||||||
getTrendData(): Promise<{
|
|
||||||
month: string;
|
|
||||||
tenantCount: number;
|
|
||||||
lessonCount: number;
|
|
||||||
studentCount: number;
|
|
||||||
}[]>;
|
|
||||||
getActiveTenants(limit?: number): Promise<{
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
lessonCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
studentCount: number;
|
|
||||||
}[]>;
|
|
||||||
getPopularCourses(limit?: number): Promise<{
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
}[]>;
|
|
||||||
getRecentActivities(limit?: number): Promise<{
|
|
||||||
time: string;
|
|
||||||
id: number;
|
|
||||||
type: string;
|
|
||||||
title: string;
|
|
||||||
description?: string;
|
|
||||||
}[]>;
|
|
||||||
}
|
|
||||||
@ -1,212 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.AdminStatsService = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const prisma_service_1 = require("../../database/prisma.service");
|
|
||||||
let AdminStatsService = class AdminStatsService {
|
|
||||||
constructor(prisma) {
|
|
||||||
this.prisma = prisma;
|
|
||||||
}
|
|
||||||
async getStats() {
|
|
||||||
const [tenantCount, activeTenantCount, courseCount, publishedCourseCount, studentCount, teacherCount, lessonCount, monthlyLessons,] = await Promise.all([
|
|
||||||
this.prisma.tenant.count(),
|
|
||||||
this.prisma.tenant.count({ where: { status: 'ACTIVE' } }),
|
|
||||||
this.prisma.course.count(),
|
|
||||||
this.prisma.course.count({ where: { status: 'PUBLISHED' } }),
|
|
||||||
this.prisma.student.count(),
|
|
||||||
this.prisma.teacher.count(),
|
|
||||||
this.prisma.lesson.count(),
|
|
||||||
this.getThisMonthLessonCount(),
|
|
||||||
]);
|
|
||||||
return {
|
|
||||||
tenantCount,
|
|
||||||
activeTenantCount,
|
|
||||||
courseCount,
|
|
||||||
publishedCourseCount,
|
|
||||||
studentCount,
|
|
||||||
teacherCount,
|
|
||||||
lessonCount,
|
|
||||||
monthlyLessons,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
async getThisMonthLessonCount() {
|
|
||||||
const now = new Date();
|
|
||||||
const firstDayOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
|
|
||||||
return this.prisma.lesson.count({
|
|
||||||
where: {
|
|
||||||
createdAt: {
|
|
||||||
gte: firstDayOfMonth,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
async getTrendData() {
|
|
||||||
const months = [];
|
|
||||||
for (let i = 5; i >= 0; i--) {
|
|
||||||
const date = new Date();
|
|
||||||
date.setMonth(date.getMonth() - i);
|
|
||||||
const year = date.getFullYear();
|
|
||||||
const month = date.getMonth() + 1;
|
|
||||||
const monthStr = `${year}-${String(month).padStart(2, '0')}`;
|
|
||||||
const firstDay = new Date(year, month - 1, 1);
|
|
||||||
const lastDay = new Date(year, month, 0, 23, 59, 59);
|
|
||||||
const [tenantCount, lessonCount, studentCount] = await Promise.all([
|
|
||||||
this.prisma.tenant.count({
|
|
||||||
where: {
|
|
||||||
createdAt: {
|
|
||||||
lte: lastDay,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
this.prisma.lesson.count({
|
|
||||||
where: {
|
|
||||||
createdAt: {
|
|
||||||
gte: firstDay,
|
|
||||||
lte: lastDay,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
this.prisma.student.count({
|
|
||||||
where: {
|
|
||||||
createdAt: {
|
|
||||||
lte: lastDay,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
]);
|
|
||||||
months.push({
|
|
||||||
month: monthStr,
|
|
||||||
tenantCount,
|
|
||||||
lessonCount,
|
|
||||||
studentCount,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return months;
|
|
||||||
}
|
|
||||||
async getActiveTenants(limit = 5) {
|
|
||||||
const thirtyDaysAgo = new Date();
|
|
||||||
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
|
|
||||||
const tenants = await this.prisma.tenant.findMany({
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
name: true,
|
|
||||||
teacherCount: true,
|
|
||||||
studentCount: true,
|
|
||||||
_count: {
|
|
||||||
select: {
|
|
||||||
lessons: {
|
|
||||||
where: {
|
|
||||||
createdAt: {
|
|
||||||
gte: thirtyDaysAgo,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
lessons: {
|
|
||||||
_count: 'desc',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
take: limit,
|
|
||||||
});
|
|
||||||
return tenants.map((t) => ({
|
|
||||||
id: t.id,
|
|
||||||
name: t.name,
|
|
||||||
lessonCount: t._count.lessons,
|
|
||||||
teacherCount: t.teacherCount,
|
|
||||||
studentCount: t.studentCount,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
async getPopularCourses(limit = 5) {
|
|
||||||
const courses = await this.prisma.course.findMany({
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
name: true,
|
|
||||||
usageCount: true,
|
|
||||||
teacherCount: true,
|
|
||||||
},
|
|
||||||
where: {
|
|
||||||
status: 'PUBLISHED',
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
usageCount: 'desc',
|
|
||||||
},
|
|
||||||
take: limit,
|
|
||||||
});
|
|
||||||
return courses;
|
|
||||||
}
|
|
||||||
async getRecentActivities(limit = 10) {
|
|
||||||
const activities = [];
|
|
||||||
const recentLessons = await this.prisma.lesson.findMany({
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
createdAt: true,
|
|
||||||
tenant: {
|
|
||||||
select: {
|
|
||||||
name: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
course: {
|
|
||||||
select: {
|
|
||||||
name: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
createdAt: 'desc',
|
|
||||||
},
|
|
||||||
take: limit,
|
|
||||||
});
|
|
||||||
for (const lesson of recentLessons) {
|
|
||||||
activities.push({
|
|
||||||
id: lesson.id,
|
|
||||||
type: 'lesson',
|
|
||||||
title: `${lesson.tenant.name} 完成了课程《${lesson.course.name}》`,
|
|
||||||
time: lesson.createdAt,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const recentTenants = await this.prisma.tenant.findMany({
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
name: true,
|
|
||||||
createdAt: true,
|
|
||||||
},
|
|
||||||
orderBy: {
|
|
||||||
createdAt: 'desc',
|
|
||||||
},
|
|
||||||
take: limit,
|
|
||||||
});
|
|
||||||
for (const tenant of recentTenants) {
|
|
||||||
activities.push({
|
|
||||||
id: tenant.id + 10000,
|
|
||||||
type: 'tenant',
|
|
||||||
title: `新租户注册: ${tenant.name}`,
|
|
||||||
time: tenant.createdAt,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return activities
|
|
||||||
.sort((a, b) => b.time.getTime() - a.time.getTime())
|
|
||||||
.slice(0, limit)
|
|
||||||
.map((a) => ({
|
|
||||||
...a,
|
|
||||||
time: a.time.toISOString(),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.AdminStatsService = AdminStatsService;
|
|
||||||
exports.AdminStatsService = AdminStatsService = __decorate([
|
|
||||||
(0, common_1.Injectable)(),
|
|
||||||
__metadata("design:paramtypes", [prisma_service_1.PrismaService])
|
|
||||||
], AdminStatsService);
|
|
||||||
//# sourceMappingURL=admin-stats.service.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
@ -1,2 +0,0 @@
|
|||||||
export declare class AdminModule {
|
|
||||||
}
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.AdminModule = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const admin_settings_controller_1 = require("./admin-settings.controller");
|
|
||||||
const admin_settings_service_1 = require("./admin-settings.service");
|
|
||||||
const admin_stats_controller_1 = require("./admin-stats.controller");
|
|
||||||
const admin_stats_service_1 = require("./admin-stats.service");
|
|
||||||
const prisma_module_1 = require("../../database/prisma.module");
|
|
||||||
let AdminModule = class AdminModule {
|
|
||||||
};
|
|
||||||
exports.AdminModule = AdminModule;
|
|
||||||
exports.AdminModule = AdminModule = __decorate([
|
|
||||||
(0, common_1.Module)({
|
|
||||||
imports: [prisma_module_1.PrismaModule],
|
|
||||||
controllers: [admin_settings_controller_1.AdminSettingsController, admin_stats_controller_1.AdminStatsController],
|
|
||||||
providers: [admin_settings_service_1.AdminSettingsService, admin_stats_service_1.AdminStatsService],
|
|
||||||
exports: [admin_settings_service_1.AdminSettingsService, admin_stats_service_1.AdminStatsService],
|
|
||||||
})
|
|
||||||
], AdminModule);
|
|
||||||
//# sourceMappingURL=admin.module.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"admin.module.js","sourceRoot":"","sources":["../../../../src/modules/admin/admin.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,2EAAsE;AACtE,qEAAgE;AAChE,qEAAgE;AAChE,+DAA0D;AAC1D,gEAA4D;AAQrD,IAAM,WAAW,GAAjB,MAAM,WAAW;CAAG,CAAA;AAAd,kCAAW;sBAAX,WAAW;IANvB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,4BAAY,CAAC;QACvB,WAAW,EAAE,CAAC,mDAAuB,EAAE,6CAAoB,CAAC;QAC5D,SAAS,EAAE,CAAC,6CAAoB,EAAE,uCAAiB,CAAC;QACpD,OAAO,EAAE,CAAC,6CAAoB,EAAE,uCAAiB,CAAC;KACnD,CAAC;GACW,WAAW,CAAG"}
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
import { AuthService } from './auth.service';
|
|
||||||
import { LoginDto } from './dto/login.dto';
|
|
||||||
export declare class AuthController {
|
|
||||||
private authService;
|
|
||||||
constructor(authService: AuthService);
|
|
||||||
login(loginDto: LoginDto): Promise<{
|
|
||||||
token: string;
|
|
||||||
user: {
|
|
||||||
id: any;
|
|
||||||
name: any;
|
|
||||||
role: any;
|
|
||||||
tenantId: any;
|
|
||||||
tenantName: any;
|
|
||||||
};
|
|
||||||
}>;
|
|
||||||
logout(): Promise<{
|
|
||||||
message: string;
|
|
||||||
}>;
|
|
||||||
getProfile(req: any): Promise<{
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
role: string;
|
|
||||||
tenantId?: undefined;
|
|
||||||
tenantName?: undefined;
|
|
||||||
email?: undefined;
|
|
||||||
phone?: undefined;
|
|
||||||
children?: undefined;
|
|
||||||
} | {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
role: string;
|
|
||||||
tenantId: number;
|
|
||||||
tenantName: string;
|
|
||||||
email?: undefined;
|
|
||||||
phone?: undefined;
|
|
||||||
children?: undefined;
|
|
||||||
} | {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
role: string;
|
|
||||||
tenantId: number;
|
|
||||||
tenantName: string;
|
|
||||||
email: string;
|
|
||||||
phone: string;
|
|
||||||
children?: undefined;
|
|
||||||
} | {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
role: string;
|
|
||||||
tenantId: number;
|
|
||||||
tenantName: string;
|
|
||||||
email: string;
|
|
||||||
phone: string;
|
|
||||||
children: {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
relationship: string;
|
|
||||||
}[];
|
|
||||||
}>;
|
|
||||||
}
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
||||||
};
|
|
||||||
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
||||||
return function (target, key) { decorator(target, key, paramIndex); }
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.AuthController = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const auth_service_1 = require("./auth.service");
|
|
||||||
const jwt_auth_guard_1 = require("../common/guards/jwt-auth.guard");
|
|
||||||
const login_dto_1 = require("./dto/login.dto");
|
|
||||||
let AuthController = class AuthController {
|
|
||||||
constructor(authService) {
|
|
||||||
this.authService = authService;
|
|
||||||
}
|
|
||||||
async login(loginDto) {
|
|
||||||
return this.authService.login(loginDto);
|
|
||||||
}
|
|
||||||
async logout() {
|
|
||||||
return { message: 'Logged out successfully' };
|
|
||||||
}
|
|
||||||
async getProfile(req) {
|
|
||||||
return this.authService.getProfile(req.user.userId, req.user.role);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.AuthController = AuthController;
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Post)('login'),
|
|
||||||
__param(0, (0, common_1.Body)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [login_dto_1.LoginDto]),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], AuthController.prototype, "login", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Post)('logout'),
|
|
||||||
(0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", []),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], AuthController.prototype, "logout", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)('profile'),
|
|
||||||
(0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard),
|
|
||||||
__param(0, (0, common_1.Request)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [Object]),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], AuthController.prototype, "getProfile", null);
|
|
||||||
exports.AuthController = AuthController = __decorate([
|
|
||||||
(0, common_1.Controller)('auth'),
|
|
||||||
__metadata("design:paramtypes", [auth_service_1.AuthService])
|
|
||||||
], AuthController);
|
|
||||||
//# sourceMappingURL=auth.controller.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"auth.controller.js","sourceRoot":"","sources":["../../../../src/modules/auth/auth.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAiF;AACjF,iDAA6C;AAC7C,oEAA+D;AAC/D,+CAA2C;AAGpC,IAAM,cAAc,GAApB,MAAM,cAAc;IACzB,YAAoB,WAAwB;QAAxB,gBAAW,GAAX,WAAW,CAAa;IAAG,CAAC;IAG1C,AAAN,KAAK,CAAC,KAAK,CAAS,QAAkB;QACpC,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAIK,AAAN,KAAK,CAAC,MAAM;QAEV,OAAO,EAAE,OAAO,EAAE,yBAAyB,EAAE,CAAC;IAChD,CAAC;IAIK,AAAN,KAAK,CAAC,UAAU,CAAY,GAAG;QAC7B,OAAO,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrE,CAAC;CACF,CAAA;AApBY,wCAAc;AAInB;IADL,IAAA,aAAI,EAAC,OAAO,CAAC;IACD,WAAA,IAAA,aAAI,GAAE,CAAA;;qCAAW,oBAAQ;;2CAErC;AAIK;IAFL,IAAA,aAAI,EAAC,QAAQ,CAAC;IACd,IAAA,kBAAS,EAAC,6BAAY,CAAC;;;;4CAIvB;AAIK;IAFL,IAAA,YAAG,EAAC,SAAS,CAAC;IACd,IAAA,kBAAS,EAAC,6BAAY,CAAC;IACN,WAAA,IAAA,gBAAO,GAAE,CAAA;;;;gDAE1B;yBAnBU,cAAc;IAD1B,IAAA,mBAAU,EAAC,MAAM,CAAC;qCAEgB,0BAAW;GADjC,cAAc,CAoB1B"}
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
export declare class AuthModule {
|
|
||||||
}
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.AuthModule = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const jwt_1 = require("@nestjs/jwt");
|
|
||||||
const passport_1 = require("@nestjs/passport");
|
|
||||||
const config_1 = require("@nestjs/config");
|
|
||||||
const auth_service_1 = require("./auth.service");
|
|
||||||
const auth_controller_1 = require("./auth.controller");
|
|
||||||
const jwt_strategy_1 = require("./strategies/jwt.strategy");
|
|
||||||
const prisma_module_1 = require("../../database/prisma.module");
|
|
||||||
let AuthModule = class AuthModule {
|
|
||||||
};
|
|
||||||
exports.AuthModule = AuthModule;
|
|
||||||
exports.AuthModule = AuthModule = __decorate([
|
|
||||||
(0, common_1.Module)({
|
|
||||||
imports: [
|
|
||||||
passport_1.PassportModule,
|
|
||||||
jwt_1.JwtModule.registerAsync({
|
|
||||||
imports: [config_1.ConfigModule],
|
|
||||||
useFactory: async (configService) => ({
|
|
||||||
secret: configService.get('JWT_SECRET') || 'your-secret-key',
|
|
||||||
signOptions: {
|
|
||||||
expiresIn: configService.get('JWT_EXPIRES_IN') || '7d',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
inject: [config_1.ConfigService],
|
|
||||||
}),
|
|
||||||
prisma_module_1.PrismaModule,
|
|
||||||
],
|
|
||||||
controllers: [auth_controller_1.AuthController],
|
|
||||||
providers: [auth_service_1.AuthService, jwt_strategy_1.JwtStrategy],
|
|
||||||
exports: [auth_service_1.AuthService],
|
|
||||||
})
|
|
||||||
], AuthModule);
|
|
||||||
//# sourceMappingURL=auth.module.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"auth.module.js","sourceRoot":"","sources":["../../../../src/modules/auth/auth.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,qCAAwC;AACxC,+CAAkD;AAClD,2CAA6D;AAC7D,iDAA6C;AAC7C,uDAAmD;AACnD,4DAAwD;AACxD,gEAA4D;AAqBrD,IAAM,UAAU,GAAhB,MAAM,UAAU;CAAG,CAAA;AAAb,gCAAU;qBAAV,UAAU;IAnBtB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,yBAAc;YACd,eAAS,CAAC,aAAa,CAAC;gBACtB,OAAO,EAAE,CAAC,qBAAY,CAAC;gBACvB,UAAU,EAAE,KAAK,EAAE,aAA4B,EAAE,EAAE,CAAC,CAAC;oBACnD,MAAM,EAAE,aAAa,CAAC,GAAG,CAAS,YAAY,CAAC,IAAI,iBAAiB;oBACpE,WAAW,EAAE;wBACX,SAAS,EAAE,aAAa,CAAC,GAAG,CAAS,gBAAgB,CAAC,IAAI,IAAI;qBAC/D;iBACF,CAAC;gBACF,MAAM,EAAE,CAAC,sBAAa,CAAC;aACxB,CAAC;YACF,4BAAY;SACb;QACD,WAAW,EAAE,CAAC,gCAAc,CAAC;QAC7B,SAAS,EAAE,CAAC,0BAAW,EAAE,0BAAW,CAAC;QACrC,OAAO,EAAE,CAAC,0BAAW,CAAC;KACvB,CAAC;GACW,UAAU,CAAG"}
|
|
||||||
@ -1,84 +0,0 @@
|
|||||||
import { JwtService } from '@nestjs/jwt';
|
|
||||||
import { PrismaService } from '../../database/prisma.service';
|
|
||||||
export interface LoginDto {
|
|
||||||
account: string;
|
|
||||||
password: string;
|
|
||||||
role: string;
|
|
||||||
}
|
|
||||||
export interface JwtPayload {
|
|
||||||
sub: number;
|
|
||||||
role: string;
|
|
||||||
tenantId?: number;
|
|
||||||
}
|
|
||||||
export declare class AuthService {
|
|
||||||
private prisma;
|
|
||||||
private jwtService;
|
|
||||||
constructor(prisma: PrismaService, jwtService: JwtService);
|
|
||||||
validateUser(account: string, password: string): Promise<{
|
|
||||||
id: number;
|
|
||||||
tenantId: number;
|
|
||||||
name: string;
|
|
||||||
phone: string;
|
|
||||||
email: string | null;
|
|
||||||
loginAccount: string;
|
|
||||||
passwordHash: string;
|
|
||||||
classIds: string | null;
|
|
||||||
status: string;
|
|
||||||
lessonCount: number;
|
|
||||||
feedbackCount: number;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
lastLoginAt: Date | null;
|
|
||||||
}>;
|
|
||||||
login(dto: LoginDto): Promise<{
|
|
||||||
token: string;
|
|
||||||
user: {
|
|
||||||
id: any;
|
|
||||||
name: any;
|
|
||||||
role: any;
|
|
||||||
tenantId: any;
|
|
||||||
tenantName: any;
|
|
||||||
};
|
|
||||||
}>;
|
|
||||||
getProfile(userId: number, role: string): Promise<{
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
role: string;
|
|
||||||
tenantId?: undefined;
|
|
||||||
tenantName?: undefined;
|
|
||||||
email?: undefined;
|
|
||||||
phone?: undefined;
|
|
||||||
children?: undefined;
|
|
||||||
} | {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
role: string;
|
|
||||||
tenantId: number;
|
|
||||||
tenantName: string;
|
|
||||||
email?: undefined;
|
|
||||||
phone?: undefined;
|
|
||||||
children?: undefined;
|
|
||||||
} | {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
role: string;
|
|
||||||
tenantId: number;
|
|
||||||
tenantName: string;
|
|
||||||
email: string;
|
|
||||||
phone: string;
|
|
||||||
children?: undefined;
|
|
||||||
} | {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
role: string;
|
|
||||||
tenantId: number;
|
|
||||||
tenantName: string;
|
|
||||||
email: string;
|
|
||||||
phone: string;
|
|
||||||
children: {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
relationship: string;
|
|
||||||
}[];
|
|
||||||
}>;
|
|
||||||
}
|
|
||||||
@ -1,287 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
||||||
if (k2 === undefined) k2 = k;
|
|
||||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
||||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
||||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
||||||
}
|
|
||||||
Object.defineProperty(o, k2, desc);
|
|
||||||
}) : (function(o, m, k, k2) {
|
|
||||||
if (k2 === undefined) k2 = k;
|
|
||||||
o[k2] = m[k];
|
|
||||||
}));
|
|
||||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
||||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
||||||
}) : function(o, v) {
|
|
||||||
o["default"] = v;
|
|
||||||
});
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
var __importStar = (this && this.__importStar) || function (mod) {
|
|
||||||
if (mod && mod.__esModule) return mod;
|
|
||||||
var result = {};
|
|
||||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
||||||
__setModuleDefault(result, mod);
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.AuthService = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const jwt_1 = require("@nestjs/jwt");
|
|
||||||
const prisma_service_1 = require("../../database/prisma.service");
|
|
||||||
const bcrypt = __importStar(require("bcrypt"));
|
|
||||||
let AuthService = class AuthService {
|
|
||||||
constructor(prisma, jwtService) {
|
|
||||||
this.prisma = prisma;
|
|
||||||
this.jwtService = jwtService;
|
|
||||||
}
|
|
||||||
async validateUser(account, password) {
|
|
||||||
const user = await this.prisma.teacher.findUnique({
|
|
||||||
where: { loginAccount: account },
|
|
||||||
});
|
|
||||||
if (!user) {
|
|
||||||
throw new common_1.UnauthorizedException('账号或密码错误');
|
|
||||||
}
|
|
||||||
const isPasswordValid = await bcrypt.compare(password, user.passwordHash);
|
|
||||||
if (!isPasswordValid) {
|
|
||||||
throw new common_1.UnauthorizedException('账号或密码错误');
|
|
||||||
}
|
|
||||||
if (user.status !== 'ACTIVE') {
|
|
||||||
throw new common_1.UnauthorizedException('账号已被停用');
|
|
||||||
}
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
async login(dto) {
|
|
||||||
let user;
|
|
||||||
if (dto.role === 'admin') {
|
|
||||||
if (dto.account === 'admin' && dto.password === 'admin123') {
|
|
||||||
user = {
|
|
||||||
id: 1,
|
|
||||||
name: '超级管理员',
|
|
||||||
role: 'admin',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new common_1.UnauthorizedException('账号或密码错误');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (dto.role === 'school') {
|
|
||||||
const tenant = await this.prisma.tenant.findUnique({
|
|
||||||
where: { loginAccount: dto.account },
|
|
||||||
});
|
|
||||||
if (!tenant) {
|
|
||||||
throw new common_1.UnauthorizedException('账号或密码错误');
|
|
||||||
}
|
|
||||||
if (!tenant.passwordHash) {
|
|
||||||
throw new common_1.UnauthorizedException('账号未设置密码');
|
|
||||||
}
|
|
||||||
const isPasswordValid = await bcrypt.compare(dto.password, tenant.passwordHash);
|
|
||||||
if (!isPasswordValid) {
|
|
||||||
throw new common_1.UnauthorizedException('账号或密码错误');
|
|
||||||
}
|
|
||||||
if (tenant.status !== 'ACTIVE') {
|
|
||||||
throw new common_1.UnauthorizedException('账号已被停用');
|
|
||||||
}
|
|
||||||
user = {
|
|
||||||
id: tenant.id,
|
|
||||||
name: tenant.name,
|
|
||||||
role: 'school',
|
|
||||||
tenantId: tenant.id,
|
|
||||||
tenantName: tenant.name,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if (dto.role === 'teacher') {
|
|
||||||
const teacher = await this.prisma.teacher.findUnique({
|
|
||||||
where: { loginAccount: dto.account },
|
|
||||||
include: {
|
|
||||||
tenant: {
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
name: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (!teacher) {
|
|
||||||
throw new common_1.UnauthorizedException('账号或密码错误');
|
|
||||||
}
|
|
||||||
const isPasswordValid = await bcrypt.compare(dto.password, teacher.passwordHash);
|
|
||||||
if (!isPasswordValid) {
|
|
||||||
throw new common_1.UnauthorizedException('账号或密码错误');
|
|
||||||
}
|
|
||||||
if (teacher.status !== 'ACTIVE') {
|
|
||||||
throw new common_1.UnauthorizedException('账号已被停用');
|
|
||||||
}
|
|
||||||
user = {
|
|
||||||
id: teacher.id,
|
|
||||||
name: teacher.name,
|
|
||||||
role: 'teacher',
|
|
||||||
tenantId: teacher.tenantId,
|
|
||||||
tenantName: teacher.tenant?.name,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if (dto.role === 'parent') {
|
|
||||||
const parent = await this.prisma.parent.findUnique({
|
|
||||||
where: { loginAccount: dto.account },
|
|
||||||
include: {
|
|
||||||
tenant: {
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
name: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (!parent) {
|
|
||||||
throw new common_1.UnauthorizedException('账号或密码错误');
|
|
||||||
}
|
|
||||||
const isPasswordValid = await bcrypt.compare(dto.password, parent.passwordHash);
|
|
||||||
if (!isPasswordValid) {
|
|
||||||
throw new common_1.UnauthorizedException('账号或密码错误');
|
|
||||||
}
|
|
||||||
if (parent.status !== 'ACTIVE') {
|
|
||||||
throw new common_1.UnauthorizedException('账号已被停用');
|
|
||||||
}
|
|
||||||
user = {
|
|
||||||
id: parent.id,
|
|
||||||
name: parent.name,
|
|
||||||
role: 'parent',
|
|
||||||
tenantId: parent.tenantId,
|
|
||||||
tenantName: parent.tenant?.name,
|
|
||||||
};
|
|
||||||
await this.prisma.parent.update({
|
|
||||||
where: { id: parent.id },
|
|
||||||
data: { lastLoginAt: new Date() },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new common_1.UnauthorizedException('无效的角色');
|
|
||||||
}
|
|
||||||
const payload = {
|
|
||||||
sub: user.id,
|
|
||||||
role: user.role,
|
|
||||||
tenantId: user.tenantId,
|
|
||||||
};
|
|
||||||
const token = this.jwtService.sign(payload);
|
|
||||||
if (dto.role === 'teacher') {
|
|
||||||
await this.prisma.teacher.update({
|
|
||||||
where: { id: user.id },
|
|
||||||
data: { lastLoginAt: new Date() },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
token,
|
|
||||||
user: {
|
|
||||||
id: user.id,
|
|
||||||
name: user.name,
|
|
||||||
role: user.role,
|
|
||||||
tenantId: user.tenantId,
|
|
||||||
tenantName: user.tenantName,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
async getProfile(userId, role) {
|
|
||||||
if (role === 'admin') {
|
|
||||||
return {
|
|
||||||
id: 1,
|
|
||||||
name: '超级管理员',
|
|
||||||
role: 'admin',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if (role === 'school') {
|
|
||||||
const tenant = await this.prisma.tenant.findUnique({
|
|
||||||
where: { id: userId },
|
|
||||||
});
|
|
||||||
if (!tenant) {
|
|
||||||
throw new common_1.UnauthorizedException('用户不存在');
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
id: tenant.id,
|
|
||||||
name: tenant.name,
|
|
||||||
role: 'school',
|
|
||||||
tenantId: tenant.id,
|
|
||||||
tenantName: tenant.name,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if (role === 'teacher') {
|
|
||||||
const teacher = await this.prisma.teacher.findUnique({
|
|
||||||
where: { id: userId },
|
|
||||||
include: {
|
|
||||||
tenant: {
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
name: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (!teacher) {
|
|
||||||
throw new common_1.UnauthorizedException('用户不存在');
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
id: teacher.id,
|
|
||||||
name: teacher.name,
|
|
||||||
role: 'teacher',
|
|
||||||
tenantId: teacher.tenantId,
|
|
||||||
tenantName: teacher.tenant?.name,
|
|
||||||
email: teacher.email,
|
|
||||||
phone: teacher.phone,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if (role === 'parent') {
|
|
||||||
const parent = await this.prisma.parent.findUnique({
|
|
||||||
where: { id: userId },
|
|
||||||
include: {
|
|
||||||
tenant: {
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
name: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
children: {
|
|
||||||
include: {
|
|
||||||
student: {
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
name: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (!parent) {
|
|
||||||
throw new common_1.UnauthorizedException('用户不存在');
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
id: parent.id,
|
|
||||||
name: parent.name,
|
|
||||||
role: 'parent',
|
|
||||||
tenantId: parent.tenantId,
|
|
||||||
tenantName: parent.tenant?.name,
|
|
||||||
email: parent.email,
|
|
||||||
phone: parent.phone,
|
|
||||||
children: parent.children.map((c) => ({
|
|
||||||
id: c.student.id,
|
|
||||||
name: c.student.name,
|
|
||||||
relationship: c.relationship,
|
|
||||||
})),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
throw new common_1.UnauthorizedException('无效的角色');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.AuthService = AuthService;
|
|
||||||
exports.AuthService = AuthService = __decorate([
|
|
||||||
(0, common_1.Injectable)(),
|
|
||||||
__metadata("design:paramtypes", [prisma_service_1.PrismaService,
|
|
||||||
jwt_1.JwtService])
|
|
||||||
], AuthService);
|
|
||||||
//# sourceMappingURL=auth.service.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
@ -1,5 +0,0 @@
|
|||||||
export declare class LoginDto {
|
|
||||||
account: string;
|
|
||||||
password: string;
|
|
||||||
role: string;
|
|
||||||
}
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.LoginDto = void 0;
|
|
||||||
const class_validator_1 = require("class-validator");
|
|
||||||
class LoginDto {
|
|
||||||
}
|
|
||||||
exports.LoginDto = LoginDto;
|
|
||||||
__decorate([
|
|
||||||
(0, class_validator_1.IsString)(),
|
|
||||||
(0, class_validator_1.IsNotEmpty)(),
|
|
||||||
__metadata("design:type", String)
|
|
||||||
], LoginDto.prototype, "account", void 0);
|
|
||||||
__decorate([
|
|
||||||
(0, class_validator_1.IsString)(),
|
|
||||||
(0, class_validator_1.IsNotEmpty)(),
|
|
||||||
__metadata("design:type", String)
|
|
||||||
], LoginDto.prototype, "password", void 0);
|
|
||||||
__decorate([
|
|
||||||
(0, class_validator_1.IsString)(),
|
|
||||||
(0, class_validator_1.IsIn)(['admin', 'school', 'teacher', 'parent']),
|
|
||||||
(0, class_validator_1.IsNotEmpty)(),
|
|
||||||
__metadata("design:type", String)
|
|
||||||
], LoginDto.prototype, "role", void 0);
|
|
||||||
//# sourceMappingURL=login.dto.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"login.dto.js","sourceRoot":"","sources":["../../../../../src/modules/auth/dto/login.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAA6D;AAE7D,MAAa,QAAQ;CAapB;AAbD,4BAaC;AAVC;IAFC,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;yCACG;AAIhB;IAFC,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;;0CACI;AAKjB;IAHC,IAAA,0BAAQ,GAAE;IACV,IAAA,sBAAI,EAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC9C,IAAA,4BAAU,GAAE;;sCACA"}
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
import { Strategy } from 'passport-jwt';
|
|
||||||
import { ConfigService } from '@nestjs/config';
|
|
||||||
export interface JwtPayload {
|
|
||||||
sub: number;
|
|
||||||
role: string;
|
|
||||||
tenantId?: number;
|
|
||||||
}
|
|
||||||
declare const JwtStrategy_base: new (...args: any[]) => Strategy;
|
|
||||||
export declare class JwtStrategy extends JwtStrategy_base {
|
|
||||||
private configService;
|
|
||||||
constructor(configService: ConfigService);
|
|
||||||
validate(payload: JwtPayload): Promise<{
|
|
||||||
userId: number;
|
|
||||||
role: string;
|
|
||||||
tenantId: number;
|
|
||||||
}>;
|
|
||||||
}
|
|
||||||
export {};
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.JwtStrategy = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const passport_1 = require("@nestjs/passport");
|
|
||||||
const passport_jwt_1 = require("passport-jwt");
|
|
||||||
const config_1 = require("@nestjs/config");
|
|
||||||
let JwtStrategy = class JwtStrategy extends (0, passport_1.PassportStrategy)(passport_jwt_1.Strategy) {
|
|
||||||
constructor(configService) {
|
|
||||||
super({
|
|
||||||
jwtFromRequest: passport_jwt_1.ExtractJwt.fromAuthHeaderAsBearerToken(),
|
|
||||||
ignoreExpiration: false,
|
|
||||||
secretOrKey: configService.get('JWT_SECRET') || 'your-secret-key',
|
|
||||||
});
|
|
||||||
this.configService = configService;
|
|
||||||
}
|
|
||||||
async validate(payload) {
|
|
||||||
if (!payload.sub || !payload.role) {
|
|
||||||
throw new common_1.UnauthorizedException();
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
userId: payload.sub,
|
|
||||||
role: payload.role,
|
|
||||||
tenantId: payload.tenantId,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.JwtStrategy = JwtStrategy;
|
|
||||||
exports.JwtStrategy = JwtStrategy = __decorate([
|
|
||||||
(0, common_1.Injectable)(),
|
|
||||||
__metadata("design:paramtypes", [config_1.ConfigService])
|
|
||||||
], JwtStrategy);
|
|
||||||
//# sourceMappingURL=jwt.strategy.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"jwt.strategy.js","sourceRoot":"","sources":["../../../../../src/modules/auth/strategies/jwt.strategy.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAAmE;AACnE,+CAAoD;AACpD,+CAAoD;AACpD,2CAA+C;AASxC,IAAM,WAAW,GAAjB,MAAM,WAAY,SAAQ,IAAA,2BAAgB,EAAC,uBAAQ,CAAC;IACzD,YAAoB,aAA4B;QAC9C,KAAK,CAAC;YACJ,cAAc,EAAE,yBAAU,CAAC,2BAA2B,EAAE;YACxD,gBAAgB,EAAE,KAAK;YACvB,WAAW,EAAE,aAAa,CAAC,GAAG,CAAS,YAAY,CAAC,IAAI,iBAAiB;SAC1E,CAAC,CAAC;QALe,kBAAa,GAAb,aAAa,CAAe;IAMhD,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAAmB;QAChC,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClC,MAAM,IAAI,8BAAqB,EAAE,CAAC;QACpC,CAAC;QAED,OAAO;YACL,MAAM,EAAE,OAAO,CAAC,GAAG;YACnB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC3B,CAAC;IACJ,CAAC;CACF,CAAA;AApBY,kCAAW;sBAAX,WAAW;IADvB,IAAA,mBAAU,GAAE;qCAEwB,sBAAa;GADrC,WAAW,CAoBvB"}
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
export declare class CommonModule {
|
|
||||||
}
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.CommonModule = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const jwt_auth_guard_1 = require("./guards/jwt-auth.guard");
|
|
||||||
const roles_guard_1 = require("./guards/roles.guard");
|
|
||||||
const log_interceptor_1 = require("./interceptors/log.interceptor");
|
|
||||||
const operation_log_service_1 = require("./operation-log.service");
|
|
||||||
const operation_log_controller_1 = require("./operation-log.controller");
|
|
||||||
let CommonModule = class CommonModule {
|
|
||||||
};
|
|
||||||
exports.CommonModule = CommonModule;
|
|
||||||
exports.CommonModule = CommonModule = __decorate([
|
|
||||||
(0, common_1.Module)({
|
|
||||||
controllers: [operation_log_controller_1.SchoolOperationLogController, operation_log_controller_1.AdminOperationLogController],
|
|
||||||
providers: [jwt_auth_guard_1.JwtAuthGuard, roles_guard_1.RolesGuard, log_interceptor_1.LogInterceptor, operation_log_service_1.OperationLogService],
|
|
||||||
exports: [jwt_auth_guard_1.JwtAuthGuard, roles_guard_1.RolesGuard, log_interceptor_1.LogInterceptor, operation_log_service_1.OperationLogService],
|
|
||||||
})
|
|
||||||
], CommonModule);
|
|
||||||
//# sourceMappingURL=common.module.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"common.module.js","sourceRoot":"","sources":["../../../../src/modules/common/common.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,4DAAuD;AACvD,sDAAkD;AAClD,oEAAgE;AAChE,mEAA8D;AAC9D,yEAAuG;AAOhG,IAAM,YAAY,GAAlB,MAAM,YAAY;CAAG,CAAA;AAAf,oCAAY;uBAAZ,YAAY;IALxB,IAAA,eAAM,EAAC;QACN,WAAW,EAAE,CAAC,uDAA4B,EAAE,sDAA2B,CAAC;QACxE,SAAS,EAAE,CAAC,6BAAY,EAAE,wBAAU,EAAE,gCAAc,EAAE,2CAAmB,CAAC;QAC1E,OAAO,EAAE,CAAC,6BAAY,EAAE,wBAAU,EAAE,gCAAc,EAAE,2CAAmB,CAAC;KACzE,CAAC;GACW,YAAY,CAAG"}
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
export declare const LOG_OPERATION_KEY = "log_operation";
|
|
||||||
export interface LogOperationOptions {
|
|
||||||
action: string;
|
|
||||||
module: string;
|
|
||||||
description: string;
|
|
||||||
}
|
|
||||||
export declare const LogOperation: (options: LogOperationOptions) => import("@nestjs/common").CustomDecorator<string>;
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.LogOperation = exports.LOG_OPERATION_KEY = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
exports.LOG_OPERATION_KEY = 'log_operation';
|
|
||||||
const LogOperation = (options) => {
|
|
||||||
return (0, common_1.SetMetadata)(exports.LOG_OPERATION_KEY, options);
|
|
||||||
};
|
|
||||||
exports.LogOperation = LogOperation;
|
|
||||||
//# sourceMappingURL=log-operation.decorator.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"log-operation.decorator.js","sourceRoot":"","sources":["../../../../../src/modules/common/decorators/log-operation.decorator.ts"],"names":[],"mappings":";;;AAAA,2CAA6C;AAEhC,QAAA,iBAAiB,GAAG,eAAe,CAAC;AAY1C,MAAM,YAAY,GAAG,CAAC,OAA4B,EAAE,EAAE;IAC3D,OAAO,IAAA,oBAAW,EAAC,yBAAiB,EAAE,OAAO,CAAC,CAAC;AACjD,CAAC,CAAC;AAFW,QAAA,YAAY,gBAEvB"}
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
export declare const ROLES_KEY = "roles";
|
|
||||||
export declare const Roles: (...roles: string[]) => import("@nestjs/common").CustomDecorator<string>;
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.Roles = exports.ROLES_KEY = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
exports.ROLES_KEY = 'roles';
|
|
||||||
const Roles = (...roles) => (0, common_1.SetMetadata)(exports.ROLES_KEY, roles);
|
|
||||||
exports.Roles = Roles;
|
|
||||||
//# sourceMappingURL=roles.decorator.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"roles.decorator.js","sourceRoot":"","sources":["../../../../../src/modules/common/decorators/roles.decorator.ts"],"names":[],"mappings":";;;AAAA,2CAA6C;AAEhC,QAAA,SAAS,GAAG,OAAO,CAAC;AAC1B,MAAM,KAAK,GAAG,CAAC,GAAG,KAAe,EAAE,EAAE,CAAC,IAAA,oBAAW,EAAC,iBAAS,EAAE,KAAK,CAAC,CAAC;AAA9D,QAAA,KAAK,SAAyD"}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
import { ExecutionContext } from '@nestjs/common';
|
|
||||||
import { Reflector } from '@nestjs/core';
|
|
||||||
declare const JwtAuthGuard_base: import("@nestjs/passport").Type<import("@nestjs/passport").IAuthGuard>;
|
|
||||||
export declare class JwtAuthGuard extends JwtAuthGuard_base {
|
|
||||||
private reflector;
|
|
||||||
constructor(reflector: Reflector);
|
|
||||||
canActivate(context: ExecutionContext): boolean | Promise<boolean> | import("rxjs").Observable<boolean>;
|
|
||||||
}
|
|
||||||
export {};
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.JwtAuthGuard = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const core_1 = require("@nestjs/core");
|
|
||||||
const passport_1 = require("@nestjs/passport");
|
|
||||||
let JwtAuthGuard = class JwtAuthGuard extends (0, passport_1.AuthGuard)('jwt') {
|
|
||||||
constructor(reflector) {
|
|
||||||
super();
|
|
||||||
this.reflector = reflector;
|
|
||||||
}
|
|
||||||
canActivate(context) {
|
|
||||||
const requireAuth = this.reflector.getAllAndOverride('requireAuth', [
|
|
||||||
context.getHandler(),
|
|
||||||
context.getClass(),
|
|
||||||
]);
|
|
||||||
if (requireAuth === false) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return super.canActivate(context);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.JwtAuthGuard = JwtAuthGuard;
|
|
||||||
exports.JwtAuthGuard = JwtAuthGuard = __decorate([
|
|
||||||
(0, common_1.Injectable)(),
|
|
||||||
__metadata("design:paramtypes", [core_1.Reflector])
|
|
||||||
], JwtAuthGuard);
|
|
||||||
//# sourceMappingURL=jwt-auth.guard.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"jwt-auth.guard.js","sourceRoot":"","sources":["../../../../../src/modules/common/guards/jwt-auth.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA8D;AAC9D,uCAAyC;AACzC,+CAA6C;AAGtC,IAAM,YAAY,GAAlB,MAAM,YAAa,SAAQ,IAAA,oBAAS,EAAC,KAAK,CAAC;IAChD,YAAoB,SAAoB;QACtC,KAAK,EAAE,CAAC;QADU,cAAS,GAAT,SAAS,CAAW;IAExC,CAAC;IAED,WAAW,CAAC,OAAyB;QAEnC,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAU,aAAa,EAAE;YAC3E,OAAO,CAAC,UAAU,EAAE;YACpB,OAAO,CAAC,QAAQ,EAAE;SACnB,CAAC,CAAC;QAEH,IAAI,WAAW,KAAK,KAAK,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;CACF,CAAA;AAlBY,oCAAY;uBAAZ,YAAY;IADxB,IAAA,mBAAU,GAAE;qCAEoB,gBAAS;GAD7B,YAAY,CAkBxB"}
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
import { CanActivate, ExecutionContext } from '@nestjs/common';
|
|
||||||
import { Reflector } from '@nestjs/core';
|
|
||||||
export declare class RolesGuard implements CanActivate {
|
|
||||||
private reflector;
|
|
||||||
constructor(reflector: Reflector);
|
|
||||||
canActivate(context: ExecutionContext): boolean;
|
|
||||||
}
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.RolesGuard = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const core_1 = require("@nestjs/core");
|
|
||||||
const roles_decorator_1 = require("../decorators/roles.decorator");
|
|
||||||
let RolesGuard = class RolesGuard {
|
|
||||||
constructor(reflector) {
|
|
||||||
this.reflector = reflector;
|
|
||||||
}
|
|
||||||
canActivate(context) {
|
|
||||||
const requiredRoles = this.reflector.getAllAndOverride(roles_decorator_1.ROLES_KEY, [
|
|
||||||
context.getHandler(),
|
|
||||||
context.getClass(),
|
|
||||||
]);
|
|
||||||
if (!requiredRoles) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const { user } = context.switchToHttp().getRequest();
|
|
||||||
return requiredRoles.some((role) => user?.role === role);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.RolesGuard = RolesGuard;
|
|
||||||
exports.RolesGuard = RolesGuard = __decorate([
|
|
||||||
(0, common_1.Injectable)(),
|
|
||||||
__metadata("design:paramtypes", [core_1.Reflector])
|
|
||||||
], RolesGuard);
|
|
||||||
//# sourceMappingURL=roles.guard.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"roles.guard.js","sourceRoot":"","sources":["../../../../../src/modules/common/guards/roles.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA2E;AAC3E,uCAAyC;AACzC,mEAA0D;AAGnD,IAAM,UAAU,GAAhB,MAAM,UAAU;IACrB,YAAoB,SAAoB;QAApB,cAAS,GAAT,SAAS,CAAW;IAAG,CAAC;IAE5C,WAAW,CAAC,OAAyB;QACnC,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAW,2BAAS,EAAE;YAC1E,OAAO,CAAC,UAAU,EAAE;YACpB,OAAO,CAAC,QAAQ,EAAE;SACnB,CAAC,CAAC;QAGH,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;QAGrD,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC,CAAC;IAC3D,CAAC;CACF,CAAA;AAnBY,gCAAU;qBAAV,UAAU;IADtB,IAAA,mBAAU,GAAE;qCAEoB,gBAAS;GAD7B,UAAU,CAmBtB"}
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
import { NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
|
|
||||||
import { Reflector } from '@nestjs/core';
|
|
||||||
import { Observable } from 'rxjs';
|
|
||||||
import { PrismaService } from '../../../database/prisma.service';
|
|
||||||
export declare class LogInterceptor implements NestInterceptor {
|
|
||||||
private reflector;
|
|
||||||
private prisma;
|
|
||||||
private readonly logger;
|
|
||||||
constructor(reflector: Reflector, prisma: PrismaService);
|
|
||||||
intercept(context: ExecutionContext, next: CallHandler): Observable<any>;
|
|
||||||
private saveLog;
|
|
||||||
private getIpAddress;
|
|
||||||
}
|
|
||||||
@ -1,115 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
||||||
};
|
|
||||||
var LogInterceptor_1;
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.LogInterceptor = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const core_1 = require("@nestjs/core");
|
|
||||||
const rxjs_1 = require("rxjs");
|
|
||||||
const prisma_service_1 = require("../../../database/prisma.service");
|
|
||||||
const log_operation_decorator_1 = require("../decorators/log-operation.decorator");
|
|
||||||
let LogInterceptor = LogInterceptor_1 = class LogInterceptor {
|
|
||||||
constructor(reflector, prisma) {
|
|
||||||
this.reflector = reflector;
|
|
||||||
this.prisma = prisma;
|
|
||||||
this.logger = new common_1.Logger(LogInterceptor_1.name);
|
|
||||||
}
|
|
||||||
intercept(context, next) {
|
|
||||||
const logOptions = this.reflector.getAllAndOverride(log_operation_decorator_1.LOG_OPERATION_KEY, [context.getHandler(), context.getClass()]);
|
|
||||||
if (!logOptions) {
|
|
||||||
return next.handle();
|
|
||||||
}
|
|
||||||
const request = context.switchToHttp().getRequest();
|
|
||||||
const user = request.user;
|
|
||||||
const startTime = Date.now();
|
|
||||||
const body = request.body;
|
|
||||||
const params = request.params;
|
|
||||||
return next.handle().pipe((0, rxjs_1.tap)({
|
|
||||||
next: (response) => {
|
|
||||||
this.saveLog({
|
|
||||||
user,
|
|
||||||
logOptions,
|
|
||||||
body,
|
|
||||||
params,
|
|
||||||
response,
|
|
||||||
ipAddress: this.getIpAddress(request),
|
|
||||||
userAgent: request.headers['user-agent'],
|
|
||||||
duration: Date.now() - startTime,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
error: (error) => {
|
|
||||||
this.saveLog({
|
|
||||||
user,
|
|
||||||
logOptions,
|
|
||||||
body,
|
|
||||||
params,
|
|
||||||
response: { error: error.message },
|
|
||||||
ipAddress: this.getIpAddress(request),
|
|
||||||
userAgent: request.headers['user-agent'],
|
|
||||||
duration: Date.now() - startTime,
|
|
||||||
isError: true,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
async saveLog(data) {
|
|
||||||
try {
|
|
||||||
const { user, logOptions, body, params, response, ipAddress, userAgent } = data;
|
|
||||||
let targetId;
|
|
||||||
if (params?.id) {
|
|
||||||
targetId = parseInt(params.id, 10);
|
|
||||||
}
|
|
||||||
else if (response?.id) {
|
|
||||||
targetId = response.id;
|
|
||||||
}
|
|
||||||
else if (body?.id) {
|
|
||||||
targetId = body.id;
|
|
||||||
}
|
|
||||||
let description = logOptions.description;
|
|
||||||
if (data.isError) {
|
|
||||||
description = `[失败] ${description}`;
|
|
||||||
}
|
|
||||||
await this.prisma.operationLog.create({
|
|
||||||
data: {
|
|
||||||
tenantId: user?.tenantId || null,
|
|
||||||
userId: user?.userId || 0,
|
|
||||||
userType: user?.role || 'UNKNOWN',
|
|
||||||
action: logOptions.action,
|
|
||||||
module: logOptions.module,
|
|
||||||
description,
|
|
||||||
targetId,
|
|
||||||
oldValue: body ? JSON.stringify(body) : null,
|
|
||||||
newValue: response ? JSON.stringify(response) : null,
|
|
||||||
ipAddress,
|
|
||||||
userAgent,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
this.logger.debug(`Operation logged: ${logOptions.module} - ${logOptions.action} (${data.duration}ms)`);
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
this.logger.error('Failed to save operation log:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
getIpAddress(request) {
|
|
||||||
return (request.headers['x-forwarded-for']?.split(',')[0]?.trim() ||
|
|
||||||
request.headers['x-real-ip'] ||
|
|
||||||
request.connection?.remoteAddress ||
|
|
||||||
request.socket?.remoteAddress ||
|
|
||||||
'unknown');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.LogInterceptor = LogInterceptor;
|
|
||||||
exports.LogInterceptor = LogInterceptor = LogInterceptor_1 = __decorate([
|
|
||||||
(0, common_1.Injectable)(),
|
|
||||||
__metadata("design:paramtypes", [core_1.Reflector,
|
|
||||||
prisma_service_1.PrismaService])
|
|
||||||
], LogInterceptor);
|
|
||||||
//# sourceMappingURL=log.interceptor.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"log.interceptor.js","sourceRoot":"","sources":["../../../../../src/modules/common/interceptors/log.interceptor.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAMwB;AACxB,uCAAyC;AACzC,+BAAuC;AACvC,qEAAiE;AACjE,mFAA+F;AAGxF,IAAM,cAAc,sBAApB,MAAM,cAAc;IAGzB,YACU,SAAoB,EACpB,MAAqB;QADrB,cAAS,GAAT,SAAS,CAAW;QACpB,WAAM,GAAN,MAAM,CAAe;QAJd,WAAM,GAAG,IAAI,eAAM,CAAC,gBAAc,CAAC,IAAI,CAAC,CAAC;IAKvD,CAAC;IAEJ,SAAS,CAAC,OAAyB,EAAE,IAAiB;QACpD,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CACjD,2CAAiB,EACjB,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAC3C,CAAC;QAEF,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,CAAC;QAED,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;QACpD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QAC1B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAG7B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QAC1B,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAE9B,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CACvB,IAAA,UAAG,EAAC;YACF,IAAI,EAAE,CAAC,QAAQ,EAAE,EAAE;gBACjB,IAAI,CAAC,OAAO,CAAC;oBACX,IAAI;oBACJ,UAAU;oBACV,IAAI;oBACJ,MAAM;oBACN,QAAQ;oBACR,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC;oBACrC,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC;oBACxC,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;iBACjC,CAAC,CAAC;YACL,CAAC;YACD,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE;gBAEf,IAAI,CAAC,OAAO,CAAC;oBACX,IAAI;oBACJ,UAAU;oBACV,IAAI;oBACJ,MAAM;oBACN,QAAQ,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE;oBAClC,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC;oBACrC,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC;oBACxC,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;oBAChC,OAAO,EAAE,IAAI;iBACd,CAAC,CAAC;YACL,CAAC;SACF,CAAC,CACH,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,OAAO,CAAC,IAUrB;QACC,IAAI,CAAC;YACH,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;YAGhF,IAAI,QAA4B,CAAC;YACjC,IAAI,MAAM,EAAE,EAAE,EAAE,CAAC;gBACf,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACrC,CAAC;iBAAM,IAAI,QAAQ,EAAE,EAAE,EAAE,CAAC;gBACxB,QAAQ,GAAG,QAAQ,CAAC,EAAE,CAAC;YACzB,CAAC;iBAAM,IAAI,IAAI,EAAE,EAAE,EAAE,CAAC;gBACpB,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC;YACrB,CAAC;YAGD,IAAI,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC;YACzC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBACjB,WAAW,GAAG,QAAQ,WAAW,EAAE,CAAC;YACtC,CAAC;YAED,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC;gBACpC,IAAI,EAAE;oBACJ,QAAQ,EAAE,IAAI,EAAE,QAAQ,IAAI,IAAI;oBAChC,MAAM,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;oBACzB,QAAQ,EAAE,IAAI,EAAE,IAAI,IAAI,SAAS;oBACjC,MAAM,EAAE,UAAU,CAAC,MAAM;oBACzB,MAAM,EAAE,UAAU,CAAC,MAAM;oBACzB,WAAW;oBACX,QAAQ;oBACR,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;oBAC5C,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI;oBACpD,SAAS;oBACT,SAAS;iBACV;aACF,CAAC,CAAC;YAEH,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,qBAAqB,UAAU,CAAC,MAAM,MAAM,UAAU,CAAC,MAAM,KAAK,IAAI,CAAC,QAAQ,KAAK,CACrF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAEO,YAAY,CAAC,OAAY;QAC/B,OAAO,CACL,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE;YACzD,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC;YAC5B,OAAO,CAAC,UAAU,EAAE,aAAa;YACjC,OAAO,CAAC,MAAM,EAAE,aAAa;YAC7B,SAAS,CACV,CAAC;IACJ,CAAC;CACF,CAAA;AAzHY,wCAAc;yBAAd,cAAc;IAD1B,IAAA,mBAAU,GAAE;qCAKU,gBAAS;QACZ,8BAAa;GALpB,cAAc,CAyH1B"}
|
|
||||||
@ -1,101 +0,0 @@
|
|||||||
import { OperationLogService } from './operation-log.service';
|
|
||||||
export declare class SchoolOperationLogController {
|
|
||||||
private readonly logService;
|
|
||||||
constructor(logService: OperationLogService);
|
|
||||||
getLogs(req: any, query: any): Promise<{
|
|
||||||
items: {
|
|
||||||
id: number;
|
|
||||||
tenantId: number | null;
|
|
||||||
description: string;
|
|
||||||
createdAt: Date;
|
|
||||||
ipAddress: string | null;
|
|
||||||
userAgent: string | null;
|
|
||||||
userId: number;
|
|
||||||
userType: string;
|
|
||||||
action: string;
|
|
||||||
module: string;
|
|
||||||
targetId: number | null;
|
|
||||||
oldValue: string | null;
|
|
||||||
newValue: string | null;
|
|
||||||
}[];
|
|
||||||
total: number;
|
|
||||||
page: number;
|
|
||||||
pageSize: number;
|
|
||||||
}>;
|
|
||||||
getStats(req: any, query: any): Promise<{
|
|
||||||
modules: {
|
|
||||||
name: string;
|
|
||||||
count: number;
|
|
||||||
}[];
|
|
||||||
actions: {
|
|
||||||
name: string;
|
|
||||||
count: number;
|
|
||||||
}[];
|
|
||||||
total: number;
|
|
||||||
}>;
|
|
||||||
getLogById(req: any, id: string): Promise<{
|
|
||||||
oldValue: any;
|
|
||||||
newValue: any;
|
|
||||||
id: number;
|
|
||||||
tenantId: number | null;
|
|
||||||
description: string;
|
|
||||||
createdAt: Date;
|
|
||||||
ipAddress: string | null;
|
|
||||||
userAgent: string | null;
|
|
||||||
userId: number;
|
|
||||||
userType: string;
|
|
||||||
action: string;
|
|
||||||
module: string;
|
|
||||||
targetId: number | null;
|
|
||||||
}>;
|
|
||||||
}
|
|
||||||
export declare class AdminOperationLogController {
|
|
||||||
private readonly logService;
|
|
||||||
constructor(logService: OperationLogService);
|
|
||||||
getLogs(query: any): Promise<{
|
|
||||||
items: {
|
|
||||||
id: number;
|
|
||||||
tenantId: number | null;
|
|
||||||
description: string;
|
|
||||||
createdAt: Date;
|
|
||||||
ipAddress: string | null;
|
|
||||||
userAgent: string | null;
|
|
||||||
userId: number;
|
|
||||||
userType: string;
|
|
||||||
action: string;
|
|
||||||
module: string;
|
|
||||||
targetId: number | null;
|
|
||||||
oldValue: string | null;
|
|
||||||
newValue: string | null;
|
|
||||||
}[];
|
|
||||||
total: number;
|
|
||||||
page: number;
|
|
||||||
pageSize: number;
|
|
||||||
}>;
|
|
||||||
getStats(query: any): Promise<{
|
|
||||||
modules: {
|
|
||||||
name: string;
|
|
||||||
count: number;
|
|
||||||
}[];
|
|
||||||
actions: {
|
|
||||||
name: string;
|
|
||||||
count: number;
|
|
||||||
}[];
|
|
||||||
total: number;
|
|
||||||
}>;
|
|
||||||
getLogById(id: string): Promise<{
|
|
||||||
oldValue: any;
|
|
||||||
newValue: any;
|
|
||||||
id: number;
|
|
||||||
tenantId: number | null;
|
|
||||||
description: string;
|
|
||||||
createdAt: Date;
|
|
||||||
ipAddress: string | null;
|
|
||||||
userAgent: string | null;
|
|
||||||
userId: number;
|
|
||||||
userType: string;
|
|
||||||
action: string;
|
|
||||||
module: string;
|
|
||||||
targetId: number | null;
|
|
||||||
}>;
|
|
||||||
}
|
|
||||||
@ -1,108 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
||||||
};
|
|
||||||
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
||||||
return function (target, key) { decorator(target, key, paramIndex); }
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.AdminOperationLogController = exports.SchoolOperationLogController = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const operation_log_service_1 = require("./operation-log.service");
|
|
||||||
const jwt_auth_guard_1 = require("./guards/jwt-auth.guard");
|
|
||||||
const roles_guard_1 = require("./guards/roles.guard");
|
|
||||||
const roles_decorator_1 = require("./decorators/roles.decorator");
|
|
||||||
let SchoolOperationLogController = class SchoolOperationLogController {
|
|
||||||
constructor(logService) {
|
|
||||||
this.logService = logService;
|
|
||||||
}
|
|
||||||
getLogs(req, query) {
|
|
||||||
return this.logService.getLogs(req.user.tenantId, query);
|
|
||||||
}
|
|
||||||
getStats(req, query) {
|
|
||||||
return this.logService.getModuleStats(req.user.tenantId, query.startDate, query.endDate);
|
|
||||||
}
|
|
||||||
getLogById(req, id) {
|
|
||||||
return this.logService.getLogById(req.user.tenantId, +id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.SchoolOperationLogController = SchoolOperationLogController;
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)('operation-logs'),
|
|
||||||
__param(0, (0, common_1.Request)()),
|
|
||||||
__param(1, (0, common_1.Query)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [Object, Object]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], SchoolOperationLogController.prototype, "getLogs", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)('operation-logs/stats'),
|
|
||||||
__param(0, (0, common_1.Request)()),
|
|
||||||
__param(1, (0, common_1.Query)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [Object, Object]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], SchoolOperationLogController.prototype, "getStats", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)('operation-logs/:id'),
|
|
||||||
__param(0, (0, common_1.Request)()),
|
|
||||||
__param(1, (0, common_1.Param)('id')),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [Object, String]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], SchoolOperationLogController.prototype, "getLogById", null);
|
|
||||||
exports.SchoolOperationLogController = SchoolOperationLogController = __decorate([
|
|
||||||
(0, common_1.Controller)('school'),
|
|
||||||
(0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard, roles_guard_1.RolesGuard),
|
|
||||||
(0, roles_decorator_1.Roles)('school'),
|
|
||||||
__metadata("design:paramtypes", [operation_log_service_1.OperationLogService])
|
|
||||||
], SchoolOperationLogController);
|
|
||||||
let AdminOperationLogController = class AdminOperationLogController {
|
|
||||||
constructor(logService) {
|
|
||||||
this.logService = logService;
|
|
||||||
}
|
|
||||||
getLogs(query) {
|
|
||||||
return this.logService.getLogs(null, query);
|
|
||||||
}
|
|
||||||
getStats(query) {
|
|
||||||
return this.logService.getModuleStats(null, query.startDate, query.endDate);
|
|
||||||
}
|
|
||||||
getLogById(id) {
|
|
||||||
return this.logService.getLogById(null, +id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.AdminOperationLogController = AdminOperationLogController;
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)('operation-logs'),
|
|
||||||
__param(0, (0, common_1.Query)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [Object]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], AdminOperationLogController.prototype, "getLogs", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)('operation-logs/stats'),
|
|
||||||
__param(0, (0, common_1.Query)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [Object]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], AdminOperationLogController.prototype, "getStats", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)('operation-logs/:id'),
|
|
||||||
__param(0, (0, common_1.Param)('id')),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [String]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], AdminOperationLogController.prototype, "getLogById", null);
|
|
||||||
exports.AdminOperationLogController = AdminOperationLogController = __decorate([
|
|
||||||
(0, common_1.Controller)('admin'),
|
|
||||||
(0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard, roles_guard_1.RolesGuard),
|
|
||||||
(0, roles_decorator_1.Roles)('admin'),
|
|
||||||
__metadata("design:paramtypes", [operation_log_service_1.OperationLogService])
|
|
||||||
], AdminOperationLogController);
|
|
||||||
//# sourceMappingURL=operation-log.controller.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"operation-log.controller.js","sourceRoot":"","sources":["../../../../src/modules/common/operation-log.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAOwB;AACxB,mEAA8D;AAC9D,4DAAuD;AACvD,sDAAkD;AAClD,kEAAqD;AAK9C,IAAM,4BAA4B,GAAlC,MAAM,4BAA4B;IACvC,YAA6B,UAA+B;QAA/B,eAAU,GAAV,UAAU,CAAqB;IAAG,CAAC;IAGhE,OAAO,CAAY,GAAQ,EAAW,KAAU;QAC9C,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC3D,CAAC;IAGD,QAAQ,CAAY,GAAQ,EAAW,KAAU;QAC/C,OAAO,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3F,CAAC;IAGD,UAAU,CAAY,GAAQ,EAAe,EAAU;QACrD,OAAO,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;IAC5D,CAAC;CACF,CAAA;AAjBY,oEAA4B;AAIvC;IADC,IAAA,YAAG,EAAC,gBAAgB,CAAC;IACb,WAAA,IAAA,gBAAO,GAAE,CAAA;IAAY,WAAA,IAAA,cAAK,GAAE,CAAA;;;;2DAEpC;AAGD;IADC,IAAA,YAAG,EAAC,sBAAsB,CAAC;IAClB,WAAA,IAAA,gBAAO,GAAE,CAAA;IAAY,WAAA,IAAA,cAAK,GAAE,CAAA;;;;4DAErC;AAGD;IADC,IAAA,YAAG,EAAC,oBAAoB,CAAC;IACd,WAAA,IAAA,gBAAO,GAAE,CAAA;IAAY,WAAA,IAAA,cAAK,EAAC,IAAI,CAAC,CAAA;;;;8DAE3C;uCAhBU,4BAA4B;IAHxC,IAAA,mBAAU,EAAC,QAAQ,CAAC;IACpB,IAAA,kBAAS,EAAC,6BAAY,EAAE,wBAAU,CAAC;IACnC,IAAA,uBAAK,EAAC,QAAQ,CAAC;qCAE2B,2CAAmB;GADjD,4BAA4B,CAiBxC;AAKM,IAAM,2BAA2B,GAAjC,MAAM,2BAA2B;IACtC,YAA6B,UAA+B;QAA/B,eAAU,GAAV,UAAU,CAAqB;IAAG,CAAC;IAGhE,OAAO,CAAU,KAAU;QACzB,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC9C,CAAC;IAGD,QAAQ,CAAU,KAAU;QAC1B,OAAO,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC9E,CAAC;IAGD,UAAU,CAAc,EAAU;QAChC,OAAO,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;IAC/C,CAAC;CACF,CAAA;AAjBY,kEAA2B;AAItC;IADC,IAAA,YAAG,EAAC,gBAAgB,CAAC;IACb,WAAA,IAAA,cAAK,GAAE,CAAA;;;;0DAEf;AAGD;IADC,IAAA,YAAG,EAAC,sBAAsB,CAAC;IAClB,WAAA,IAAA,cAAK,GAAE,CAAA;;;;2DAEhB;AAGD;IADC,IAAA,YAAG,EAAC,oBAAoB,CAAC;IACd,WAAA,IAAA,cAAK,EAAC,IAAI,CAAC,CAAA;;;;6DAEtB;sCAhBU,2BAA2B;IAHvC,IAAA,mBAAU,EAAC,OAAO,CAAC;IACnB,IAAA,kBAAS,EAAC,6BAAY,EAAE,wBAAU,CAAC;IACnC,IAAA,uBAAK,EAAC,OAAO,CAAC;qCAE4B,2CAAmB;GADjD,2BAA2B,CAiBvC"}
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
import { PrismaService } from '../../database/prisma.service';
|
|
||||||
export declare class OperationLogService {
|
|
||||||
private prisma;
|
|
||||||
private readonly logger;
|
|
||||||
constructor(prisma: PrismaService);
|
|
||||||
getLogs(tenantId: number | null, query: {
|
|
||||||
page?: number;
|
|
||||||
pageSize?: number;
|
|
||||||
userId?: number;
|
|
||||||
userType?: string;
|
|
||||||
action?: string;
|
|
||||||
module?: string;
|
|
||||||
startDate?: string;
|
|
||||||
endDate?: string;
|
|
||||||
}): Promise<{
|
|
||||||
items: {
|
|
||||||
id: number;
|
|
||||||
tenantId: number | null;
|
|
||||||
description: string;
|
|
||||||
createdAt: Date;
|
|
||||||
ipAddress: string | null;
|
|
||||||
userAgent: string | null;
|
|
||||||
userId: number;
|
|
||||||
userType: string;
|
|
||||||
action: string;
|
|
||||||
module: string;
|
|
||||||
targetId: number | null;
|
|
||||||
oldValue: string | null;
|
|
||||||
newValue: string | null;
|
|
||||||
}[];
|
|
||||||
total: number;
|
|
||||||
page: number;
|
|
||||||
pageSize: number;
|
|
||||||
}>;
|
|
||||||
getLogById(tenantId: number | null, id: number): Promise<{
|
|
||||||
oldValue: any;
|
|
||||||
newValue: any;
|
|
||||||
id: number;
|
|
||||||
tenantId: number | null;
|
|
||||||
description: string;
|
|
||||||
createdAt: Date;
|
|
||||||
ipAddress: string | null;
|
|
||||||
userAgent: string | null;
|
|
||||||
userId: number;
|
|
||||||
userType: string;
|
|
||||||
action: string;
|
|
||||||
module: string;
|
|
||||||
targetId: number | null;
|
|
||||||
}>;
|
|
||||||
getModuleStats(tenantId: number | null, startDate?: string, endDate?: string): Promise<{
|
|
||||||
modules: {
|
|
||||||
name: string;
|
|
||||||
count: number;
|
|
||||||
}[];
|
|
||||||
actions: {
|
|
||||||
name: string;
|
|
||||||
count: number;
|
|
||||||
}[];
|
|
||||||
total: number;
|
|
||||||
}>;
|
|
||||||
private safeParseJson;
|
|
||||||
}
|
|
||||||
@ -1,134 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
||||||
};
|
|
||||||
var OperationLogService_1;
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.OperationLogService = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const prisma_service_1 = require("../../database/prisma.service");
|
|
||||||
let OperationLogService = OperationLogService_1 = class OperationLogService {
|
|
||||||
constructor(prisma) {
|
|
||||||
this.prisma = prisma;
|
|
||||||
this.logger = new common_1.Logger(OperationLogService_1.name);
|
|
||||||
}
|
|
||||||
async getLogs(tenantId, query) {
|
|
||||||
const { page = 1, pageSize = 20, userId, userType, action, module, startDate, endDate, } = query;
|
|
||||||
const skip = (page - 1) * pageSize;
|
|
||||||
const take = +pageSize;
|
|
||||||
const where = {};
|
|
||||||
if (tenantId !== null) {
|
|
||||||
where.tenantId = tenantId;
|
|
||||||
}
|
|
||||||
if (userId) {
|
|
||||||
where.userId = userId;
|
|
||||||
}
|
|
||||||
if (userType) {
|
|
||||||
where.userType = userType;
|
|
||||||
}
|
|
||||||
if (action) {
|
|
||||||
where.action = action;
|
|
||||||
}
|
|
||||||
if (module) {
|
|
||||||
where.module = module;
|
|
||||||
}
|
|
||||||
if (startDate || endDate) {
|
|
||||||
where.createdAt = {};
|
|
||||||
if (startDate) {
|
|
||||||
where.createdAt.gte = new Date(startDate);
|
|
||||||
}
|
|
||||||
if (endDate) {
|
|
||||||
where.createdAt.lte = new Date(endDate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const [items, total] = await Promise.all([
|
|
||||||
this.prisma.operationLog.findMany({
|
|
||||||
where,
|
|
||||||
skip,
|
|
||||||
take,
|
|
||||||
orderBy: { createdAt: 'desc' },
|
|
||||||
}),
|
|
||||||
this.prisma.operationLog.count({ where }),
|
|
||||||
]);
|
|
||||||
return {
|
|
||||||
items,
|
|
||||||
total,
|
|
||||||
page: +page,
|
|
||||||
pageSize: +pageSize,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
async getLogById(tenantId, id) {
|
|
||||||
const where = { id };
|
|
||||||
if (tenantId !== null) {
|
|
||||||
where.tenantId = tenantId;
|
|
||||||
}
|
|
||||||
const log = await this.prisma.operationLog.findFirst({
|
|
||||||
where,
|
|
||||||
});
|
|
||||||
if (!log) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
...log,
|
|
||||||
oldValue: log.oldValue ? this.safeParseJson(log.oldValue) : null,
|
|
||||||
newValue: log.newValue ? this.safeParseJson(log.newValue) : null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
async getModuleStats(tenantId, startDate, endDate) {
|
|
||||||
const where = {};
|
|
||||||
if (tenantId !== null) {
|
|
||||||
where.tenantId = tenantId;
|
|
||||||
}
|
|
||||||
if (startDate || endDate) {
|
|
||||||
where.createdAt = {};
|
|
||||||
if (startDate) {
|
|
||||||
where.createdAt.gte = new Date(startDate);
|
|
||||||
}
|
|
||||||
if (endDate) {
|
|
||||||
where.createdAt.lte = new Date(endDate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const logs = await this.prisma.operationLog.findMany({
|
|
||||||
where,
|
|
||||||
select: {
|
|
||||||
module: true,
|
|
||||||
action: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const moduleStats = new Map();
|
|
||||||
const actionStats = new Map();
|
|
||||||
logs.forEach((log) => {
|
|
||||||
moduleStats.set(log.module, (moduleStats.get(log.module) || 0) + 1);
|
|
||||||
actionStats.set(log.action, (actionStats.get(log.action) || 0) + 1);
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
modules: Array.from(moduleStats.entries())
|
|
||||||
.map(([name, count]) => ({ name, count }))
|
|
||||||
.sort((a, b) => b.count - a.count),
|
|
||||||
actions: Array.from(actionStats.entries())
|
|
||||||
.map(([name, count]) => ({ name, count }))
|
|
||||||
.sort((a, b) => b.count - a.count),
|
|
||||||
total: logs.length,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
safeParseJson(str) {
|
|
||||||
try {
|
|
||||||
return JSON.parse(str);
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.OperationLogService = OperationLogService;
|
|
||||||
exports.OperationLogService = OperationLogService = OperationLogService_1 = __decorate([
|
|
||||||
(0, common_1.Injectable)(),
|
|
||||||
__metadata("design:paramtypes", [prisma_service_1.PrismaService])
|
|
||||||
], OperationLogService);
|
|
||||||
//# sourceMappingURL=operation-log.service.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"operation-log.service.js","sourceRoot":"","sources":["../../../../src/modules/common/operation-log.service.ts"],"names":[],"mappings":"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"}
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
export interface ValidationResult {
|
|
||||||
valid: boolean;
|
|
||||||
errors: ValidationError[];
|
|
||||||
warnings: ValidationWarning[];
|
|
||||||
}
|
|
||||||
export interface ValidationError {
|
|
||||||
field: string;
|
|
||||||
message: string;
|
|
||||||
code: string;
|
|
||||||
}
|
|
||||||
export interface ValidationWarning {
|
|
||||||
field: string;
|
|
||||||
message: string;
|
|
||||||
code: string;
|
|
||||||
}
|
|
||||||
export interface CourseValidationData {
|
|
||||||
name?: string;
|
|
||||||
description?: string;
|
|
||||||
coverImagePath?: string;
|
|
||||||
gradeTags?: string;
|
|
||||||
domainTags?: string;
|
|
||||||
duration?: number;
|
|
||||||
ebookPaths?: string;
|
|
||||||
audioPaths?: string;
|
|
||||||
videoPaths?: string;
|
|
||||||
otherResources?: string;
|
|
||||||
scripts?: any[];
|
|
||||||
lessonPlanData?: string;
|
|
||||||
}
|
|
||||||
export declare class CourseValidationService {
|
|
||||||
private readonly logger;
|
|
||||||
validateForSubmit(course: CourseValidationData): Promise<ValidationResult>;
|
|
||||||
private validateBasicInfo;
|
|
||||||
private validateCover;
|
|
||||||
private validateGradeTags;
|
|
||||||
private validateDuration;
|
|
||||||
private validateResources;
|
|
||||||
private validateScripts;
|
|
||||||
private hasValidJsonArray;
|
|
||||||
canSubmit(course: CourseValidationData): Promise<boolean>;
|
|
||||||
getValidationSummary(result: ValidationResult): string;
|
|
||||||
}
|
|
||||||
@ -1,190 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
var CourseValidationService_1;
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.CourseValidationService = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
let CourseValidationService = CourseValidationService_1 = class CourseValidationService {
|
|
||||||
constructor() {
|
|
||||||
this.logger = new common_1.Logger(CourseValidationService_1.name);
|
|
||||||
}
|
|
||||||
async validateForSubmit(course) {
|
|
||||||
const errors = [];
|
|
||||||
const warnings = [];
|
|
||||||
this.validateBasicInfo(course, errors);
|
|
||||||
this.validateCover(course, errors);
|
|
||||||
this.validateGradeTags(course, errors);
|
|
||||||
this.validateDuration(course, errors);
|
|
||||||
this.validateResources(course, warnings);
|
|
||||||
this.validateScripts(course, errors);
|
|
||||||
const result = {
|
|
||||||
valid: errors.length === 0,
|
|
||||||
errors,
|
|
||||||
warnings,
|
|
||||||
};
|
|
||||||
this.logger.log(`Validation result: valid=${result.valid}, errors=${errors.length}, warnings=${warnings.length}`);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
validateBasicInfo(course, errors) {
|
|
||||||
if (!course.name || course.name.trim().length === 0) {
|
|
||||||
errors.push({
|
|
||||||
field: 'name',
|
|
||||||
message: '请输入课程名称',
|
|
||||||
code: 'NAME_REQUIRED',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (course.name.length < 2) {
|
|
||||||
errors.push({
|
|
||||||
field: 'name',
|
|
||||||
message: '课程名称至少需要2个字符',
|
|
||||||
code: 'NAME_TOO_SHORT',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (course.name.length > 50) {
|
|
||||||
errors.push({
|
|
||||||
field: 'name',
|
|
||||||
message: '课程名称不能超过50个字符',
|
|
||||||
code: 'NAME_TOO_LONG',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
validateCover(course, errors) {
|
|
||||||
if (!course.coverImagePath) {
|
|
||||||
errors.push({
|
|
||||||
field: 'coverImagePath',
|
|
||||||
message: '请上传课程封面',
|
|
||||||
code: 'COVER_REQUIRED',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
validateGradeTags(course, errors) {
|
|
||||||
if (!course.gradeTags) {
|
|
||||||
errors.push({
|
|
||||||
field: 'gradeTags',
|
|
||||||
message: '请选择适用年级',
|
|
||||||
code: 'GRADE_REQUIRED',
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const grades = JSON.parse(course.gradeTags);
|
|
||||||
if (!Array.isArray(grades) || grades.length === 0) {
|
|
||||||
errors.push({
|
|
||||||
field: 'gradeTags',
|
|
||||||
message: '请至少选择一个适用年级',
|
|
||||||
code: 'GRADE_EMPTY',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
errors.push({
|
|
||||||
field: 'gradeTags',
|
|
||||||
message: '年级标签格式错误',
|
|
||||||
code: 'GRADE_FORMAT_ERROR',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
validateDuration(course, errors) {
|
|
||||||
if (course.duration === undefined || course.duration === null) {
|
|
||||||
errors.push({
|
|
||||||
field: 'duration',
|
|
||||||
message: '请设置课程时长',
|
|
||||||
code: 'DURATION_REQUIRED',
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (course.duration < 5) {
|
|
||||||
errors.push({
|
|
||||||
field: 'duration',
|
|
||||||
message: '课程时长不能少于5分钟',
|
|
||||||
code: 'DURATION_TOO_SHORT',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (course.duration > 60) {
|
|
||||||
errors.push({
|
|
||||||
field: 'duration',
|
|
||||||
message: '课程时长不能超过60分钟',
|
|
||||||
code: 'DURATION_TOO_LONG',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
validateResources(course, warnings) {
|
|
||||||
const hasEbook = this.hasValidJsonArray(course.ebookPaths);
|
|
||||||
const hasAudio = this.hasValidJsonArray(course.audioPaths);
|
|
||||||
const hasVideo = this.hasValidJsonArray(course.videoPaths);
|
|
||||||
const hasOther = this.hasValidJsonArray(course.otherResources);
|
|
||||||
if (!hasEbook && !hasAudio && !hasVideo && !hasOther) {
|
|
||||||
warnings.push({
|
|
||||||
field: 'resources',
|
|
||||||
message: '建议上传至少1个数字资源(电子绘本、音频或视频)',
|
|
||||||
code: 'RESOURCES_SUGGESTED',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
validateScripts(course, errors) {
|
|
||||||
if (course.lessonPlanData) {
|
|
||||||
try {
|
|
||||||
const lessonPlan = JSON.parse(course.lessonPlanData);
|
|
||||||
if (!lessonPlan.phases || !Array.isArray(lessonPlan.phases) || lessonPlan.phases.length === 0) {
|
|
||||||
errors.push({
|
|
||||||
field: 'lessonPlanData',
|
|
||||||
message: '请至少配置一个教学环节',
|
|
||||||
code: 'SCRIPTS_REQUIRED',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
errors.push({
|
|
||||||
field: 'lessonPlanData',
|
|
||||||
message: '教学计划数据格式错误',
|
|
||||||
code: 'LESSON_PLAN_FORMAT_ERROR',
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (course.scripts !== undefined) {
|
|
||||||
if (!Array.isArray(course.scripts) || course.scripts.length === 0) {
|
|
||||||
errors.push({
|
|
||||||
field: 'scripts',
|
|
||||||
message: '请至少配置一个教学环节',
|
|
||||||
code: 'SCRIPTS_REQUIRED',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hasValidJsonArray(jsonStr) {
|
|
||||||
if (!jsonStr)
|
|
||||||
return false;
|
|
||||||
try {
|
|
||||||
const arr = JSON.parse(jsonStr);
|
|
||||||
return Array.isArray(arr) && arr.length > 0;
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async canSubmit(course) {
|
|
||||||
const result = await this.validateForSubmit(course);
|
|
||||||
return result.valid;
|
|
||||||
}
|
|
||||||
getValidationSummary(result) {
|
|
||||||
if (result.valid && result.warnings.length === 0) {
|
|
||||||
return '课程内容完整,可以提交审核';
|
|
||||||
}
|
|
||||||
if (result.valid && result.warnings.length > 0) {
|
|
||||||
return `课程可以提交,但有 ${result.warnings.length} 条建议`;
|
|
||||||
}
|
|
||||||
return `课程有 ${result.errors.length} 个问题需要修复`;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.CourseValidationService = CourseValidationService;
|
|
||||||
exports.CourseValidationService = CourseValidationService = CourseValidationService_1 = __decorate([
|
|
||||||
(0, common_1.Injectable)()
|
|
||||||
], CourseValidationService);
|
|
||||||
//# sourceMappingURL=course-validation.service.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
@ -1,625 +0,0 @@
|
|||||||
import { CourseService } from './course.service';
|
|
||||||
export declare class CourseController {
|
|
||||||
private readonly courseService;
|
|
||||||
constructor(courseService: CourseService);
|
|
||||||
findAll(query: any): Promise<{
|
|
||||||
items: {
|
|
||||||
id: number;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookName: string;
|
|
||||||
gradeTags: string;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date;
|
|
||||||
reviewedAt: Date;
|
|
||||||
reviewComment: string;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
}[];
|
|
||||||
total: number;
|
|
||||||
page: number;
|
|
||||||
pageSize: number;
|
|
||||||
}>;
|
|
||||||
getReviewList(query: any): Promise<{
|
|
||||||
items: {
|
|
||||||
id: number;
|
|
||||||
status: string;
|
|
||||||
name: string;
|
|
||||||
coverImagePath: string;
|
|
||||||
gradeTags: string;
|
|
||||||
submittedAt: Date;
|
|
||||||
submittedBy: number;
|
|
||||||
reviewedAt: Date;
|
|
||||||
reviewedBy: number;
|
|
||||||
reviewComment: string;
|
|
||||||
}[];
|
|
||||||
total: number;
|
|
||||||
page: number;
|
|
||||||
pageSize: number;
|
|
||||||
}>;
|
|
||||||
findOne(id: string): Promise<{
|
|
||||||
resources: {
|
|
||||||
id: number;
|
|
||||||
createdAt: Date;
|
|
||||||
sortOrder: number;
|
|
||||||
courseId: number;
|
|
||||||
resourceType: string;
|
|
||||||
resourceName: string;
|
|
||||||
fileUrl: string;
|
|
||||||
fileSize: number | null;
|
|
||||||
mimeType: string | null;
|
|
||||||
metadata: string | null;
|
|
||||||
}[];
|
|
||||||
scripts: ({
|
|
||||||
pages: {
|
|
||||||
id: number;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
resourceIds: string | null;
|
|
||||||
pageNumber: number;
|
|
||||||
scriptId: number;
|
|
||||||
questions: string | null;
|
|
||||||
interactionComponent: string | null;
|
|
||||||
teacherNotes: string | null;
|
|
||||||
}[];
|
|
||||||
} & {
|
|
||||||
id: number;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
duration: number;
|
|
||||||
sortOrder: number;
|
|
||||||
courseId: number;
|
|
||||||
stepIndex: number;
|
|
||||||
stepName: string;
|
|
||||||
stepType: string;
|
|
||||||
objective: string | null;
|
|
||||||
teacherScript: string | null;
|
|
||||||
interactionPoints: string | null;
|
|
||||||
resourceIds: string | null;
|
|
||||||
})[];
|
|
||||||
activities: {
|
|
||||||
id: number;
|
|
||||||
createdAt: Date;
|
|
||||||
name: string;
|
|
||||||
duration: number | null;
|
|
||||||
sortOrder: number;
|
|
||||||
courseId: number;
|
|
||||||
domain: string | null;
|
|
||||||
domainTagId: number | null;
|
|
||||||
activityType: string;
|
|
||||||
onlineMaterials: string | null;
|
|
||||||
offlineMaterials: string | null;
|
|
||||||
activityGuide: string | null;
|
|
||||||
objectives: string | null;
|
|
||||||
}[];
|
|
||||||
} & {
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
getStats(id: string): Promise<{
|
|
||||||
courseName: string;
|
|
||||||
totalLessons: number;
|
|
||||||
totalTeachers: number;
|
|
||||||
totalStudents: number;
|
|
||||||
avgRating: number;
|
|
||||||
lessonTrend: any[];
|
|
||||||
feedbackDistribution: {
|
|
||||||
designQuality: number;
|
|
||||||
participation: number;
|
|
||||||
goalAchievement: number;
|
|
||||||
totalFeedbacks: number;
|
|
||||||
};
|
|
||||||
recentLessons: any[];
|
|
||||||
studentPerformance: {
|
|
||||||
avgFocus: number;
|
|
||||||
avgParticipation: number;
|
|
||||||
avgInterest: number;
|
|
||||||
avgUnderstanding: number;
|
|
||||||
};
|
|
||||||
}>;
|
|
||||||
validate(id: string): Promise<import("./course-validation.service").ValidationResult>;
|
|
||||||
getVersionHistory(id: string): Promise<{
|
|
||||||
id: number;
|
|
||||||
version: string;
|
|
||||||
changeLog: string;
|
|
||||||
publishedAt: Date;
|
|
||||||
publishedBy: number;
|
|
||||||
}[]>;
|
|
||||||
create(createCourseDto: any, req: any): Promise<{
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
update(id: string, updateCourseDto: any): Promise<{
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
remove(id: string): Promise<{
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
submit(id: string, body: {
|
|
||||||
copyrightConfirmed: boolean;
|
|
||||||
}, req: any): Promise<{
|
|
||||||
validationSummary: string;
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
withdraw(id: string, req: any): Promise<{
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
approve(id: string, body: {
|
|
||||||
checklist?: any;
|
|
||||||
comment?: string;
|
|
||||||
}, req: any): Promise<{
|
|
||||||
authorizedTenantCount: number;
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
reject(id: string, body: {
|
|
||||||
checklist?: any;
|
|
||||||
comment: string;
|
|
||||||
}, req: any): Promise<{
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
directPublish(id: string, body: {
|
|
||||||
skipValidation?: boolean;
|
|
||||||
}, req: any): Promise<{
|
|
||||||
authorizedTenantCount: number;
|
|
||||||
validationSkipped: boolean;
|
|
||||||
validationWarnings: import("./course-validation.service").ValidationWarning[];
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
publish(id: string): Promise<{
|
|
||||||
authorizedTenantCount: number;
|
|
||||||
validationSkipped: boolean;
|
|
||||||
validationWarnings: import("./course-validation.service").ValidationWarning[];
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
unpublish(id: string): Promise<{
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
republish(id: string): Promise<{
|
|
||||||
authorizedTenantCount: number;
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
}
|
|
||||||
@ -1,223 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
||||||
};
|
|
||||||
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
||||||
return function (target, key) { decorator(target, key, paramIndex); }
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.CourseController = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const course_service_1 = require("./course.service");
|
|
||||||
const jwt_auth_guard_1 = require("../common/guards/jwt-auth.guard");
|
|
||||||
const roles_guard_1 = require("../common/guards/roles.guard");
|
|
||||||
const roles_decorator_1 = require("../common/decorators/roles.decorator");
|
|
||||||
let CourseController = class CourseController {
|
|
||||||
constructor(courseService) {
|
|
||||||
this.courseService = courseService;
|
|
||||||
}
|
|
||||||
findAll(query) {
|
|
||||||
return this.courseService.findAll(query);
|
|
||||||
}
|
|
||||||
getReviewList(query) {
|
|
||||||
return this.courseService.getReviewList(query);
|
|
||||||
}
|
|
||||||
findOne(id) {
|
|
||||||
return this.courseService.findOne(+id);
|
|
||||||
}
|
|
||||||
getStats(id) {
|
|
||||||
return this.courseService.getStats(+id);
|
|
||||||
}
|
|
||||||
validate(id) {
|
|
||||||
return this.courseService.validate(+id);
|
|
||||||
}
|
|
||||||
getVersionHistory(id) {
|
|
||||||
return this.courseService.getVersionHistory(+id);
|
|
||||||
}
|
|
||||||
create(createCourseDto, req) {
|
|
||||||
return this.courseService.create({
|
|
||||||
...createCourseDto,
|
|
||||||
createdBy: req.user?.userId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
update(id, updateCourseDto) {
|
|
||||||
return this.courseService.update(+id, updateCourseDto);
|
|
||||||
}
|
|
||||||
remove(id) {
|
|
||||||
return this.courseService.remove(+id);
|
|
||||||
}
|
|
||||||
submit(id, body, req) {
|
|
||||||
const userId = req.user?.userId || 0;
|
|
||||||
return this.courseService.submit(+id, userId, body.copyrightConfirmed);
|
|
||||||
}
|
|
||||||
withdraw(id, req) {
|
|
||||||
const userId = req.user?.userId || 0;
|
|
||||||
return this.courseService.withdraw(+id, userId);
|
|
||||||
}
|
|
||||||
approve(id, body, req) {
|
|
||||||
const reviewerId = req.user?.userId || 0;
|
|
||||||
return this.courseService.approve(+id, reviewerId, body);
|
|
||||||
}
|
|
||||||
reject(id, body, req) {
|
|
||||||
const reviewerId = req.user?.userId || 0;
|
|
||||||
return this.courseService.reject(+id, reviewerId, body);
|
|
||||||
}
|
|
||||||
directPublish(id, body, req) {
|
|
||||||
const userId = req.user?.userId || 0;
|
|
||||||
return this.courseService.directPublish(+id, userId, body.skipValidation);
|
|
||||||
}
|
|
||||||
publish(id) {
|
|
||||||
return this.courseService.publish(+id);
|
|
||||||
}
|
|
||||||
unpublish(id) {
|
|
||||||
return this.courseService.unpublish(+id);
|
|
||||||
}
|
|
||||||
republish(id) {
|
|
||||||
return this.courseService.republish(+id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.CourseController = CourseController;
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)(),
|
|
||||||
__param(0, (0, common_1.Query)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [Object]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], CourseController.prototype, "findAll", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)('review'),
|
|
||||||
__param(0, (0, common_1.Query)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [Object]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], CourseController.prototype, "getReviewList", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)(':id'),
|
|
||||||
__param(0, (0, common_1.Param)('id')),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [String]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], CourseController.prototype, "findOne", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)(':id/stats'),
|
|
||||||
__param(0, (0, common_1.Param)('id')),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [String]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], CourseController.prototype, "getStats", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)(':id/validate'),
|
|
||||||
__param(0, (0, common_1.Param)('id')),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [String]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], CourseController.prototype, "validate", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)(':id/versions'),
|
|
||||||
__param(0, (0, common_1.Param)('id')),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [String]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], CourseController.prototype, "getVersionHistory", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Post)(),
|
|
||||||
__param(0, (0, common_1.Body)()),
|
|
||||||
__param(1, (0, common_1.Request)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [Object, Object]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], CourseController.prototype, "create", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Put)(':id'),
|
|
||||||
__param(0, (0, common_1.Param)('id')),
|
|
||||||
__param(1, (0, common_1.Body)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [String, Object]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], CourseController.prototype, "update", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Delete)(':id'),
|
|
||||||
__param(0, (0, common_1.Param)('id')),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [String]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], CourseController.prototype, "remove", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Post)(':id/submit'),
|
|
||||||
__param(0, (0, common_1.Param)('id')),
|
|
||||||
__param(1, (0, common_1.Body)()),
|
|
||||||
__param(2, (0, common_1.Request)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [String, Object, Object]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], CourseController.prototype, "submit", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Post)(':id/withdraw'),
|
|
||||||
__param(0, (0, common_1.Param)('id')),
|
|
||||||
__param(1, (0, common_1.Request)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [String, Object]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], CourseController.prototype, "withdraw", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Post)(':id/approve'),
|
|
||||||
__param(0, (0, common_1.Param)('id')),
|
|
||||||
__param(1, (0, common_1.Body)()),
|
|
||||||
__param(2, (0, common_1.Request)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [String, Object, Object]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], CourseController.prototype, "approve", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Post)(':id/reject'),
|
|
||||||
__param(0, (0, common_1.Param)('id')),
|
|
||||||
__param(1, (0, common_1.Body)()),
|
|
||||||
__param(2, (0, common_1.Request)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [String, Object, Object]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], CourseController.prototype, "reject", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Post)(':id/direct-publish'),
|
|
||||||
(0, roles_decorator_1.Roles)('admin'),
|
|
||||||
__param(0, (0, common_1.Param)('id')),
|
|
||||||
__param(1, (0, common_1.Body)()),
|
|
||||||
__param(2, (0, common_1.Request)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [String, Object, Object]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], CourseController.prototype, "directPublish", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Post)(':id/publish'),
|
|
||||||
__param(0, (0, common_1.Param)('id')),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [String]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], CourseController.prototype, "publish", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Post)(':id/unpublish'),
|
|
||||||
__param(0, (0, common_1.Param)('id')),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [String]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], CourseController.prototype, "unpublish", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Post)(':id/republish'),
|
|
||||||
__param(0, (0, common_1.Param)('id')),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [String]),
|
|
||||||
__metadata("design:returntype", void 0)
|
|
||||||
], CourseController.prototype, "republish", null);
|
|
||||||
exports.CourseController = CourseController = __decorate([
|
|
||||||
(0, common_1.Controller)('courses'),
|
|
||||||
(0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard, roles_guard_1.RolesGuard),
|
|
||||||
(0, roles_decorator_1.Roles)('admin'),
|
|
||||||
__metadata("design:paramtypes", [course_service_1.CourseService])
|
|
||||||
], CourseController);
|
|
||||||
//# sourceMappingURL=course.controller.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"course.controller.js","sourceRoot":"","sources":["../../../../src/modules/course/course.controller.ts"],"names":[],"mappings":"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"}
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
export declare class CourseModule {
|
|
||||||
}
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.CourseModule = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const course_controller_1 = require("./course.controller");
|
|
||||||
const course_service_1 = require("./course.service");
|
|
||||||
const course_validation_service_1 = require("./course-validation.service");
|
|
||||||
const prisma_module_1 = require("../../database/prisma.module");
|
|
||||||
let CourseModule = class CourseModule {
|
|
||||||
};
|
|
||||||
exports.CourseModule = CourseModule;
|
|
||||||
exports.CourseModule = CourseModule = __decorate([
|
|
||||||
(0, common_1.Module)({
|
|
||||||
imports: [prisma_module_1.PrismaModule],
|
|
||||||
controllers: [course_controller_1.CourseController],
|
|
||||||
providers: [course_service_1.CourseService, course_validation_service_1.CourseValidationService],
|
|
||||||
exports: [course_service_1.CourseService, course_validation_service_1.CourseValidationService],
|
|
||||||
})
|
|
||||||
], CourseModule);
|
|
||||||
//# sourceMappingURL=course.module.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"course.module.js","sourceRoot":"","sources":["../../../../src/modules/course/course.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,2DAAuD;AACvD,qDAAiD;AACjD,2EAAsE;AACtE,gEAA4D;AAQrD,IAAM,YAAY,GAAlB,MAAM,YAAY;CAAG,CAAA;AAAf,oCAAY;uBAAZ,YAAY;IANxB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,4BAAY,CAAC;QACvB,WAAW,EAAE,CAAC,oCAAgB,CAAC;QAC/B,SAAS,EAAE,CAAC,8BAAa,EAAE,mDAAuB,CAAC;QACnD,OAAO,EAAE,CAAC,8BAAa,EAAE,mDAAuB,CAAC;KAClD,CAAC;GACW,YAAY,CAAG"}
|
|
||||||
@ -1,627 +0,0 @@
|
|||||||
import { PrismaService } from '../../database/prisma.service';
|
|
||||||
import { CourseValidationService, ValidationResult } from './course-validation.service';
|
|
||||||
export declare class CourseService {
|
|
||||||
private prisma;
|
|
||||||
private validationService;
|
|
||||||
private readonly logger;
|
|
||||||
constructor(prisma: PrismaService, validationService: CourseValidationService);
|
|
||||||
findAll(query: any): Promise<{
|
|
||||||
items: {
|
|
||||||
id: number;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookName: string;
|
|
||||||
gradeTags: string;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date;
|
|
||||||
reviewedAt: Date;
|
|
||||||
reviewComment: string;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
}[];
|
|
||||||
total: number;
|
|
||||||
page: number;
|
|
||||||
pageSize: number;
|
|
||||||
}>;
|
|
||||||
findOne(id: number): Promise<{
|
|
||||||
resources: {
|
|
||||||
id: number;
|
|
||||||
createdAt: Date;
|
|
||||||
sortOrder: number;
|
|
||||||
courseId: number;
|
|
||||||
resourceType: string;
|
|
||||||
resourceName: string;
|
|
||||||
fileUrl: string;
|
|
||||||
fileSize: number | null;
|
|
||||||
mimeType: string | null;
|
|
||||||
metadata: string | null;
|
|
||||||
}[];
|
|
||||||
scripts: ({
|
|
||||||
pages: {
|
|
||||||
id: number;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
resourceIds: string | null;
|
|
||||||
pageNumber: number;
|
|
||||||
scriptId: number;
|
|
||||||
questions: string | null;
|
|
||||||
interactionComponent: string | null;
|
|
||||||
teacherNotes: string | null;
|
|
||||||
}[];
|
|
||||||
} & {
|
|
||||||
id: number;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
duration: number;
|
|
||||||
sortOrder: number;
|
|
||||||
courseId: number;
|
|
||||||
stepIndex: number;
|
|
||||||
stepName: string;
|
|
||||||
stepType: string;
|
|
||||||
objective: string | null;
|
|
||||||
teacherScript: string | null;
|
|
||||||
interactionPoints: string | null;
|
|
||||||
resourceIds: string | null;
|
|
||||||
})[];
|
|
||||||
activities: {
|
|
||||||
id: number;
|
|
||||||
createdAt: Date;
|
|
||||||
name: string;
|
|
||||||
duration: number | null;
|
|
||||||
sortOrder: number;
|
|
||||||
courseId: number;
|
|
||||||
domain: string | null;
|
|
||||||
domainTagId: number | null;
|
|
||||||
activityType: string;
|
|
||||||
onlineMaterials: string | null;
|
|
||||||
offlineMaterials: string | null;
|
|
||||||
activityGuide: string | null;
|
|
||||||
objectives: string | null;
|
|
||||||
}[];
|
|
||||||
} & {
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
create(createCourseDto: any): Promise<{
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
update(id: number, updateCourseDto: any): Promise<{
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
private syncLessonPlanToScripts;
|
|
||||||
private syncActivitiesToTable;
|
|
||||||
private mapActivityType;
|
|
||||||
remove(id: number): Promise<{
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
validate(id: number): Promise<ValidationResult>;
|
|
||||||
submit(id: number, userId: number, copyrightConfirmed: boolean): Promise<{
|
|
||||||
validationSummary: string;
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
withdraw(id: number, userId: number): Promise<{
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
approve(id: number, reviewerId: number, reviewData: {
|
|
||||||
checklist?: any;
|
|
||||||
comment?: string;
|
|
||||||
}): Promise<{
|
|
||||||
authorizedTenantCount: number;
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
reject(id: number, reviewerId: number, reviewData: {
|
|
||||||
checklist?: any;
|
|
||||||
comment: string;
|
|
||||||
}): Promise<{
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
directPublish(id: number, userId: number, skipValidation?: boolean): Promise<{
|
|
||||||
authorizedTenantCount: number;
|
|
||||||
validationSkipped: boolean;
|
|
||||||
validationWarnings: import("./course-validation.service").ValidationWarning[];
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
publish(id: number): Promise<{
|
|
||||||
authorizedTenantCount: number;
|
|
||||||
validationSkipped: boolean;
|
|
||||||
validationWarnings: import("./course-validation.service").ValidationWarning[];
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
unpublish(id: number): Promise<{
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
republish(id: number): Promise<{
|
|
||||||
authorizedTenantCount: number;
|
|
||||||
id: number;
|
|
||||||
description: string | null;
|
|
||||||
createdBy: number | null;
|
|
||||||
status: string;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
name: string;
|
|
||||||
pictureBookId: number | null;
|
|
||||||
pictureBookName: string | null;
|
|
||||||
coverImagePath: string | null;
|
|
||||||
ebookPaths: string | null;
|
|
||||||
audioPaths: string | null;
|
|
||||||
videoPaths: string | null;
|
|
||||||
otherResources: string | null;
|
|
||||||
pptPath: string | null;
|
|
||||||
pptName: string | null;
|
|
||||||
posterPaths: string | null;
|
|
||||||
tools: string | null;
|
|
||||||
studentMaterials: string | null;
|
|
||||||
lessonPlanData: string | null;
|
|
||||||
activitiesData: string | null;
|
|
||||||
assessmentData: string | null;
|
|
||||||
gradeTags: string;
|
|
||||||
domainTags: string;
|
|
||||||
duration: number;
|
|
||||||
version: string;
|
|
||||||
submittedAt: Date | null;
|
|
||||||
submittedBy: number | null;
|
|
||||||
reviewedAt: Date | null;
|
|
||||||
reviewedBy: number | null;
|
|
||||||
reviewComment: string | null;
|
|
||||||
reviewChecklist: string | null;
|
|
||||||
parentId: number | null;
|
|
||||||
isLatest: boolean;
|
|
||||||
usageCount: number;
|
|
||||||
teacherCount: number;
|
|
||||||
avgRating: number;
|
|
||||||
publishedAt: Date | null;
|
|
||||||
}>;
|
|
||||||
getStats(id: number): Promise<{
|
|
||||||
courseName: string;
|
|
||||||
totalLessons: number;
|
|
||||||
totalTeachers: number;
|
|
||||||
totalStudents: number;
|
|
||||||
avgRating: number;
|
|
||||||
lessonTrend: any[];
|
|
||||||
feedbackDistribution: {
|
|
||||||
designQuality: number;
|
|
||||||
participation: number;
|
|
||||||
goalAchievement: number;
|
|
||||||
totalFeedbacks: number;
|
|
||||||
};
|
|
||||||
recentLessons: any[];
|
|
||||||
studentPerformance: {
|
|
||||||
avgFocus: number;
|
|
||||||
avgParticipation: number;
|
|
||||||
avgInterest: number;
|
|
||||||
avgUnderstanding: number;
|
|
||||||
};
|
|
||||||
}>;
|
|
||||||
getReviewList(query: any): Promise<{
|
|
||||||
items: {
|
|
||||||
id: number;
|
|
||||||
status: string;
|
|
||||||
name: string;
|
|
||||||
coverImagePath: string;
|
|
||||||
gradeTags: string;
|
|
||||||
submittedAt: Date;
|
|
||||||
submittedBy: number;
|
|
||||||
reviewedAt: Date;
|
|
||||||
reviewedBy: number;
|
|
||||||
reviewComment: string;
|
|
||||||
}[];
|
|
||||||
total: number;
|
|
||||||
page: number;
|
|
||||||
pageSize: number;
|
|
||||||
}>;
|
|
||||||
getVersionHistory(id: number): Promise<{
|
|
||||||
id: number;
|
|
||||||
version: string;
|
|
||||||
changeLog: string;
|
|
||||||
publishedAt: Date;
|
|
||||||
publishedBy: number;
|
|
||||||
}[]>;
|
|
||||||
}
|
|
||||||
@ -1,750 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
||||||
};
|
|
||||||
var CourseService_1;
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.CourseService = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const prisma_service_1 = require("../../database/prisma.service");
|
|
||||||
const course_validation_service_1 = require("./course-validation.service");
|
|
||||||
let CourseService = CourseService_1 = class CourseService {
|
|
||||||
constructor(prisma, validationService) {
|
|
||||||
this.prisma = prisma;
|
|
||||||
this.validationService = validationService;
|
|
||||||
this.logger = new common_1.Logger(CourseService_1.name);
|
|
||||||
}
|
|
||||||
async findAll(query) {
|
|
||||||
const { page = 1, pageSize = 10, grade, status, keyword } = query;
|
|
||||||
const skip = (page - 1) * pageSize;
|
|
||||||
const take = +pageSize;
|
|
||||||
const where = {};
|
|
||||||
if (status) {
|
|
||||||
where.status = status;
|
|
||||||
}
|
|
||||||
if (keyword) {
|
|
||||||
where.name = { contains: keyword };
|
|
||||||
}
|
|
||||||
if (grade) {
|
|
||||||
const gradeUpper = grade.toUpperCase();
|
|
||||||
where.OR = [
|
|
||||||
{ gradeTags: { contains: gradeUpper } },
|
|
||||||
{ gradeTags: { contains: grade.toLowerCase() } },
|
|
||||||
];
|
|
||||||
}
|
|
||||||
const [items, total] = await Promise.all([
|
|
||||||
this.prisma.course.findMany({
|
|
||||||
where,
|
|
||||||
skip,
|
|
||||||
take,
|
|
||||||
orderBy: { createdAt: 'desc' },
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
name: true,
|
|
||||||
pictureBookName: true,
|
|
||||||
gradeTags: true,
|
|
||||||
status: true,
|
|
||||||
version: true,
|
|
||||||
usageCount: true,
|
|
||||||
teacherCount: true,
|
|
||||||
avgRating: true,
|
|
||||||
createdAt: true,
|
|
||||||
submittedAt: true,
|
|
||||||
reviewedAt: true,
|
|
||||||
reviewComment: true,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
this.prisma.course.count({ where }),
|
|
||||||
]);
|
|
||||||
return {
|
|
||||||
items,
|
|
||||||
total,
|
|
||||||
page: +page,
|
|
||||||
pageSize: +pageSize,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
async findOne(id) {
|
|
||||||
const course = await this.prisma.course.findUnique({
|
|
||||||
where: { id },
|
|
||||||
include: {
|
|
||||||
resources: {
|
|
||||||
orderBy: { sortOrder: 'asc' },
|
|
||||||
},
|
|
||||||
scripts: {
|
|
||||||
orderBy: { sortOrder: 'asc' },
|
|
||||||
include: {
|
|
||||||
pages: {
|
|
||||||
orderBy: { pageNumber: 'asc' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
activities: {
|
|
||||||
orderBy: { sortOrder: 'asc' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (!course) {
|
|
||||||
throw new common_1.NotFoundException(`Course #${id} not found`);
|
|
||||||
}
|
|
||||||
return course;
|
|
||||||
}
|
|
||||||
async create(createCourseDto) {
|
|
||||||
try {
|
|
||||||
this.logger.log(`Creating course with data: ${JSON.stringify(createCourseDto)}`);
|
|
||||||
const result = await this.prisma.course.create({
|
|
||||||
data: createCourseDto,
|
|
||||||
});
|
|
||||||
this.logger.log(`Course created successfully with ID: ${result.id}`);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
this.logger.error(`Error creating course: ${error.message}`, error.stack);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async update(id, updateCourseDto) {
|
|
||||||
const fieldsToClear = [
|
|
||||||
'coverImagePath',
|
|
||||||
'ebookPaths',
|
|
||||||
'audioPaths',
|
|
||||||
'videoPaths',
|
|
||||||
'otherResources',
|
|
||||||
'pptPath',
|
|
||||||
'pptName',
|
|
||||||
'posterPaths',
|
|
||||||
'tools',
|
|
||||||
'studentMaterials',
|
|
||||||
'pictureBookName',
|
|
||||||
'lessonPlanData',
|
|
||||||
'activitiesData',
|
|
||||||
'assessmentData',
|
|
||||||
];
|
|
||||||
const cleanedData = {};
|
|
||||||
for (const [key, value] of Object.entries(updateCourseDto)) {
|
|
||||||
if (fieldsToClear.includes(key) && (value === null || value === '')) {
|
|
||||||
cleanedData[key] = null;
|
|
||||||
}
|
|
||||||
else if (value !== undefined) {
|
|
||||||
cleanedData[key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.logger.log(`Updating course ${id} with data: ${JSON.stringify(Object.keys(cleanedData))}`);
|
|
||||||
return this.prisma.$transaction(async (tx) => {
|
|
||||||
const updatedCourse = await tx.course.update({
|
|
||||||
where: { id },
|
|
||||||
data: cleanedData,
|
|
||||||
});
|
|
||||||
if (updateCourseDto.lessonPlanData !== undefined) {
|
|
||||||
await this.syncLessonPlanToScripts(tx, id, updateCourseDto.lessonPlanData);
|
|
||||||
}
|
|
||||||
if (updateCourseDto.activitiesData !== undefined) {
|
|
||||||
await this.syncActivitiesToTable(tx, id, updateCourseDto.activitiesData);
|
|
||||||
}
|
|
||||||
return updatedCourse;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
async syncLessonPlanToScripts(tx, courseId, lessonPlanData) {
|
|
||||||
await tx.courseScriptPage.deleteMany({
|
|
||||||
where: { script: { courseId } },
|
|
||||||
});
|
|
||||||
await tx.courseScript.deleteMany({
|
|
||||||
where: { courseId },
|
|
||||||
});
|
|
||||||
if (!lessonPlanData) {
|
|
||||||
this.logger.log(`Course ${courseId}: lessonPlanData is null, cleared scripts`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const lessonPlan = JSON.parse(lessonPlanData);
|
|
||||||
const phases = lessonPlan.phases || [];
|
|
||||||
const topLevelScriptPages = lessonPlan.scriptPages || [];
|
|
||||||
this.logger.log(`=== 同步课程 ${courseId} 的教学脚本 ===`);
|
|
||||||
this.logger.log(`phases 数量: ${phases.length}`);
|
|
||||||
this.logger.log(`顶层 scriptPages 数量: ${topLevelScriptPages.length}`);
|
|
||||||
for (let i = 0; i < phases.length; i++) {
|
|
||||||
const phase = phases[i];
|
|
||||||
this.logger.log(`Phase ${i}: name=${phase.name}, pages=${phase.pages?.length || 0}, enablePageScript=${phase.enablePageScript}`);
|
|
||||||
const script = await tx.courseScript.create({
|
|
||||||
data: {
|
|
||||||
courseId,
|
|
||||||
stepIndex: i + 1,
|
|
||||||
stepName: phase.name || `步骤${i + 1}`,
|
|
||||||
stepType: phase.type || 'CUSTOM',
|
|
||||||
duration: phase.duration || 5,
|
|
||||||
objective: phase.objective || null,
|
|
||||||
teacherScript: phase.content || null,
|
|
||||||
interactionPoints: null,
|
|
||||||
resourceIds: phase.resourceIds ? JSON.stringify(phase.resourceIds) : null,
|
|
||||||
sortOrder: i,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
let pagesToCreate = phase.pages || [];
|
|
||||||
if (pagesToCreate.length === 0 && topLevelScriptPages.length > 0 && i === 0) {
|
|
||||||
pagesToCreate = topLevelScriptPages;
|
|
||||||
}
|
|
||||||
if (pagesToCreate.length > 0) {
|
|
||||||
this.logger.log(`为 Phase ${i} 创建 ${pagesToCreate.length} 页逐页脚本`);
|
|
||||||
for (const page of pagesToCreate) {
|
|
||||||
await tx.courseScriptPage.create({
|
|
||||||
data: {
|
|
||||||
scriptId: script.id,
|
|
||||||
pageNumber: page.pageNumber,
|
|
||||||
questions: page.teacherScript || null,
|
|
||||||
interactionComponent: page.actions ? JSON.stringify(page.actions) : null,
|
|
||||||
teacherNotes: page.notes || null,
|
|
||||||
resourceIds: page.resourceIds ? JSON.stringify(page.resourceIds) : null,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.logger.log(`Course ${courseId}: synced ${phases.length} scripts from lessonPlanData`);
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
this.logger.error(`Failed to sync lessonPlanData for course ${courseId}: ${error.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async syncActivitiesToTable(tx, courseId, activitiesData) {
|
|
||||||
await tx.courseActivity.deleteMany({
|
|
||||||
where: { courseId },
|
|
||||||
});
|
|
||||||
if (!activitiesData) {
|
|
||||||
this.logger.log(`Course ${courseId}: activitiesData is null, cleared activities`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const activities = JSON.parse(activitiesData);
|
|
||||||
for (let i = 0; i < activities.length; i++) {
|
|
||||||
const activity = activities[i];
|
|
||||||
await tx.courseActivity.create({
|
|
||||||
data: {
|
|
||||||
courseId,
|
|
||||||
name: activity.name || `活动${i + 1}`,
|
|
||||||
domain: activity.domain || null,
|
|
||||||
domainTagId: null,
|
|
||||||
activityType: this.mapActivityType(activity.type),
|
|
||||||
duration: activity.duration || 15,
|
|
||||||
onlineMaterials: activity.content ? JSON.stringify({ content: activity.content }) : null,
|
|
||||||
offlineMaterials: activity.materials || null,
|
|
||||||
activityGuide: null,
|
|
||||||
objectives: null,
|
|
||||||
sortOrder: i,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.logger.log(`Course ${courseId}: synced ${activities.length} activities from activitiesData`);
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
this.logger.error(`Failed to sync activitiesData for course ${courseId}: ${error.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mapActivityType(type) {
|
|
||||||
const typeMap = {
|
|
||||||
'family': 'FAMILY',
|
|
||||||
'art': 'ART',
|
|
||||||
'game': 'GAME',
|
|
||||||
'outdoor': 'OUTDOOR',
|
|
||||||
'other': 'OTHER',
|
|
||||||
'handicraft': 'HANDICRAFT',
|
|
||||||
'music': 'MUSIC',
|
|
||||||
'exploration': 'EXPLORATION',
|
|
||||||
'sports': 'SPORTS',
|
|
||||||
'家庭延伸': 'FAMILY',
|
|
||||||
'美工活动': 'ART',
|
|
||||||
'游戏活动': 'GAME',
|
|
||||||
'户外活动': 'OUTDOOR',
|
|
||||||
'其他': 'OTHER',
|
|
||||||
'手工活动': 'HANDICRAFT',
|
|
||||||
'音乐活动': 'MUSIC',
|
|
||||||
'探索活动': 'EXPLORATION',
|
|
||||||
'运动活动': 'SPORTS',
|
|
||||||
'亲子活动': 'FAMILY',
|
|
||||||
};
|
|
||||||
return typeMap[type || ''] || 'OTHER';
|
|
||||||
}
|
|
||||||
async remove(id) {
|
|
||||||
return this.prisma.course.delete({
|
|
||||||
where: { id },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
async validate(id) {
|
|
||||||
const course = await this.findOne(id);
|
|
||||||
return this.validationService.validateForSubmit(course);
|
|
||||||
}
|
|
||||||
async submit(id, userId, copyrightConfirmed) {
|
|
||||||
const course = await this.prisma.course.findUnique({
|
|
||||||
where: { id },
|
|
||||||
});
|
|
||||||
if (!course) {
|
|
||||||
throw new common_1.NotFoundException(`Course #${id} not found`);
|
|
||||||
}
|
|
||||||
if (course.status !== 'DRAFT' && course.status !== 'REJECTED') {
|
|
||||||
throw new common_1.BadRequestException(`课程状态为 ${course.status},无法提交审核`);
|
|
||||||
}
|
|
||||||
const validationResult = await this.validationService.validateForSubmit(course);
|
|
||||||
if (!validationResult.valid) {
|
|
||||||
throw new common_1.BadRequestException({
|
|
||||||
message: '课程内容不完整,请检查以下问题',
|
|
||||||
errors: validationResult.errors,
|
|
||||||
warnings: validationResult.warnings,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!copyrightConfirmed) {
|
|
||||||
throw new common_1.BadRequestException('请确认版权合规');
|
|
||||||
}
|
|
||||||
const updatedCourse = await this.prisma.course.update({
|
|
||||||
where: { id },
|
|
||||||
data: {
|
|
||||||
status: 'PENDING',
|
|
||||||
submittedAt: new Date(),
|
|
||||||
submittedBy: userId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
this.logger.log(`Course ${id} submitted for review by user ${userId}`);
|
|
||||||
return {
|
|
||||||
...updatedCourse,
|
|
||||||
validationSummary: this.validationService.getValidationSummary(validationResult),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
async withdraw(id, userId) {
|
|
||||||
const course = await this.prisma.course.findUnique({
|
|
||||||
where: { id },
|
|
||||||
});
|
|
||||||
if (!course) {
|
|
||||||
throw new common_1.NotFoundException(`Course #${id} not found`);
|
|
||||||
}
|
|
||||||
if (course.status !== 'PENDING') {
|
|
||||||
throw new common_1.BadRequestException(`课程状态为 ${course.status},无法撤销`);
|
|
||||||
}
|
|
||||||
const updatedCourse = await this.prisma.course.update({
|
|
||||||
where: { id },
|
|
||||||
data: {
|
|
||||||
status: 'DRAFT',
|
|
||||||
submittedAt: null,
|
|
||||||
submittedBy: null,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
this.logger.log(`Course ${id} review withdrawn by user ${userId}`);
|
|
||||||
return updatedCourse;
|
|
||||||
}
|
|
||||||
async approve(id, reviewerId, reviewData) {
|
|
||||||
const course = await this.prisma.course.findUnique({
|
|
||||||
where: { id },
|
|
||||||
});
|
|
||||||
if (!course) {
|
|
||||||
throw new common_1.NotFoundException(`Course #${id} not found`);
|
|
||||||
}
|
|
||||||
if (course.status !== 'PENDING') {
|
|
||||||
throw new common_1.BadRequestException(`课程状态为 ${course.status},无法审核`);
|
|
||||||
}
|
|
||||||
if (course.submittedBy === reviewerId) {
|
|
||||||
throw new common_1.BadRequestException('不能审核自己提交的课程');
|
|
||||||
}
|
|
||||||
const result = await this.prisma.$transaction(async (tx) => {
|
|
||||||
const updatedCourse = await tx.course.update({
|
|
||||||
where: { id },
|
|
||||||
data: {
|
|
||||||
status: 'PUBLISHED',
|
|
||||||
reviewedAt: new Date(),
|
|
||||||
reviewedBy: reviewerId,
|
|
||||||
reviewComment: reviewData.comment || null,
|
|
||||||
reviewChecklist: reviewData.checklist ? JSON.stringify(reviewData.checklist) : null,
|
|
||||||
publishedAt: new Date(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
await tx.courseVersion.create({
|
|
||||||
data: {
|
|
||||||
courseId: id,
|
|
||||||
version: course.version,
|
|
||||||
snapshotData: JSON.stringify(course),
|
|
||||||
changeLog: reviewData.comment || '审核通过发布',
|
|
||||||
publishedBy: reviewerId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return updatedCourse;
|
|
||||||
});
|
|
||||||
const activeTenants = await this.prisma.tenant.findMany({
|
|
||||||
where: { status: 'ACTIVE' },
|
|
||||||
select: { id: true },
|
|
||||||
});
|
|
||||||
this.logger.log(`Publishing course ${id} to ${activeTenants.length} active tenants`);
|
|
||||||
for (const tenant of activeTenants) {
|
|
||||||
await this.prisma.tenantCourse.upsert({
|
|
||||||
where: {
|
|
||||||
tenantId_courseId: {
|
|
||||||
tenantId: tenant.id,
|
|
||||||
courseId: id,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
update: {
|
|
||||||
authorized: true,
|
|
||||||
authorizedAt: new Date(),
|
|
||||||
},
|
|
||||||
create: {
|
|
||||||
tenantId: tenant.id,
|
|
||||||
courseId: id,
|
|
||||||
authorized: true,
|
|
||||||
authorizedAt: new Date(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.logger.log(`Course ${id} approved and published by reviewer ${reviewerId}`);
|
|
||||||
return {
|
|
||||||
...result,
|
|
||||||
authorizedTenantCount: activeTenants.length,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
async reject(id, reviewerId, reviewData) {
|
|
||||||
const course = await this.prisma.course.findUnique({
|
|
||||||
where: { id },
|
|
||||||
});
|
|
||||||
if (!course) {
|
|
||||||
throw new common_1.NotFoundException(`Course #${id} not found`);
|
|
||||||
}
|
|
||||||
if (course.status !== 'PENDING') {
|
|
||||||
throw new common_1.BadRequestException(`课程状态为 ${course.status},无法审核`);
|
|
||||||
}
|
|
||||||
if (course.submittedBy === reviewerId) {
|
|
||||||
throw new common_1.BadRequestException('不能审核自己提交的课程');
|
|
||||||
}
|
|
||||||
if (!reviewData.comment || reviewData.comment.trim().length === 0) {
|
|
||||||
throw new common_1.BadRequestException('请填写驳回原因');
|
|
||||||
}
|
|
||||||
const updatedCourse = await this.prisma.course.update({
|
|
||||||
where: { id },
|
|
||||||
data: {
|
|
||||||
status: 'REJECTED',
|
|
||||||
reviewedAt: new Date(),
|
|
||||||
reviewedBy: reviewerId,
|
|
||||||
reviewComment: reviewData.comment,
|
|
||||||
reviewChecklist: reviewData.checklist ? JSON.stringify(reviewData.checklist) : null,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
this.logger.log(`Course ${id} rejected by reviewer ${reviewerId}: ${reviewData.comment}`);
|
|
||||||
return updatedCourse;
|
|
||||||
}
|
|
||||||
async directPublish(id, userId, skipValidation = false) {
|
|
||||||
const course = await this.prisma.course.findUnique({
|
|
||||||
where: { id },
|
|
||||||
});
|
|
||||||
if (!course) {
|
|
||||||
throw new common_1.NotFoundException(`Course #${id} not found`);
|
|
||||||
}
|
|
||||||
if (course.status === 'PUBLISHED') {
|
|
||||||
throw new common_1.BadRequestException('课程已发布');
|
|
||||||
}
|
|
||||||
const validationResult = await this.validationService.validateForSubmit(course);
|
|
||||||
if (!skipValidation && !validationResult.valid) {
|
|
||||||
throw new common_1.BadRequestException({
|
|
||||||
message: '课程内容不完整,请检查以下问题',
|
|
||||||
errors: validationResult.errors,
|
|
||||||
warnings: validationResult.warnings,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const result = await this.prisma.$transaction(async (tx) => {
|
|
||||||
const updatedCourse = await tx.course.update({
|
|
||||||
where: { id },
|
|
||||||
data: {
|
|
||||||
status: 'PUBLISHED',
|
|
||||||
publishedAt: new Date(),
|
|
||||||
reviewedAt: new Date(),
|
|
||||||
reviewedBy: userId,
|
|
||||||
reviewComment: '超级管理员直接发布',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
await tx.courseVersion.create({
|
|
||||||
data: {
|
|
||||||
courseId: id,
|
|
||||||
version: course.version,
|
|
||||||
snapshotData: JSON.stringify(course),
|
|
||||||
changeLog: '超级管理员直接发布',
|
|
||||||
publishedBy: userId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return updatedCourse;
|
|
||||||
});
|
|
||||||
const activeTenants = await this.prisma.tenant.findMany({
|
|
||||||
where: { status: 'ACTIVE' },
|
|
||||||
select: { id: true },
|
|
||||||
});
|
|
||||||
for (const tenant of activeTenants) {
|
|
||||||
await this.prisma.tenantCourse.upsert({
|
|
||||||
where: {
|
|
||||||
tenantId_courseId: {
|
|
||||||
tenantId: tenant.id,
|
|
||||||
courseId: id,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
update: {
|
|
||||||
authorized: true,
|
|
||||||
authorizedAt: new Date(),
|
|
||||||
},
|
|
||||||
create: {
|
|
||||||
tenantId: tenant.id,
|
|
||||||
courseId: id,
|
|
||||||
authorized: true,
|
|
||||||
authorizedAt: new Date(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.logger.log(`Course ${id} directly published by super admin ${userId}`);
|
|
||||||
return {
|
|
||||||
...result,
|
|
||||||
authorizedTenantCount: activeTenants.length,
|
|
||||||
validationSkipped: skipValidation && !validationResult.valid,
|
|
||||||
validationWarnings: validationResult.warnings,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
async publish(id) {
|
|
||||||
return this.directPublish(id, 0, false);
|
|
||||||
}
|
|
||||||
async unpublish(id) {
|
|
||||||
const course = await this.prisma.course.findUnique({
|
|
||||||
where: { id },
|
|
||||||
});
|
|
||||||
if (!course) {
|
|
||||||
throw new common_1.NotFoundException(`Course #${id} not found`);
|
|
||||||
}
|
|
||||||
if (course.status !== 'PUBLISHED') {
|
|
||||||
throw new common_1.BadRequestException(`课程状态为 ${course.status},无法下架`);
|
|
||||||
}
|
|
||||||
const updatedCourse = await this.prisma.course.update({
|
|
||||||
where: { id },
|
|
||||||
data: {
|
|
||||||
status: 'ARCHIVED',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
await this.prisma.tenantCourse.updateMany({
|
|
||||||
where: { courseId: id },
|
|
||||||
data: {
|
|
||||||
authorized: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
this.logger.log(`Course ${id} unpublished`);
|
|
||||||
return updatedCourse;
|
|
||||||
}
|
|
||||||
async republish(id) {
|
|
||||||
const course = await this.prisma.course.findUnique({
|
|
||||||
where: { id },
|
|
||||||
});
|
|
||||||
if (!course) {
|
|
||||||
throw new common_1.NotFoundException(`Course #${id} not found`);
|
|
||||||
}
|
|
||||||
if (course.status !== 'ARCHIVED') {
|
|
||||||
throw new common_1.BadRequestException(`课程状态为 ${course.status},无法重新发布`);
|
|
||||||
}
|
|
||||||
const updatedCourse = await this.prisma.course.update({
|
|
||||||
where: { id },
|
|
||||||
data: {
|
|
||||||
status: 'PUBLISHED',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const activeTenants = await this.prisma.tenant.findMany({
|
|
||||||
where: { status: 'ACTIVE' },
|
|
||||||
select: { id: true },
|
|
||||||
});
|
|
||||||
for (const tenant of activeTenants) {
|
|
||||||
await this.prisma.tenantCourse.upsert({
|
|
||||||
where: {
|
|
||||||
tenantId_courseId: {
|
|
||||||
tenantId: tenant.id,
|
|
||||||
courseId: id,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
update: {
|
|
||||||
authorized: true,
|
|
||||||
authorizedAt: new Date(),
|
|
||||||
},
|
|
||||||
create: {
|
|
||||||
tenantId: tenant.id,
|
|
||||||
courseId: id,
|
|
||||||
authorized: true,
|
|
||||||
authorizedAt: new Date(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.logger.log(`Course ${id} republished`);
|
|
||||||
return {
|
|
||||||
...updatedCourse,
|
|
||||||
authorizedTenantCount: activeTenants.length,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
async getStats(id) {
|
|
||||||
const course = await this.prisma.course.findUnique({
|
|
||||||
where: { id },
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
name: true,
|
|
||||||
usageCount: true,
|
|
||||||
teacherCount: true,
|
|
||||||
avgRating: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (!course) {
|
|
||||||
throw new common_1.NotFoundException(`Course #${id} not found`);
|
|
||||||
}
|
|
||||||
const lessons = await this.prisma.lesson.findMany({
|
|
||||||
where: { courseId: id },
|
|
||||||
include: {
|
|
||||||
teacher: {
|
|
||||||
select: { id: true, name: true },
|
|
||||||
},
|
|
||||||
class: {
|
|
||||||
select: { id: true, name: true },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
orderBy: { createdAt: 'desc' },
|
|
||||||
take: 10,
|
|
||||||
});
|
|
||||||
const feedbacks = await this.prisma.lessonFeedback.findMany({
|
|
||||||
where: {
|
|
||||||
lesson: {
|
|
||||||
courseId: id,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const calculateAverage = (field) => {
|
|
||||||
const validFeedbacks = feedbacks.filter((f) => f[field] != null);
|
|
||||||
if (validFeedbacks.length === 0)
|
|
||||||
return 0;
|
|
||||||
const sum = validFeedbacks.reduce((acc, f) => acc + f[field], 0);
|
|
||||||
return sum / validFeedbacks.length;
|
|
||||||
};
|
|
||||||
const studentRecords = await this.prisma.studentRecord.findMany({
|
|
||||||
where: {
|
|
||||||
lesson: {
|
|
||||||
courseId: id,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const calculateStudentAvg = (field) => {
|
|
||||||
const validRecords = studentRecords.filter((r) => r[field] != null);
|
|
||||||
if (validRecords.length === 0)
|
|
||||||
return 0;
|
|
||||||
const sum = validRecords.reduce((acc, r) => acc + r[field], 0);
|
|
||||||
return sum / validRecords.length;
|
|
||||||
};
|
|
||||||
const now = new Date();
|
|
||||||
const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
|
|
||||||
const recentLessons = await this.prisma.lesson.findMany({
|
|
||||||
where: {
|
|
||||||
courseId: id,
|
|
||||||
createdAt: { gte: weekAgo },
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
createdAt: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const lessonTrend = [];
|
|
||||||
for (let i = 6; i >= 0; i--) {
|
|
||||||
const date = new Date(now.getTime() - i * 24 * 60 * 60 * 1000);
|
|
||||||
const dateStr = date.toLocaleDateString('zh-CN', { weekday: 'short' });
|
|
||||||
const count = recentLessons.filter((lesson) => {
|
|
||||||
const lessonDate = new Date(lesson.createdAt);
|
|
||||||
return lessonDate.toDateString() === date.toDateString();
|
|
||||||
}).length;
|
|
||||||
lessonTrend.push({ date: dateStr, count });
|
|
||||||
}
|
|
||||||
const uniqueStudentIds = new Set();
|
|
||||||
lessons.forEach((lesson) => {
|
|
||||||
uniqueStudentIds.add(lesson.classId);
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
courseName: course.name,
|
|
||||||
totalLessons: course.usageCount || lessons.length,
|
|
||||||
totalTeachers: course.teacherCount || new Set(lessons.map((l) => l.teacherId)).size,
|
|
||||||
totalStudents: uniqueStudentIds.size,
|
|
||||||
avgRating: course.avgRating || 0,
|
|
||||||
lessonTrend,
|
|
||||||
feedbackDistribution: {
|
|
||||||
designQuality: calculateAverage('designQuality'),
|
|
||||||
participation: calculateAverage('participation'),
|
|
||||||
goalAchievement: calculateAverage('goalAchievement'),
|
|
||||||
totalFeedbacks: feedbacks.length,
|
|
||||||
},
|
|
||||||
recentLessons: lessons.map((lesson) => ({
|
|
||||||
...lesson,
|
|
||||||
date: lesson.createdAt,
|
|
||||||
})),
|
|
||||||
studentPerformance: {
|
|
||||||
avgFocus: calculateStudentAvg('focus'),
|
|
||||||
avgParticipation: calculateStudentAvg('participation'),
|
|
||||||
avgInterest: calculateStudentAvg('interest'),
|
|
||||||
avgUnderstanding: calculateStudentAvg('understanding'),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
async getReviewList(query) {
|
|
||||||
const { page = 1, pageSize = 10, status, submittedBy } = query;
|
|
||||||
const skip = (page - 1) * pageSize;
|
|
||||||
const take = +pageSize;
|
|
||||||
const where = {
|
|
||||||
status: { in: ['PENDING', 'REJECTED'] },
|
|
||||||
};
|
|
||||||
if (status) {
|
|
||||||
where.status = status;
|
|
||||||
}
|
|
||||||
if (submittedBy) {
|
|
||||||
where.submittedBy = +submittedBy;
|
|
||||||
}
|
|
||||||
const [items, total] = await Promise.all([
|
|
||||||
this.prisma.course.findMany({
|
|
||||||
where,
|
|
||||||
skip,
|
|
||||||
take,
|
|
||||||
orderBy: { submittedAt: 'desc' },
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
name: true,
|
|
||||||
status: true,
|
|
||||||
submittedAt: true,
|
|
||||||
submittedBy: true,
|
|
||||||
reviewedAt: true,
|
|
||||||
reviewedBy: true,
|
|
||||||
reviewComment: true,
|
|
||||||
coverImagePath: true,
|
|
||||||
gradeTags: true,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
this.prisma.course.count({ where }),
|
|
||||||
]);
|
|
||||||
return {
|
|
||||||
items,
|
|
||||||
total,
|
|
||||||
page: +page,
|
|
||||||
pageSize: +pageSize,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
async getVersionHistory(id) {
|
|
||||||
const course = await this.prisma.course.findUnique({
|
|
||||||
where: { id },
|
|
||||||
});
|
|
||||||
if (!course) {
|
|
||||||
throw new common_1.NotFoundException(`Course #${id} not found`);
|
|
||||||
}
|
|
||||||
const versions = await this.prisma.courseVersion.findMany({
|
|
||||||
where: { courseId: id },
|
|
||||||
orderBy: { publishedAt: 'desc' },
|
|
||||||
});
|
|
||||||
return versions.map((v) => ({
|
|
||||||
id: v.id,
|
|
||||||
version: v.version,
|
|
||||||
changeLog: v.changeLog,
|
|
||||||
publishedAt: v.publishedAt,
|
|
||||||
publishedBy: v.publishedBy,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.CourseService = CourseService;
|
|
||||||
exports.CourseService = CourseService = CourseService_1 = __decorate([
|
|
||||||
(0, common_1.Injectable)(),
|
|
||||||
__metadata("design:paramtypes", [prisma_service_1.PrismaService,
|
|
||||||
course_validation_service_1.CourseValidationService])
|
|
||||||
], CourseService);
|
|
||||||
//# sourceMappingURL=course.service.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
@ -1,10 +0,0 @@
|
|||||||
import { Response } from 'express';
|
|
||||||
import { ExportService } from './export.service';
|
|
||||||
export declare class ExportController {
|
|
||||||
private readonly exportService;
|
|
||||||
constructor(exportService: ExportService);
|
|
||||||
exportTeachers(req: any, res: Response): Promise<void>;
|
|
||||||
exportStudents(req: any, res: Response): Promise<void>;
|
|
||||||
exportLessons(req: any, res: Response): Promise<void>;
|
|
||||||
exportGrowthRecords(req: any, studentId: string, res: Response): Promise<void>;
|
|
||||||
}
|
|
||||||
@ -1,90 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
||||||
};
|
|
||||||
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
||||||
return function (target, key) { decorator(target, key, paramIndex); }
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.ExportController = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const export_service_1 = require("./export.service");
|
|
||||||
const jwt_auth_guard_1 = require("../common/guards/jwt-auth.guard");
|
|
||||||
const roles_guard_1 = require("../common/guards/roles.guard");
|
|
||||||
const roles_decorator_1 = require("../common/decorators/roles.decorator");
|
|
||||||
let ExportController = class ExportController {
|
|
||||||
constructor(exportService) {
|
|
||||||
this.exportService = exportService;
|
|
||||||
}
|
|
||||||
async exportTeachers(req, res) {
|
|
||||||
const buffer = await this.exportService.exportTeachers(req.user.tenantId);
|
|
||||||
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
|
||||||
res.setHeader('Content-Disposition', `attachment; filename=teachers_${Date.now()}.xlsx`);
|
|
||||||
res.send(buffer);
|
|
||||||
}
|
|
||||||
async exportStudents(req, res) {
|
|
||||||
const buffer = await this.exportService.exportStudents(req.user.tenantId);
|
|
||||||
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
|
||||||
res.setHeader('Content-Disposition', `attachment; filename=students_${Date.now()}.xlsx`);
|
|
||||||
res.send(buffer);
|
|
||||||
}
|
|
||||||
async exportLessons(req, res) {
|
|
||||||
const buffer = await this.exportService.exportLessons(req.user.tenantId);
|
|
||||||
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
|
||||||
res.setHeader('Content-Disposition', `attachment; filename=lessons_${Date.now()}.xlsx`);
|
|
||||||
res.send(buffer);
|
|
||||||
}
|
|
||||||
async exportGrowthRecords(req, studentId, res) {
|
|
||||||
const buffer = await this.exportService.exportGrowthRecords(req.user.tenantId, studentId ? +studentId : undefined);
|
|
||||||
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
|
||||||
res.setHeader('Content-Disposition', `attachment; filename=growth_records_${Date.now()}.xlsx`);
|
|
||||||
res.send(buffer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.ExportController = ExportController;
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)('teachers'),
|
|
||||||
__param(0, (0, common_1.Request)()),
|
|
||||||
__param(1, (0, common_1.Res)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [Object, Object]),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], ExportController.prototype, "exportTeachers", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)('students'),
|
|
||||||
__param(0, (0, common_1.Request)()),
|
|
||||||
__param(1, (0, common_1.Res)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [Object, Object]),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], ExportController.prototype, "exportStudents", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)('lessons'),
|
|
||||||
__param(0, (0, common_1.Request)()),
|
|
||||||
__param(1, (0, common_1.Res)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [Object, Object]),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], ExportController.prototype, "exportLessons", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Get)('growth-records'),
|
|
||||||
__param(0, (0, common_1.Request)()),
|
|
||||||
__param(1, (0, common_1.Query)('studentId')),
|
|
||||||
__param(2, (0, common_1.Res)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [Object, String, Object]),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], ExportController.prototype, "exportGrowthRecords", null);
|
|
||||||
exports.ExportController = ExportController = __decorate([
|
|
||||||
(0, common_1.Controller)('school/export'),
|
|
||||||
(0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard, roles_guard_1.RolesGuard),
|
|
||||||
(0, roles_decorator_1.Roles)('school'),
|
|
||||||
__metadata("design:paramtypes", [export_service_1.ExportService])
|
|
||||||
], ExportController);
|
|
||||||
//# sourceMappingURL=export.controller.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"export.controller.js","sourceRoot":"","sources":["../../../../src/modules/export/export.controller.ts"],"names":[],"mappings":"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"}
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
export declare class ExportModule {
|
|
||||||
}
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.ExportModule = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const export_controller_1 = require("./export.controller");
|
|
||||||
const export_service_1 = require("./export.service");
|
|
||||||
let ExportModule = class ExportModule {
|
|
||||||
};
|
|
||||||
exports.ExportModule = ExportModule;
|
|
||||||
exports.ExportModule = ExportModule = __decorate([
|
|
||||||
(0, common_1.Module)({
|
|
||||||
controllers: [export_controller_1.ExportController],
|
|
||||||
providers: [export_service_1.ExportService],
|
|
||||||
exports: [export_service_1.ExportService],
|
|
||||||
})
|
|
||||||
], ExportModule);
|
|
||||||
//# sourceMappingURL=export.module.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"export.module.js","sourceRoot":"","sources":["../../../../src/modules/export/export.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,2DAAuD;AACvD,qDAAiD;AAO1C,IAAM,YAAY,GAAlB,MAAM,YAAY;CAAG,CAAA;AAAf,oCAAY;uBAAZ,YAAY;IALxB,IAAA,eAAM,EAAC;QACN,WAAW,EAAE,CAAC,oCAAgB,CAAC;QAC/B,SAAS,EAAE,CAAC,8BAAa,CAAC;QAC1B,OAAO,EAAE,CAAC,8BAAa,CAAC;KACzB,CAAC;GACW,YAAY,CAAG"}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
import { PrismaService } from '../../database/prisma.service';
|
|
||||||
export declare class ExportService {
|
|
||||||
private prisma;
|
|
||||||
private readonly logger;
|
|
||||||
constructor(prisma: PrismaService);
|
|
||||||
exportTeachers(tenantId: number): Promise<Buffer>;
|
|
||||||
exportStudents(tenantId: number): Promise<Buffer>;
|
|
||||||
exportLessons(tenantId: number): Promise<Buffer>;
|
|
||||||
exportGrowthRecords(tenantId: number, studentId?: number): Promise<Buffer>;
|
|
||||||
}
|
|
||||||
@ -1,260 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
||||||
if (k2 === undefined) k2 = k;
|
|
||||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
||||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
||||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
||||||
}
|
|
||||||
Object.defineProperty(o, k2, desc);
|
|
||||||
}) : (function(o, m, k, k2) {
|
|
||||||
if (k2 === undefined) k2 = k;
|
|
||||||
o[k2] = m[k];
|
|
||||||
}));
|
|
||||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
||||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
||||||
}) : function(o, v) {
|
|
||||||
o["default"] = v;
|
|
||||||
});
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
var __importStar = (this && this.__importStar) || function (mod) {
|
|
||||||
if (mod && mod.__esModule) return mod;
|
|
||||||
var result = {};
|
|
||||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
||||||
__setModuleDefault(result, mod);
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
||||||
};
|
|
||||||
var ExportService_1;
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.ExportService = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const prisma_service_1 = require("../../database/prisma.service");
|
|
||||||
const ExcelJS = __importStar(require("exceljs"));
|
|
||||||
let ExportService = ExportService_1 = class ExportService {
|
|
||||||
constructor(prisma) {
|
|
||||||
this.prisma = prisma;
|
|
||||||
this.logger = new common_1.Logger(ExportService_1.name);
|
|
||||||
}
|
|
||||||
async exportTeachers(tenantId) {
|
|
||||||
const teachers = await this.prisma.teacher.findMany({
|
|
||||||
where: { tenantId },
|
|
||||||
include: {
|
|
||||||
classes: {
|
|
||||||
select: { name: true },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
orderBy: { createdAt: 'desc' },
|
|
||||||
});
|
|
||||||
const workbook = new ExcelJS.Workbook();
|
|
||||||
const worksheet = workbook.addWorksheet('教师列表');
|
|
||||||
worksheet.columns = [
|
|
||||||
{ header: 'ID', key: 'id', width: 8 },
|
|
||||||
{ header: '姓名', key: 'name', width: 15 },
|
|
||||||
{ header: '手机号', key: 'phone', width: 15 },
|
|
||||||
{ header: '邮箱', key: 'email', width: 25 },
|
|
||||||
{ header: '登录账号', key: 'loginAccount', width: 15 },
|
|
||||||
{ header: '负责班级', key: 'classes', width: 20 },
|
|
||||||
{ header: '授课次数', key: 'lessonCount', width: 10 },
|
|
||||||
{ header: '状态', key: 'status', width: 10 },
|
|
||||||
{ header: '创建时间', key: 'createdAt', width: 20 },
|
|
||||||
];
|
|
||||||
worksheet.getRow(1).font = { bold: true };
|
|
||||||
worksheet.getRow(1).fill = {
|
|
||||||
type: 'pattern',
|
|
||||||
pattern: 'solid',
|
|
||||||
fgColor: { argb: 'FFE0E0E0' },
|
|
||||||
};
|
|
||||||
teachers.forEach((teacher) => {
|
|
||||||
worksheet.addRow({
|
|
||||||
id: teacher.id,
|
|
||||||
name: teacher.name,
|
|
||||||
phone: teacher.phone,
|
|
||||||
email: teacher.email || '-',
|
|
||||||
loginAccount: teacher.loginAccount,
|
|
||||||
classes: teacher.classes.map((c) => c.name).join('、') || '-',
|
|
||||||
lessonCount: teacher.lessonCount,
|
|
||||||
status: teacher.status === 'ACTIVE' ? '正常' : '停用',
|
|
||||||
createdAt: teacher.createdAt.toLocaleDateString('zh-CN'),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
const buffer = await workbook.xlsx.writeBuffer();
|
|
||||||
return Buffer.from(buffer);
|
|
||||||
}
|
|
||||||
async exportStudents(tenantId) {
|
|
||||||
const students = await this.prisma.student.findMany({
|
|
||||||
where: { tenantId },
|
|
||||||
include: {
|
|
||||||
class: {
|
|
||||||
select: { name: true },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
orderBy: [{ classId: 'asc' }, { createdAt: 'asc' }],
|
|
||||||
});
|
|
||||||
const workbook = new ExcelJS.Workbook();
|
|
||||||
const worksheet = workbook.addWorksheet('学生列表');
|
|
||||||
worksheet.columns = [
|
|
||||||
{ header: 'ID', key: 'id', width: 8 },
|
|
||||||
{ header: '姓名', key: 'name', width: 15 },
|
|
||||||
{ header: '性别', key: 'gender', width: 8 },
|
|
||||||
{ header: '班级', key: 'className', width: 15 },
|
|
||||||
{ header: '生日', key: 'birthDate', width: 15 },
|
|
||||||
{ header: '家长姓名', key: 'parentName', width: 15 },
|
|
||||||
{ header: '家长电话', key: 'parentPhone', width: 15 },
|
|
||||||
{ header: '阅读次数', key: 'readingCount', width: 10 },
|
|
||||||
{ header: '创建时间', key: 'createdAt', width: 20 },
|
|
||||||
];
|
|
||||||
worksheet.getRow(1).font = { bold: true };
|
|
||||||
worksheet.getRow(1).fill = {
|
|
||||||
type: 'pattern',
|
|
||||||
pattern: 'solid',
|
|
||||||
fgColor: { argb: 'FFE0E0E0' },
|
|
||||||
};
|
|
||||||
students.forEach((student) => {
|
|
||||||
worksheet.addRow({
|
|
||||||
id: student.id,
|
|
||||||
name: student.name,
|
|
||||||
gender: student.gender || '-',
|
|
||||||
className: student.class?.name || '-',
|
|
||||||
birthDate: student.birthDate
|
|
||||||
? new Date(student.birthDate).toLocaleDateString('zh-CN')
|
|
||||||
: '-',
|
|
||||||
parentName: student.parentName || '-',
|
|
||||||
parentPhone: student.parentPhone || '-',
|
|
||||||
readingCount: student.readingCount,
|
|
||||||
createdAt: student.createdAt.toLocaleDateString('zh-CN'),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
const buffer = await workbook.xlsx.writeBuffer();
|
|
||||||
return Buffer.from(buffer);
|
|
||||||
}
|
|
||||||
async exportLessons(tenantId) {
|
|
||||||
const lessons = await this.prisma.lesson.findMany({
|
|
||||||
where: { tenantId },
|
|
||||||
include: {
|
|
||||||
course: {
|
|
||||||
select: { name: true, pictureBookName: true },
|
|
||||||
},
|
|
||||||
class: {
|
|
||||||
select: { name: true },
|
|
||||||
},
|
|
||||||
teacher: {
|
|
||||||
select: { name: true },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
orderBy: { createdAt: 'desc' },
|
|
||||||
});
|
|
||||||
const workbook = new ExcelJS.Workbook();
|
|
||||||
const worksheet = workbook.addWorksheet('授课记录');
|
|
||||||
worksheet.columns = [
|
|
||||||
{ header: 'ID', key: 'id', width: 8 },
|
|
||||||
{ header: '课程名称', key: 'courseName', width: 25 },
|
|
||||||
{ header: '绘本名称', key: 'pictureBookName', width: 20 },
|
|
||||||
{ header: '授课班级', key: 'className', width: 15 },
|
|
||||||
{ header: '授课教师', key: 'teacherName', width: 12 },
|
|
||||||
{ header: '计划时间', key: 'plannedDatetime', width: 18 },
|
|
||||||
{ header: '开始时间', key: 'startDatetime', width: 18 },
|
|
||||||
{ header: '结束时间', key: 'endDatetime', width: 18 },
|
|
||||||
{ header: '实际时长(分钟)', key: 'actualDuration', width: 12 },
|
|
||||||
{ header: '状态', key: 'status', width: 10 },
|
|
||||||
];
|
|
||||||
worksheet.getRow(1).font = { bold: true };
|
|
||||||
worksheet.getRow(1).fill = {
|
|
||||||
type: 'pattern',
|
|
||||||
pattern: 'solid',
|
|
||||||
fgColor: { argb: 'FFE0E0E0' },
|
|
||||||
};
|
|
||||||
const statusMap = {
|
|
||||||
PLANNED: '已计划',
|
|
||||||
IN_PROGRESS: '进行中',
|
|
||||||
COMPLETED: '已完成',
|
|
||||||
CANCELLED: '已取消',
|
|
||||||
};
|
|
||||||
lessons.forEach((lesson) => {
|
|
||||||
worksheet.addRow({
|
|
||||||
id: lesson.id,
|
|
||||||
courseName: lesson.course?.name || '-',
|
|
||||||
pictureBookName: lesson.course?.pictureBookName || '-',
|
|
||||||
className: lesson.class?.name || '-',
|
|
||||||
teacherName: lesson.teacher?.name || '-',
|
|
||||||
plannedDatetime: lesson.plannedDatetime
|
|
||||||
? new Date(lesson.plannedDatetime).toLocaleString('zh-CN')
|
|
||||||
: '-',
|
|
||||||
startDatetime: lesson.startDatetime
|
|
||||||
? new Date(lesson.startDatetime).toLocaleString('zh-CN')
|
|
||||||
: '-',
|
|
||||||
endDatetime: lesson.endDatetime
|
|
||||||
? new Date(lesson.endDatetime).toLocaleString('zh-CN')
|
|
||||||
: '-',
|
|
||||||
actualDuration: lesson.actualDuration || '-',
|
|
||||||
status: statusMap[lesson.status] || lesson.status,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
const buffer = await workbook.xlsx.writeBuffer();
|
|
||||||
return Buffer.from(buffer);
|
|
||||||
}
|
|
||||||
async exportGrowthRecords(tenantId, studentId) {
|
|
||||||
const where = { tenantId };
|
|
||||||
if (studentId) {
|
|
||||||
where.studentId = studentId;
|
|
||||||
}
|
|
||||||
const records = await this.prisma.growthRecord.findMany({
|
|
||||||
where,
|
|
||||||
include: {
|
|
||||||
student: {
|
|
||||||
select: { name: true },
|
|
||||||
},
|
|
||||||
class: {
|
|
||||||
select: { name: true },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
orderBy: { recordDate: 'desc' },
|
|
||||||
});
|
|
||||||
const workbook = new ExcelJS.Workbook();
|
|
||||||
const worksheet = workbook.addWorksheet('成长档案');
|
|
||||||
worksheet.columns = [
|
|
||||||
{ header: 'ID', key: 'id', width: 8 },
|
|
||||||
{ header: '学生姓名', key: 'studentName', width: 15 },
|
|
||||||
{ header: '班级', key: 'className', width: 15 },
|
|
||||||
{ header: '标题', key: 'title', width: 25 },
|
|
||||||
{ header: '内容', key: 'content', width: 50 },
|
|
||||||
{ header: '记录类型', key: 'recordType', width: 12 },
|
|
||||||
{ header: '记录日期', key: 'recordDate', width: 15 },
|
|
||||||
{ header: '创建时间', key: 'createdAt', width: 20 },
|
|
||||||
];
|
|
||||||
worksheet.getRow(1).font = { bold: true };
|
|
||||||
worksheet.getRow(1).fill = {
|
|
||||||
type: 'pattern',
|
|
||||||
pattern: 'solid',
|
|
||||||
fgColor: { argb: 'FFE0E0E0' },
|
|
||||||
};
|
|
||||||
records.forEach((record) => {
|
|
||||||
worksheet.addRow({
|
|
||||||
id: record.id,
|
|
||||||
studentName: record.student?.name || '-',
|
|
||||||
className: record.class?.name || '-',
|
|
||||||
title: record.title,
|
|
||||||
content: record.content || '-',
|
|
||||||
recordType: record.recordType,
|
|
||||||
recordDate: record.recordDate
|
|
||||||
? new Date(record.recordDate).toLocaleDateString('zh-CN')
|
|
||||||
: '-',
|
|
||||||
createdAt: record.createdAt.toLocaleDateString('zh-CN'),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
const buffer = await workbook.xlsx.writeBuffer();
|
|
||||||
return Buffer.from(buffer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.ExportService = ExportService;
|
|
||||||
exports.ExportService = ExportService = ExportService_1 = __decorate([
|
|
||||||
(0, common_1.Injectable)(),
|
|
||||||
__metadata("design:paramtypes", [prisma_service_1.PrismaService])
|
|
||||||
], ExportService);
|
|
||||||
//# sourceMappingURL=export.service.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
@ -1,23 +0,0 @@
|
|||||||
import { FileUploadService } from './file-upload.service';
|
|
||||||
export declare class FileUploadController {
|
|
||||||
private readonly fileUploadService;
|
|
||||||
private readonly logger;
|
|
||||||
constructor(fileUploadService: FileUploadService);
|
|
||||||
uploadFile(file: Express.Multer.File, body: {
|
|
||||||
type?: string;
|
|
||||||
courseId?: string;
|
|
||||||
}): Promise<{
|
|
||||||
success: boolean;
|
|
||||||
filePath: string;
|
|
||||||
fileName: string;
|
|
||||||
originalName: string;
|
|
||||||
fileSize: number;
|
|
||||||
mimeType: string;
|
|
||||||
}>;
|
|
||||||
deleteFile(body: {
|
|
||||||
filePath: string;
|
|
||||||
}): Promise<{
|
|
||||||
success: boolean;
|
|
||||||
message: string;
|
|
||||||
}>;
|
|
||||||
}
|
|
||||||
@ -1,89 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
||||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
||||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
||||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
||||||
};
|
|
||||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
||||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
||||||
};
|
|
||||||
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
||||||
return function (target, key) { decorator(target, key, paramIndex); }
|
|
||||||
};
|
|
||||||
var FileUploadController_1;
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.FileUploadController = void 0;
|
|
||||||
const common_1 = require("@nestjs/common");
|
|
||||||
const platform_express_1 = require("@nestjs/platform-express");
|
|
||||||
const multer_1 = require("multer");
|
|
||||||
const file_upload_service_1 = require("./file-upload.service");
|
|
||||||
let FileUploadController = FileUploadController_1 = class FileUploadController {
|
|
||||||
constructor(fileUploadService) {
|
|
||||||
this.fileUploadService = fileUploadService;
|
|
||||||
this.logger = new common_1.Logger(FileUploadController_1.name);
|
|
||||||
}
|
|
||||||
async uploadFile(file, body) {
|
|
||||||
this.logger.log(`Uploading file: ${file.originalname}, type: ${body.type || 'unknown'}`);
|
|
||||||
if (!file) {
|
|
||||||
throw new common_1.BadRequestException('没有上传文件');
|
|
||||||
}
|
|
||||||
const fileType = body.type || 'other';
|
|
||||||
const validationResult = this.fileUploadService.validateFile(file, fileType);
|
|
||||||
if (!validationResult.valid) {
|
|
||||||
throw new common_1.BadRequestException(validationResult.error);
|
|
||||||
}
|
|
||||||
const savedFile = await this.fileUploadService.saveFile(file, fileType, body.courseId);
|
|
||||||
this.logger.log(`File uploaded successfully: ${savedFile.filePath}`);
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
filePath: savedFile.filePath,
|
|
||||||
fileName: savedFile.fileName,
|
|
||||||
originalName: file.originalname,
|
|
||||||
fileSize: file.size,
|
|
||||||
mimeType: file.mimetype,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
async deleteFile(body) {
|
|
||||||
this.logger.log(`Deleting file: ${body.filePath}`);
|
|
||||||
if (!body.filePath) {
|
|
||||||
throw new common_1.BadRequestException('缺少文件路径');
|
|
||||||
}
|
|
||||||
const result = await this.fileUploadService.deleteFile(body.filePath);
|
|
||||||
if (!result.success) {
|
|
||||||
throw new common_1.BadRequestException(result.error);
|
|
||||||
}
|
|
||||||
this.logger.log(`File deleted successfully: ${body.filePath}`);
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
message: '文件删除成功',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.FileUploadController = FileUploadController;
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Post)('upload'),
|
|
||||||
(0, common_1.UseInterceptors)((0, platform_express_1.FileInterceptor)('file', {
|
|
||||||
storage: (0, multer_1.memoryStorage)(),
|
|
||||||
limits: {
|
|
||||||
fileSize: 300 * 1024 * 1024,
|
|
||||||
},
|
|
||||||
})),
|
|
||||||
__param(0, (0, common_1.UploadedFile)()),
|
|
||||||
__param(1, (0, common_1.Body)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [Object, Object]),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], FileUploadController.prototype, "uploadFile", null);
|
|
||||||
__decorate([
|
|
||||||
(0, common_1.Delete)('delete'),
|
|
||||||
__param(0, (0, common_1.Body)()),
|
|
||||||
__metadata("design:type", Function),
|
|
||||||
__metadata("design:paramtypes", [Object]),
|
|
||||||
__metadata("design:returntype", Promise)
|
|
||||||
], FileUploadController.prototype, "deleteFile", null);
|
|
||||||
exports.FileUploadController = FileUploadController = FileUploadController_1 = __decorate([
|
|
||||||
(0, common_1.Controller)('files'),
|
|
||||||
__metadata("design:paramtypes", [file_upload_service_1.FileUploadService])
|
|
||||||
], FileUploadController);
|
|
||||||
//# sourceMappingURL=file-upload.controller.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"file-upload.controller.js","sourceRoot":"","sources":["../../../../src/modules/file-upload/file-upload.controller.ts"],"names":[],"mappings":"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"}
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
export declare class FileUploadModule {
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user