<?php
    namespace apppicontroller;
    
    use appmodelAuthor;
    use appmodelBook;
    use appmodelPhoto;
    use OvertruePinyinPinyin;
    use thinkController;
    use thinkacadeDb;
    use thinkRequest;
    use appmodelChapter;
    use appmodelTags;
    use thinkException;
    
    class Postbot
    {
        public function save(Request $request)
        {
            try {
                if (!$request->isPost()) {
                    throw new Exception('非法请求', 1);
                }
    
                $data = $request->param();
                $this->validateRequest($data);
    
                Db::startTrans();
                
                // 处理作者和书籍
                $author = $this->handleAuthor($data);
                $book = $this->handleBook($data, $author);
                
                // 处理章节
                $chapter = $this->handleChapter($data, $book);
                
                // 处理图片和标签
                $this->handlePhotos($chapter->id, $data['images']);
                $this->processTags($data['tags'], $book->id);
                
                Db::commit();
                
                return json(['code' => 0, 'message' => '发布成功']);
                
            } catch (Exception $e) {
                Db::rollback();
                $message = $e->getCode() === 0 ? '章节已存在' : $e->getMessage();
                return json(['code' => $e->getCode() ?: 1, 'message' => $message]);
            }
        }
    
        private function validateRequest($data)
        {
            if (!isset($data['api_key']) || $data['api_key'] != config('site.api_key')) {
                throw new Exception('Api密钥为空/密钥错误', 1);
            }
            
            $required = ['book_name', 'author', 'chapter_name', 'images'];
            foreach ($required as $field) {
                if (empty($data[$field])) {
                    throw new Exception("缺少必要参数: {$field}", 1);
                }
            }
        }
    
        private function handleAuthor($data)
        {
            $authorName = trim($data['author']);
            $author = Author::where('author_name', $authorName)
                ->lock(true)
                ->find();
    
            if (!$author) {
                $author = new Author();
                $author->username = 'author_'.gen_uid(8);
                $author->password = gen_uid(12);
                $author->email = 'author_'.gen_uid(6).'@auto.com';
                $author->status = 1;
                $author->author_name = $authorName;
                
                try {
                    $author->save();
                } catch (Exception $e) {
                    if ($this->isDuplicateEntry($e)) {
                        return Author::where('author_name', $authorName)
                            ->lock(true)
                            ->find();
                    }
                    throw $e;
                }
            }
            
            return $author;
        }
    
        private function handleBook($data, $author)
        {
            $bookName = trim($data['book_name']);
            $book = Book::where('book_name', $bookName)
                ->lock(true)
                ->find();
    
            if (!$book) {
                $book = new Book();
                $this->populateBookData($book, $data, $author);
                
                try {
                    $book->save();
                } catch (Exception $e) {
                    if ($this->isDuplicateEntry($e)) {
                        return Book::where('book_name', $bookName)
                            ->lock(true)
                            ->find();
                    }
                    throw $e;
                }
            }
            
            return $book;
        }
    
        private function populateBookData($book, $data, $author)
        {
            $pinyin = new Pinyin();
            $book->unique_id = $pinyin->abbr($data['book_name']).'_'.md5(microtime(true).mt_rand(1000,9999));
            $book->author_id = $author->id;
            $book->author_name = $author->author_name;
            $book->area_id = (int)($data['area_id'] ?? 6);
            $book->book_name = trim($data['book_name']);
            $book->nick_name = trim($data['nick_name'] ?? '');
            $book->tags = trim($data['tags']);
            $book->src_url = trim($data['src_url']);
            $book->end = (int)($data['end'] ?? 1);
            $book->start_pay = 9999;
            $book->money = 0;
            $book->cover_url = filter_var($data['cover_url'], FILTER_VALIDATE_URL);
            $book->banner_url = filter_var($data['banner_url'], FILTER_VALIDATE_URL);
            $book->summary = mb_substr(trim($data['summary']), 0, 500);
            $book->last_time = time();
        }
    
        private function handleChapter($data, $book)
        {
            // 使用行锁检查章节
            $chapter = Chapter::where([
                    'book_id' => $book->id,
                    'chapter_name' => trim($data['chapter_name'])
                ])
                ->lock(true)
                ->find();
    
            if ($chapter) {
                throw new Exception('章节已存在', 0);
            }
    
            $chapter = new Chapter();
            $chapter->book_id = $book->id;
            $chapter->chapter_name = trim($data['chapter_name']);
            $chapter->chapter_order = (int)($data['chapter_order'] ?? 1);
            $chapter->create_time = time();
            $chapter->update_time = time();
            $chapter->save();
    
            // 更新书籍最后章节(带行锁)
            $this->updateLastChapter($book, $chapter);
            
            return $chapter;
        }
    
        private function updateLastChapter($book, $chapter)
        {
            $freshBook = Book::where('id', $book->id)
                ->lock(true)
                ->find();
                
            $freshBook->last_time = time();
            $freshBook->last_chapter_id = $chapter->id;
            $freshBook->last_chapter = $chapter->chapter_name;
            $freshBook->save();
        }
    
        private function handlePhotos($chapterId, $images)
        {
            $images = array_filter(explode(',', $images));
            foreach ($images as $index => $url) {
                $photo = new Photo();
                $photo->chapter_id = $chapterId;
                $photo->pic_order = $index;
                $photo->img_url = filter_var(trim($url), FILTER_VALIDATE_URL);
                $photo->save();
            }
        }
    
        private function processTags($tags, $bookId)
        {
            $tags = array_unique(explode('|', trim($tags)));
            foreach ($tags as $tagName) {
                if (!empty($tagName)) {
                    $this->saveTag($tagName);
                }
            }
        }
    
        private function saveTag($tagName)
        {
            // 修正后的标签处理方法
            $tag = Tags::where('tag_name', trim($tagName))->find();
            if (!$tag) {
                $tag = new Tags();
                $tag->tag_name = trim($tagName);
                $tag->cover_url = config('app.default_tag_cover');
                $tag->create_time = time();
                $tag->update_time = time();
                $tag->save();
            }
        }
    
        private function isDuplicateEntry(Exception $e)
        {
            return strpos($e->getMessage(), 'Duplicate entry') !== false;
        }
    }
    1、测试重复章节提交应返回:
    {"code":0,"message":"章节已存在"}
    2、新章节提交应返回:
    {"code":0,"message":"发布成功"}
    3、参数缺失时应返回:
    {"code":1,"message":"缺少必要参数: xxx"}
返回顶部