|
@@ -1,26 +1,152 @@
|
|
-import { Injectable } from '@nestjs/common';
|
|
|
|
|
|
+import { Injectable, NotFoundException } from '@nestjs/common';
|
|
|
|
+import { InjectRepository } from '@nestjs/typeorm';
|
|
|
|
+import { Repository } from 'typeorm';
|
|
import { CreateChapterDto } from './dto/create-chapter.dto';
|
|
import { CreateChapterDto } from './dto/create-chapter.dto';
|
|
import { UpdateChapterDto } from './dto/update-chapter.dto';
|
|
import { UpdateChapterDto } from './dto/update-chapter.dto';
|
|
|
|
+import { Chapter, ChapterStatus } from './entities/chapter.entity';
|
|
|
|
+import { Book } from '../book/entities/book.entity';
|
|
|
|
|
|
@Injectable()
|
|
@Injectable()
|
|
export class ChapterService {
|
|
export class ChapterService {
|
|
- create(createChapterDto: CreateChapterDto) {
|
|
|
|
- return 'This action adds a new chapter';
|
|
|
|
|
|
+ constructor(
|
|
|
|
+ @InjectRepository(Chapter)
|
|
|
|
+ private chapterRepository: Repository<Chapter>,
|
|
|
|
+ @InjectRepository(Book)
|
|
|
|
+ private bookRepository: Repository<Book>,
|
|
|
|
+ ) {}
|
|
|
|
+
|
|
|
|
+ private generateChapterId(bookId: number): string {
|
|
|
|
+ const now = new Date();
|
|
|
|
+ const timestamp = now.getFullYear().toString() +
|
|
|
|
+ (now.getMonth() + 1).toString().padStart(2, '0') +
|
|
|
|
+ now.getDate().toString().padStart(2, '0') +
|
|
|
|
+ now.getHours().toString().padStart(2, '0') +
|
|
|
|
+ now.getMinutes().toString().padStart(2, '0') +
|
|
|
|
+ now.getSeconds().toString().padStart(2, '0');
|
|
|
|
+
|
|
|
|
+ // 生成6位随机字符串
|
|
|
|
+ const randomStr = Math.random().toString(36).substring(2, 8);
|
|
|
|
+
|
|
|
|
+ return `book_${bookId}_${timestamp}_${randomStr}`;
|
|
}
|
|
}
|
|
|
|
|
|
- findAll() {
|
|
|
|
- return `This action returns all chapter`;
|
|
|
|
|
|
+ async create(createChapterDto: CreateChapterDto) {
|
|
|
|
+ // 验证书籍是否存在
|
|
|
|
+ const book = await this.bookRepository.findOne({
|
|
|
|
+ where: { id: createChapterDto.bookId },
|
|
|
|
+ });
|
|
|
|
+ if (!book) {
|
|
|
|
+ throw new NotFoundException(`ID为${createChapterDto.bookId}的书籍不存在`);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const chapter = this.chapterRepository.create(createChapterDto);
|
|
|
|
+
|
|
|
|
+ // 自动生成 chapterId(如果未提供)
|
|
|
|
+ if (!chapter.chapterId) {
|
|
|
|
+ chapter.chapterId = this.generateChapterId(createChapterDto.bookId);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 转换日期字符串为 Date 对象
|
|
|
|
+ if (createChapterDto.createdAt) {
|
|
|
|
+ chapter.createdAt = new Date(createChapterDto.createdAt);
|
|
|
|
+ }
|
|
|
|
+ if (createChapterDto.updatedAt) {
|
|
|
|
+ chapter.updatedAt = new Date(createChapterDto.updatedAt);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 设置默认值
|
|
|
|
+ if (!chapter.status) {
|
|
|
|
+ chapter.status = ChapterStatus.DRAFT;
|
|
|
|
+ }
|
|
|
|
+ if (chapter.isVisible === undefined) {
|
|
|
|
+ chapter.isVisible = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return this.chapterRepository.save(chapter);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ async findAll() {
|
|
|
|
+ return this.chapterRepository.find({
|
|
|
|
+ relations: ['book', 'parent', 'children'],
|
|
|
|
+ order: { sort: 'ASC' },
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ async findOne(id: number) {
|
|
|
|
+ const chapter = await this.chapterRepository.findOne({
|
|
|
|
+ where: { id },
|
|
|
|
+ relations: ['book', 'parent', 'children'],
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ if (!chapter) {
|
|
|
|
+ throw new NotFoundException(`ID为${id}的章节不存在`);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return chapter;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ async findByChapterId(chapterId: string) {
|
|
|
|
+ const chapter = await this.chapterRepository.findOne({
|
|
|
|
+ where: { chapterId },
|
|
|
|
+ relations: ['book', 'parent', 'children'],
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ if (!chapter) {
|
|
|
|
+ throw new NotFoundException(`章节ID为${chapterId}的章节不存在`);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return chapter;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ async findByBook(bookId: number) {
|
|
|
|
+ return this.chapterRepository.find({
|
|
|
|
+ where: { bookId },
|
|
|
|
+ relations: ['parent', 'children'],
|
|
|
|
+ order: { sort: 'ASC' },
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ async findByParent(parentId: number) {
|
|
|
|
+ return this.chapterRepository.find({
|
|
|
|
+ where: { parentId },
|
|
|
|
+ relations: ['book', 'children'],
|
|
|
|
+ order: { sort: 'ASC' },
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ async update(id: number, updateChapterDto: UpdateChapterDto) {
|
|
|
|
+ const chapter = await this.findOne(id);
|
|
|
|
+
|
|
|
|
+ // 更新基本字段
|
|
|
|
+ Object.assign(chapter, updateChapterDto);
|
|
|
|
+
|
|
|
|
+ // 转换日期字符串为 Date 对象
|
|
|
|
+ if (updateChapterDto.createdAt) {
|
|
|
|
+ chapter.createdAt = new Date(updateChapterDto.createdAt);
|
|
|
|
+ }
|
|
|
|
+ if (updateChapterDto.updatedAt) {
|
|
|
|
+ chapter.updatedAt = new Date(updateChapterDto.updatedAt);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return this.chapterRepository.save(chapter);
|
|
}
|
|
}
|
|
|
|
|
|
- findOne(id: number) {
|
|
|
|
- return `This action returns a #${id} chapter`;
|
|
|
|
|
|
+ async remove(id: number) {
|
|
|
|
+ const chapter = await this.findOne(id);
|
|
|
|
+ return this.chapterRepository.remove(chapter);
|
|
}
|
|
}
|
|
|
|
|
|
- update(id: number, updateChapterDto: UpdateChapterDto) {
|
|
|
|
- return `This action updates a #${id} chapter`;
|
|
|
|
|
|
+ async updateSort(id: number, newSort: number) {
|
|
|
|
+ const chapter = await this.findOne(id);
|
|
|
|
+ chapter.sort = newSort;
|
|
|
|
+ chapter.updatedAt = new Date();
|
|
|
|
+ return this.chapterRepository.save(chapter);
|
|
}
|
|
}
|
|
|
|
|
|
- remove(id: number) {
|
|
|
|
- return `This action removes a #${id} chapter`;
|
|
|
|
|
|
+ async updateStatus(id: number, status: ChapterStatus) {
|
|
|
|
+ const chapter = await this.findOne(id);
|
|
|
|
+ chapter.status = status;
|
|
|
|
+ chapter.updatedAt = new Date();
|
|
|
|
+ return this.chapterRepository.save(chapter);
|
|
}
|
|
}
|
|
}
|
|
}
|