feat: Phase 1-3 全部完成 — 沙盒增强、学情分析、学习路径

This commit is contained in:
yuzhiran-dev
2026-05-18 09:48:51 +08:00
commit 11bb86854c
277 changed files with 37755 additions and 0 deletions
@@ -0,0 +1,56 @@
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import * as bcrypt from 'bcryptjs';
import { PrismaService } from '../../prisma/prisma.service';
@Injectable()
export class AdminService {
constructor(
private prisma: PrismaService,
private jwtService: JwtService,
) {}
async login(username: string, password: string) {
const admin = await this.prisma.adminUser.findUnique({ where: { username } });
if (!admin || admin.status !== 'ACTIVE') {
throw new UnauthorizedException('管理员账号不可用');
}
const isValid = await bcrypt.compare(password, admin.passwordHash);
if (!isValid) {
throw new UnauthorizedException('密码错误');
}
await this.prisma.adminUser.update({
where: { id: admin.id },
data: { lastLoginAt: new Date() },
});
const token = this.jwtService.sign(
{ sub: admin.id, type: 'admin' },
{ expiresIn: '8h' },
);
return { token, id: admin.id, username: admin.username, role: admin.role };
}
async getDashboard() {
const [userCount, courseCount, contentCount, promptCount, orderCount] = await Promise.all([
this.prisma.user.count({ where: { deletedAt: null } }),
this.prisma.course.count({ where: { deletedAt: null } }),
this.prisma.content.count({ where: { deletedAt: null, status: 'PUBLISHED' } }),
this.prisma.prompt.count({ where: { deletedAt: null, status: 'PUBLISHED' } }),
this.prisma.order.count(),
]);
return {
stats: { userCount, courseCount, contentCount, promptCount, orderCount },
};
}
async logAction(adminId: number, action: string, target?: string, detail?: string, ip?: string) {
return this.prisma.adminLog.create({
data: { adminId, action, target, detail, ip },
});
}
}