доделал управление файлами

This commit is contained in:
Андрей Дувакин 2025-11-29 09:02:32 +05:00
parent eb498051a1
commit e90be8b54e
4 changed files with 58 additions and 9 deletions

View File

@ -78,7 +78,7 @@ async def update_lesson(
@lessons_router.delete( @lessons_router.delete(
'/{lesson_id}', '/{lesson_id}/',
response_model=Optional[LessonRead], response_model=Optional[LessonRead],
summary='Delete a lesson', summary='Delete a lesson',
description='Delete a lesson', description='Delete a lesson',
@ -89,8 +89,7 @@ async def delete_lesson(
current_user: User = Depends(require_teacher), current_user: User = Depends(require_teacher),
): ):
lessons_service = LessonsService(db) lessons_service = LessonsService(db)
await lessons_service.delete(lesson_id, current_user) return await lessons_service.delete(lesson_id, current_user)
return None
@lessons_router.get( @lessons_router.get(

View File

@ -1,12 +1,16 @@
import os
from fastapi import HTTPException, status from fastapi import HTTPException, status
from typing import List, Optional from typing import List, Optional
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from app.application.courses_repository import CoursesRepository from app.application.courses_repository import CoursesRepository
from app.application.lesson_files_repository import LessonFilesRepository
from app.application.lessons_repository import LessonsRepository from app.application.lessons_repository import LessonsRepository
from app.domain.entities.lessons import LessonCreate, LessonUpdate, LessonRead from app.domain.entities.lessons import LessonCreate, LessonUpdate, LessonRead
from app.domain.models import Lesson, User from app.domain.models import Lesson, User
from app.infrastructure.lesson_files_service import LessonFilesService
from app.settings import Settings from app.settings import Settings
@ -14,6 +18,7 @@ class LessonsService:
def __init__(self, db: AsyncSession): def __init__(self, db: AsyncSession):
self.lessons_repository = LessonsRepository(db) self.lessons_repository = LessonsRepository(db)
self.courses_repository = CoursesRepository(db) self.courses_repository = CoursesRepository(db)
self.lesson_files_repository = LessonFilesRepository(db)
self.settings = Settings() self.settings = Settings()
async def get_all_by_course(self, course_id: int) -> List[LessonRead]: async def get_all_by_course(self, course_id: int) -> List[LessonRead]:
@ -91,4 +96,19 @@ class LessonsService:
detail="Доступ запрещён" detail="Доступ запрещён"
) )
lesson_files = await self.lesson_files_repository.get_by_lesson_id(lesson_id)
for file in lesson_files:
lesson_file = await self.lesson_files_repository.get_by_id(file.id)
if lesson_file is None:
raise HTTPException(404, "Файл не найден")
if not os.path.exists(lesson_file.file_path):
raise HTTPException(404, "Файл не найден на диске")
if os.path.exists(lesson_file.file_path):
os.remove(lesson_file.file_path)
await self.lesson_files_repository.delete(lesson_file)
await self.lessons_repository.delete(lesson) await self.lessons_repository.delete(lesson)

View File

@ -46,6 +46,7 @@ const CourseDetailPage = () => {
handleCreateLesson, handleCreateLesson,
handleOpenLesson, handleOpenLesson,
handleEditLesson, handleEditLesson,
handleDeleteLesson,
} = useCourseDetailPage(courseId); } = useCourseDetailPage(courseId);
if (isLoading) { if (isLoading) {
@ -112,10 +113,10 @@ const CourseDetailPage = () => {
<Popconfirm <Popconfirm
title="Удалить лекцию?" title="Удалить лекцию?"
description="Это действие нельзя отменить" description="Это действие нельзя отменить"
// onConfirm={(e) => { onConfirm={(e) => {
// e?.stopPropagation(); e?.stopPropagation();
// handleDeleteLesson(lesson.id); handleDeleteLesson(lesson.id);
// }} }}
okText="Удалить" okText="Удалить"
cancelText="Отмена" cancelText="Отмена"
> >
@ -132,12 +133,17 @@ const CourseDetailPage = () => {
> >
<div style={{marginBottom: 16}}> <div style={{marginBottom: 16}}>
{lesson.description ? ( {lesson.description ? (
<Text type="secondary">{lesson.description}</Text> <Text type="secondary">
{lesson.description.slice(0, 100)}...
</Text>
) : ( ) : (
<Text type="secondary" italic>Описание отсутствует</Text> <Text type="secondary" italic>Описание отсутствует</Text>
)} )}
</div> </div>
<Text>
Лекционный материал
</Text>
<div style={{marginTop: 16, display: "flex", alignItems: "center", gap: 8}}> <div style={{marginTop: 16, display: "flex", alignItems: "center", gap: 8}}>
<Avatar size="small" style={{backgroundColor: "#1890ff"}}> <Avatar size="small" style={{backgroundColor: "#1890ff"}}>
{userData?.first_name?.[0] || "У"} {userData?.first_name?.[0] || "У"}

View File

@ -7,9 +7,10 @@ import {
setSelectedLessonToUpdate, setSelectedLessonToUpdate,
setSelectedLessonToView setSelectedLessonToView
} from "../../../Redux/Slices/lessonsSlice.js"; } from "../../../Redux/Slices/lessonsSlice.js";
import {useGetLessonsByCourseIdQuery} from "../../../Api/lessonsApi.js"; import {useDeleteLessonMutation, useGetLessonsByCourseIdQuery} from "../../../Api/lessonsApi.js";
import {ROLES} from "../../../Core/constants.js"; import {ROLES} from "../../../Core/constants.js";
import CONFIG from "../../../Core/сonfig.js"; import CONFIG from "../../../Core/сonfig.js";
import {notification} from "antd";
const useCourseDetailPage = (courseId) => { const useCourseDetailPage = (courseId) => {
@ -39,6 +40,28 @@ const useCourseDetailPage = (courseId) => {
pollingInterval: 10000, pollingInterval: 10000,
}); });
const [
deleteLesson,
] = useDeleteLessonMutation();
const handleDeleteLesson = async (lessonId) => {
try {
await deleteLesson(lessonId);
notification.success({
title: "Успешно",
description: "Лекция удалена",
placement: "topRight",
});
} catch (error) {
notification.error({
title: "Ошибка",
description: error?.data?.detail || "Произошла ошибка при удалении лекции",
placement: "topRight",
})
}
};
useEffect(() => { useEffect(() => {
window.document.title = `Система обучения lectio - Курс: ${courseData?.title}`; window.document.title = `Система обучения lectio - Курс: ${courseData?.title}`;
}, [courseData]); }, [courseData]);
@ -67,6 +90,7 @@ const useCourseDetailPage = (courseId) => {
handleCreateLesson, handleCreateLesson,
handleOpenLesson, handleOpenLesson,
handleEditLesson, handleEditLesson,
handleDeleteLesson,
} }
}; };