fly před 4 roky
rodič
revize
49f82cd332

+ 1 - 1
composer.json

@@ -12,7 +12,7 @@
     "require": {},
     "autoload": {
         "psr-4": {
-            "Channel\\Common\\": "src"
+            "General\\": "src"
         }
     },
     "minimum-stability": "dev"

+ 23 - 0
src/Controllers/Book/BookController.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace General\Controllers\Book;
+
+use General\Controllers\Book\Transformers\BookTransformer;
+use General\Requests\Book\OnShelfBookRequest;
+use General\Services\Book\BookService;
+
+class BookController extends BaseController
+{
+    protected $service;
+    public function __construct()
+    {
+        $this->service = new BookService;
+    }
+
+    public function getOnShelfBooks(OnShelfBookRequest $request)
+    {
+
+        $res = $this->service->getBooks($request->all());
+        return response()->pagination(new BookTransformer, $res);
+    }
+}

+ 93 - 0
src/Controllers/Book/Transformers/BookTransformer.php

@@ -0,0 +1,93 @@
+<?php
+
+/**
+ * Created by PhpStorm.
+ * Date: 2017/3/31
+ * Time: 14:02
+ */
+
+namespace General\Controllers\Book\Transformers;
+
+use General\Models\Book\BookConfig;
+use General\Models\Book\BookSplitOperateRecord;
+use General\Models\Book\BookTags;
+
+class BookTransformer
+{
+    public function transform($item)
+    {
+
+        return [
+            'book_id' => $item->bid,
+            'book_name' => $item->book_name,
+            'old_name' => $item->book ? $item->book->name : '',
+            'book_summary' => $item->book ? $item->book->intro : '',
+            'book_author' => $item->book ? $item->book->author : '',
+            'cover_url' => $item->book ? $item->book->cover : '',
+            'book_word_count' => $item->book ? $item->book->size : 0,
+            'book_chapter_total' => $item->book ? $item->book->chapter_count : 0,
+            'book_category_id' => $item->book ? $item->book->category_id : 0,
+            'book_end_status' => $item->book ? $item->book->status : 0,
+            'book_category' => $item->book && $item->book->category ? $item->book->category->category_name : '',
+            'sex_preference' => $item->book && $item->book->category ? $item->book->category->channel_name : '',
+            'category_array' => $item->book && $item->book->category ? [$item->book->category->pid, $item->book->category_id] : [],
+            'book_published_time' => (string)$item->updated_at,
+            'copyright' => (string)$item->copyright,
+            'charge_type' => (string)$item->charge_type,
+            'force_subscribe_chapter_id' => $item->force_subscribe_chapter_seq,
+            'update_time' => $item->updated_at,
+            'product_id' => $item->product_id,
+            'is_on_shelf' => $item->is_on_shelf,
+            'book_price' => (float) $item->price,
+            'keyword' => $item->keyword,
+            'roles' => (string)$item->roles,
+            'recommend_index' => $item->recommend_index,
+            'is_show_index_content' => $item->is_show_index_content,
+            'click_count' => $item->click_count,
+            'last_cid' => $item->last_cid,
+            'last_chapter' => $item->last_chapter,
+            'first_cid' => $item->first_cid,
+            'copyright_limit_data' => (string)$item->copyright_limit_data,
+            'promotion_domain' => $item->promotion_domain,
+            'calculate_price_type' => $item->calculate_price_type,
+            'is_high_quality' => $item->is_high_quality,
+            'is_promotion' => $item->is_current_week_promotion,
+            'recommend_text' => $item->recommend_text,
+            'book_special_channels' => $this->getSpecialChannels($item),
+            'tags' => $this->getBookTags($item->bid),
+            'copyright_tag' => isset($item->copyright_tag) ? $item->copyright_tag : '',
+            'book_roles' => $this->getBookRoles($item),
+            'unit_price' => $this->getPrice($item),
+            'shelf_time' => $item->shelf_time,
+            'is_split' => $this->isSplit($item),
+        ];
+    }
+
+    protected function getBookRoles(BookConfig $item)
+    {
+        return $item->book_roles ? json_decode(json_encode($item->book_roles), true) : [];
+    }
+
+    protected function getSpecialChannels(BookConfig $item)
+    {
+        return $item->special_channels ? $item->special_channels->pluck('chanel_user_id')->all() : [];
+    }
+
+    protected function isSplit(int $bid)
+    {
+        return BookSplitOperateRecord::where('bid', $bid)->exists();
+    }
+
+    protected  function getBookTags(int $bid)
+    {
+        return BookTags::where([['bid', '=', $bid], ['status', '=', 1]])->get();
+    }
+
+    protected function getPrice(BookConfig $item)
+    {
+        return $item->calculate_price_type == 'const' ?
+            $item->unit_price : ($item->unit_price * 100 > 0 ?
+                number_format($item->unit_price * 100, 1) :
+                number_format(env('DEFAULT_CHAPTER_PRICE', 0.015) * 100, 1));
+    }
+}

+ 32 - 0
src/Models/Book/Book.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace General\Models\Book;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Book extends Model
+{
+    protected  $table = 'books';
+    protected  $fillable = [
+        'ly_bid',
+        'name',
+        'author',
+        'intro',
+        'cover',
+        'category_name',
+        'keyword',
+        'category_id',
+        'status',
+        'chapter_count',
+        'first_cid',
+        'last_cid',
+        'size',
+        'last_chapter',
+        'sequence'
+    ];
+
+    protected function category()
+    {
+        return $this->hasOne(BookCategory::class, 'id', 'category_id');
+    }
+}

+ 16 - 0
src/Models/Book/BookCategory.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace General\Models\Book;
+
+use Illuminate\Database\Eloquent\Model;
+
+class BookCategory extends Model
+{
+    protected $table = 'book_categories';
+    protected $fillable = [
+        'id',
+        'category_name',
+        'pid',
+        'channel_name'
+    ];
+}

+ 57 - 0
src/Models/Book/BookConfig.php

@@ -0,0 +1,57 @@
+<?php
+
+namespace General\Models\Book;
+
+use Illuminate\Database\Eloquent\Model;
+
+class BookConfig extends Model
+{
+    protected $table = 'book_configs';
+    protected $fillable = [
+        'bid',
+        'force_subscribe_chapter_seq',
+        'price',
+        'cover',
+        'book_name',
+        'copyright',
+        'charge_type',
+        'hot',
+        'is_on_shelf',
+        'source_domain',
+        'recommend_index',
+        'roles',
+        'test_status',
+        'plan_push_user_num',
+        'test_update_time',
+        'test_weight',
+        'unit_price',
+        'is_show_index_content',
+        'click_count',
+        'promotion_domain',
+        'copyright_limit_data',
+        'recommend_cid',
+        'is_high_quality',
+        'vip_seq',
+        'editor_recommend',
+        'is_current_week_promotion',
+        'recommend_info_stream_cid',
+        'calculate_price_type',
+        'shelf_time',
+        'cooperation_type'
+    ];
+
+    protected function book()
+    {
+        return $this->hasOne(Book::class, 'id', 'bid');
+    }
+
+    protected function special_channels()
+    {
+        return $this->hasMany(BookSpecialChannel::class, 'bid', 'bid');
+    }
+
+    protected function book_roles()
+    {
+        return $this->hasMany(BookRoles::class, 'bid', 'bid');
+    }
+}

+ 14 - 0
src/Models/Book/BookRoles.php

@@ -0,0 +1,14 @@
+<?php
+
+namespace General\Models\Book;
+
+use Illuminate\Database\Eloquent\Model;
+
+class BookRoles extends Model
+{
+    protected $table = 'book_roles';
+    protected $fillable = [
+        'bid',
+        'role'
+    ];
+}

+ 17 - 0
src/Models/Book/BookSpecialChannel.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace General\Models\Book;
+
+use Illuminate\Database\Eloquent\Model;
+
+class BookSpecialChannel extends Model
+{
+    protected $table = 'channel_special_books';
+    protected $fillable = [
+        'id',
+        'bid',
+        'channel_user_id',
+        'created_at',
+        'updated_at'
+    ];
+}

+ 17 - 0
src/Models/Book/BookSplitOperateRecord.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace General\Models\Book;
+
+use Illuminate\Database\Eloquent\Model;
+
+class BookSplitOperateRecord extends Model
+{
+    protected $table = 'book_split_operate_record';
+    protected $fillable = [
+        'bid',
+        'size',
+        'operator',
+        'is_process',
+        'config',
+    ];
+}

+ 17 - 0
src/Models/Book/BookTags.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace General\Models\Book;
+
+use Illuminate\Database\Eloquent\Model;
+
+class BookTags extends Model
+{
+    protected $table = 'book_tags';
+    protected $fillable = [
+        'id',
+        'bid',
+        'tags',
+        'tags_id',
+        'status'
+    ];
+}

+ 25 - 0
src/Requests/Book/OnShelfBookRequest.php

@@ -0,0 +1,25 @@
+<?php
+
+namespace General\Requests\Book;
+
+use General\Requests\Request;
+use Illuminate\Validation\Rule;
+
+class OnShelfBookRequest extends Request
+{
+    public function rules()
+    {
+        return [
+            'weekly_promotion' => ['integer', Rule::in([0, 1])],
+            'type' => ['integer', Rule::in([1, 2])],
+            'charge_type' => ['string', Rule::in(['CHAPTER', 'Book'])],
+            'is_high_quality' => ['integer', Rule::in([0, 1])],
+            'category_id' => 'integer',
+            'bid' => 'integer',
+            'author' => 'string',
+            'key' => 'string',
+            'roles' => 'string',
+            'firstChapterContent' => 'string',
+        ];
+    }
+}

+ 86 - 0
src/Requests/Request.php

@@ -0,0 +1,86 @@
+<?php
+
+namespace General\Requests;
+
+use Illuminate\Contracts\Validation\Validator;
+use Illuminate\Foundation\Http\FormRequest;
+use Illuminate\Http\Exceptions\HttpResponseException;
+
+abstract class Request extends FormRequest
+{
+    public function authorize()
+    {
+        return true;
+    }
+
+    public function failedValidation(Validator $validator)
+    {
+        throw (new HttpResponseException(response()->json([
+            'code' => -1,
+            'msg' => $validator->errors()->first(),
+            'data' => $validator->errors()->first(),
+        ], 200)));
+    }
+
+    public function messages()
+    {
+        return [
+            'required' => '缺少参数:attribute',
+            'integer' => ':attribute 必须是整数类型',
+            'date' => ':attribute 必须是日期格式',
+            'accepted' => 'The :attribute must be accepted.',
+            'active_url' => ':attribute 是个无效链接.',
+            'after' => 'The :attribute must be a date after :date.',
+            'after_or_equal' => 'The :attribute must be a date after or equal to :date.',
+            'alpha' => 'The :attribute may only contain letters.',
+            'alpha_dash' => 'The :attribute may only contain letters, numbers, dashes and underscores.',
+            'alpha_num' => 'The :attribute may only contain letters and numbers.',
+            'array' => 'The :attribute must be an array.',
+            'before' => 'The :attribute must be a date before :date.',
+            'before_or_equal' => 'The :attribute must be a date before or equal to :date.',
+            'between' => 'The :attribute 必须处于 :min 和 :max 之间',
+            'boolean' => 'The :attribute field must be true or false.',
+            'confirmed' => 'The :attribute confirmation does not match.',
+            'date_equals' => 'The :attribute must be a date equal to :date.',
+            'date_format' => 'The :attribute does not match the format :format.',
+            'different' => 'The :attribute and :other must be different.',
+            'digits' => 'The :attribute must be :digits digits.',
+            'digits_between' => 'The :attribute must be between :min and :max digits.',
+            'dimensions' => 'The :attribute has invalid image dimensions.',
+            'distinct' => 'The :attribute field has a duplicate value.',
+            'email' => 'The :attribute must be a valid email address.',
+            'ends_with' => 'The :attribute must end with one of the following: :values',
+            'exists' => ':attribute 不存在.',
+            'file' => 'The :attribute must be a file.',
+            'filled' => 'The :attribute field must have a value.',
+            'image' => 'The :attribute 必须是一张图片.',
+            'in' => '选项 :attribute 不在给定范围中.',
+            'in_array' => 'The :attribute field does not exist in :other.',
+            'ip' => 'The :attribute must be a valid IP address.',
+            'ipv4' => 'The :attribute must be a valid IPv4 address.',
+            'ipv6' => 'The :attribute must be a valid IPv6 address.',
+            'json' => 'The :attribute must be a valid JSON string.',
+            'mimes' => 'The :attribute must be a file of type: :values.',
+            'mimetypes' => 'The :attribute must be a file of type: :values.',
+            'not_in' => 'The selected :attribute is invalid.',
+            'not_regex' => 'The :attribute format is invalid.',
+            'numeric' => 'The :attribute must be a number.',
+            'present' => 'The :attribute field must be present.',
+            'regex' => 'The :attribute format is invalid.',
+            'required_if' => 'The :attribute field is required when :other is :value.',
+            'required_unless' => 'The :attribute field is required unless :other is in :values.',
+            'required_with' => 'The :attribute field is required when :values is present.',
+            'required_with_all' => 'The :attribute field is required when :values are present.',
+            'required_without' => 'The :attribute field is required when :values is not present.',
+            'required_without_all' => 'The :attribute field is required when none of :values are present.',
+            'same' => 'The :attribute and :other must match.',
+            'starts_with' => 'The :attribute must start with one of the following: :values',
+            'string' => 'The :attribute must be a string.',
+            'timezone' => 'The :attribute must be a valid zone.',
+            'unique' => 'The :attribute has already been taken.',
+            'uploaded' => 'The :attribute failed to upload.',
+            'url' => 'The :attribute format is invalid.',
+            'uuid' => 'The :attribute must be a valid UUID.',
+        ];
+    }
+}

+ 97 - 0
src/Services/Book/BookService.php

@@ -0,0 +1,97 @@
+<?php
+
+namespace General\Services\Book;
+
+use General\Models\Book\BookCategory;
+use General\Models\Book\BookConfig;
+use Illuminate\Database\Query\Builder;
+use Illuminate\Support\Facades\DB;
+
+class BookService
+{
+    private function slowQueryParams(Builder $sql, array $params)
+    {
+        if (isset($params['roles']) && $params['roles']) {
+            $sql->whereExists(function (Builder $query) use ($params) {
+                $query->select(DB::raw(1))
+                    ->from('book_roles')
+                    ->whereColumn('book_configs.bid', 'book_roles.bid')
+                    ->where('role', $params['role']);
+            });
+        }
+        if (isset($params['category_id']) && $params['category_id']) {
+            if ($params['category_id'] > 2) {
+                $category_ids = [$params['category_id']];
+            } else {
+                if ($params['category_id'] == 1) {
+                    $channel_name = '男频';
+                } else if ($params['category_id'] == 2) {
+                    $channel_name = '女频';
+                }
+                $category_ids = BookCategory::where('channel_name', $channel_name)->pluck('id')->all();
+            }
+            $sql->whereExists(function (Builder $query) use ($category_ids) {
+                $query->select(DB::raw(1))
+                    ->from('books')
+                    ->whereColumn('book_configs.bid', 'books.id')
+                    ->whereIn('books.category_id', $category_ids);
+            });
+        }
+        if (isset($params['author']) && $params['author']) {
+            $sql->whereExists(function (Builder $query) use ($params) {
+                $query->select(DB::raw(1))
+                    ->from('books')
+                    ->whereColumn('book_configs.bid', 'books.id')
+                    ->where('books.author', 'like', "%{$params['author']}%");
+            });
+        }
+        if (isset($params['firstChapterContent']) && $params['firstChapterContent']) {
+            $sql->whereExists(function (Builder $query) use ($params) {
+                $query->select(DB::raw(1))
+                    ->from('chapters')
+                    ->whereColumn('book_configs.bid', 'chapters.bid')
+                    ->where('chapters.sequence', 1)
+                    ->where('chapters.content', 'like', '%' . $params['firstChapterContent'] . '%');
+            });
+        }
+    }
+    /**
+     * 根据条件获取图书
+     * @param array $where
+     * @param array $order
+     * @param int $page_size
+     * @return mixed
+     */
+    public function getBooks(array $params, bool $is_page = true)
+    {
+        if (isset($params['type']) && $params['type']) {
+            $sql = BookConfig::where('is_on_shelf', $params['type']);
+            if ($params['type'] == 1) {
+                $sql->orderBy('id', 'desc');
+            }
+        } else {
+            $sql = BookConfig::whereIn('is_on_shelf', [1, 2]);
+        }
+        if (isset($params['bid']) && $params['bid']) {
+            $sql->where('bid', $params['bid']);
+        }
+        if (isset($params['charge_type']) && $params['charge_type']) {
+            $sql->where('charge_type', $params['charge_type']);
+        }
+        if (isset($params['key']) && $params['key']) {
+            $sql->where('book_name', 'like', "%{$params['key']}%");
+        }
+        if (isset($params['is_high_quality']) && $params['is_high_quality']) {
+            $sql->where('is_high_quality', $params['is_high_quality']);
+        }
+        if (isset($params['weekly_promotion']) && $params['weekly_promotion']) {
+            $sql->where('is_current_week_promotion', $params['weekly_promotion']);
+        }
+        $this->slowQueryParams($sql, $params);
+        if ($is_page) {
+            return $sql->paginate();
+        } else {
+            return $sql->get();
+        }
+    }
+}