| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123 | <?phpnamespace App\Modules\Book\Models;use App\Modules\Book\Services\BookRoleService;use App\Modules\Book\Services\BookTagsService;use App\Modules\User\Services\ReadRecordService;use App\Modules\Book\Services\BookConfigService;use App\Modules\Channel\Services\ChannelService;use App\Modules\OfficialAccount\Services\ForceSubscribeService;use DB;use Hashids;use Illuminate\Database\Eloquent\Model;use App\Modules\User\Models\User;use Log;use Redis;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',        'is_show_index_content', 'click_count', 'promotion_domain', 'copyright_limit_data', 'recommend_cid', 'is_high_quality', 'vip_seq','editor_recommend','is_current_week_promotion'];    /*    public static function getBooks($where, $order, $page_size = 15, $category = [], $key = null)    {        $res = self::join('books', 'book_configs.bid', '=', 'books.id')            ->join('book_categories', 'books.category_id', 'book_categories.id')            ->select('book_configs.bid', 'book_configs.force_subscribe_chapter_seq', 'book_configs.price',                'book_configs.cover', 'book_configs.book_name', 'book_configs.copyright', 'book_configs.charge_type', 'book_configs.is_on_shelf',                'books.author', 'books.intro', 'books.category_name', 'books.category_id', 'status', 'chapter_count', 'book_configs.click_count',                'first_cid', 'last_cid', 'size', 'last_chapter', 'books.keyword', 'book_configs.recommend_index', 'book_configs.is_show_index_content', 'book_configs.product_id'                , 'book_categories.channel_name', 'books.last_cid', 'books.last_chapter'            )            ->where($where)            ->orderBy($order[0], $order[1]);        if ($category) {            $res = $res->whereIn('books.category_id', $category);        }        if ($key) {            $res = $res->orwhere('book_configs.name', 'like', $key['name'])->orwhere('books.author', 'like', $key['author']);        }        return $res->paginate($page_size);    }    */    /**     * 根据条件获取图书     * @param array $where     * @param array $order     * @param int $page_size     * @return mixed     */    public static function getBooks(array $where = [], array $order = [], $page_size = 15)    {        if (!$order) {            $order = ['recommend_index', 'desc'];        }        $res = self::join('books', 'book_configs.bid', '=', 'books.id')            ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')            ->select('book_configs.bid', 'book_configs.roles', 'book_configs.force_subscribe_chapter_seq', 'book_configs.cp_source', 'book_configs.vip_seq', 'book_configs.price', 'book_configs.cover', 'book_configs.book_name',                'book_configs.copyright', 'book_configs.charge_type', 'book_configs.is_on_shelf', 'books.author', 'books.intro', 'book_categories.category_name',                'category_id', 'status', 'chapter_count', 'book_configs.click_count', 'first_cid', 'last_cid', 'books.size', 'last_chapter', 'books.keyword',                'book_configs.recommend_index', 'book_configs.is_show_index_content', 'book_configs.product_id', 'book_categories.channel_name',                'books.last_cid', 'books.last_chapter', 'book_configs.product_id', 'book_configs.copyright_limit_data', 'books.updated_at as last_update_time',                'book_configs.promotion_domain', 'books.name as old_name', 'book_configs.recommend_cid', 'book_configs.is_high_quality','is_current_week_promotion'            );        if ($where) {            foreach ($where as $key => $v) {                //关键词查询                if ($key == 'key' && $v) {                    //$res = $res->where('book_configs.book_name', 'like', '%' . $v . '%');                    $res = $res->where(function ($query) use ($v) {                        $query->where('book_configs.book_name', 'like', '%' . $v . '%');                            if(mb_strlen($v)<=5) {                                $roles_bids = BookRoleService::getBidsByRole($v);                                if(count($roles_bids)>0) {                                    $query->orWhereIn('book_configs.bid',$roles_bids);                                }                            }                    });                    //->orWhere('books.intro', 'like', '%' . $v . '%')                    //->orWhere('books.category_name', 'like', '%' . $v . '%')->orWhere('books.author', 'like', '%' . $v . '%')                    //->orWhere('books.keyword', 'like', '%' . $v . '%');                }                //分类id查询                if ($key == 'category_id' && $v) {                    $res = $res->where('books.category_id', '=', $v);                }                //上架查询                if ($key == 'is_on_shelf' && $v != '') {                    if (is_array($v)) {                        $res = $res->whereIn('is_on_shelf', $v);                    } else {                        $res = $res->where('is_on_shelf', '=', $v);                    }                }                //频道查询                if ($key == 'channel_name' && $v) {                    $res = $res->where('book_categories.channel_name', '=', $v);                }                if ($key == 'status') {                    $res = $res->where('books.status', '=', $v);                }                if ($key == 'author') {                    $res = $res->where('books.author', 'like', '%' . $v . '%');                }                if ($key == 'roles') {                    $res = $res->where('book_configs.roles', 'like', '%' . $v . '%');                }                //旧书名查询                if ($key == 'old_name') {                    $res = $res->where('books.name', 'like', '%' . $v . '%');                }                //版权日期查询                if ($key == 'copy_right_date') {                    if (is_array($v)) {                        $res = $res->whereBetween('book_configs.copyright_limit_data', $v);                    } else {                        $res = $res->where('book_configs.copyright_limit_data', '<=', $v);                    }                }                if ($key == 'domain') {                    $res = $res->where('book_configs.promotion_domain', 'like', '%' . $v . '%');                }                if ($key == 'bid') {                    $res = $res->where('book_configs.bid', '=', $v);                }                if ($key == 'is_high_quality') {                    $res = $res->where('book_configs.is_high_quality', '=', $v);                }                if ($key == 'charge_type') {                    $res = $res->where('book_configs.charge_type', '=', $v);                }                if ($key == 'firstChapterContent') {                    $res = $res->join('chapters', function ($query) use ($v) {                        $query->on('book_configs.bid', '=', 'chapters.bid')                            ->where('chapters.sequence', 1);                    })->where('chapters.content', 'like', '%' . $v . '%');                }                if ($key == 'tags') {                    $tags_filter = BookTagsService::getSearchBooks($v);                    $res->whereIn('book_configs.bid', $tags_filter);                }                if ($key == 'is_current_week_promotion') {                    $res->where('book_configs.is_current_week_promotion', $v);                }            }        }        //$res->orderBy('book_configs.updated_at','desc');        return $res->orderBy($order[0], $order[1])->orderBy('book_configs.updated_at', 'desc')->paginate($page_size);    }    /**     * 根据条件获取图书     * @param array $where     * @param array $order     * @param int $page_size     * @return mixed     */    public static function getPromotionBooks(array $where = [], array $bids, array $order = [], $page_size = 15)    {        if (!$order) {            $order = ['recommend_index', 'desc'];        }        $res1 = self::join('books', 'book_configs.bid', '=', 'books.id')            ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')            ->select('book_configs.bid', 'book_configs.force_subscribe_chapter_seq', 'book_configs.cp_source', 'book_configs.vip_seq', 'book_configs.price', 'book_configs.cover', 'book_configs.book_name',                'book_configs.copyright', 'book_configs.charge_type', 'book_configs.is_on_shelf', 'books.author', 'books.intro', 'book_categories.category_name',                'category_id', 'status', 'chapter_count', 'book_configs.click_count', 'first_cid', 'last_cid', 'size', 'last_chapter', 'books.keyword',                'book_configs.recommend_index', 'book_configs.is_show_index_content', 'book_configs.product_id', 'book_categories.channel_name',                'books.last_cid', 'books.last_chapter', 'book_configs.product_id', 'book_configs.copyright_limit_data', 'books.updated_at as last_update_time',                'book_configs.promotion_domain', 'books.name as old_name', 'book_configs.recommend_cid', 'book_configs.is_high_quality'            );        if ($where) {            foreach ($where as $key => $v) {                //关键词查询                if ($key == 'key' && $v) {                    $res1 = $res1->where('book_configs.book_name', 'like', '%' . $v . '%');                }                //分类id查询                if ($key == 'category_id' && $v) {                    $res1 = $res1->where('books.category_id', '=', $v);                }                //上架查询                if ($key == 'is_on_shelf' && $v != '') {                    if (is_array($v)) {                        $res1 = $res1->whereIn('is_on_shelf', $v);                    } else {                        $res1 = $res1->where('is_on_shelf', '=', $v);                    }                }                //频道查询                if ($key == 'channel_name' && $v) {                    $res1 = $res1->where('book_categories.channel_name', '=', $v);                }                if ($key == 'status') {                    $res1 = $res1->where('books.status', '=', $v);                }                if ($key == 'author') {                    $res1 = $res1->where('books.author', 'like', '%' . $v . '%');                }                //旧书名查询                if ($key == 'old_name') {                    $res1 = $res1->where('books.name', 'like', '%' . $v . '%');                }                //版权日期查询                if ($key == 'copy_right_date') {                    if (is_array($v)) {                        $res1 = $res1->whereBetween('book_configs.copyright_limit_data', $v);                    } else {                        $res1 = $res1->where('book_configs.copyright_limit_data', '<=', $v);                    }                }                if ($key == 'domain') {                    $res1 = $res1->where('book_configs.promotion_domain', 'like', '%' . $v . '%');                }                if ($key == 'bid') {                    $res1 = $res1->where('book_configs.bid', '=', $v);                }                if ($key == 'is_high_quality') {                    $res1 = $res1->where('book_configs.is_high_quality', '=', $v);                }                if ($key == 'charge_type') {                    $res1 = $res1->where('book_configs.charge_type', '=', $v);                }                if ($key == 'hidden_books') {                    $res1 = $res1->whereNotIn('book_configs.bid', $v);                }            }            if ($bids) {                //$res1 = $res1->orwhereIn('book_configs.id', $bids);                if ((isset($where['key']) && !empty($where['key'])) && (isset($where['channel_name']) && !empty($where['channel_name']))) {                    $res1 = $res1->orWhere(function ($query) use ($bids, $where) {                        $query->where('is_on_shelf', 1)                            ->whereIn('book_configs.bid', $bids)                            ->where('book_configs.book_name', 'like', '%' . $where['key'] . '%')                            ->where('book_categories.channel_name', '=', $where['channel_name']);;                    });                } elseif (isset($where['key']) && !empty($where['key'])) {                    $res1 = $res1->orWhere(function ($query) use ($bids, $where) {                        $query->where('is_on_shelf', 1)                            ->whereIn('book_configs.bid', $bids)                            ->where('book_configs.book_name', 'like', '%' . $where['key'] . '%');                    });                } elseif (isset($where['channel_name']) && !empty($where['channel_name'])) {                    $res1 = $res1->orWhere(function ($query) use ($bids, $where) {                        $query->where('is_on_shelf', 1)                            ->whereIn('book_configs.bid', $bids)                            ->where('book_categories.channel_name', '=', $where['channel_name']);                    });                } else {                    $res1 = $res1->orwhereIn('book_configs.bid', $bids);                }            }        }        return $res1->orderBy($order[0], $order[1])->orderBy('book_configs.updated_at', 'desc')->paginate($page_size);    }    /**     * 根据id数组获取图书信息     * @param array $bid_arr     * @param array $order     * @return mixed     */    public static function getBooksByIds(array $bid_arr, array $order = [])    {        $res = self::join('books', 'book_configs.bid', '=', 'books.id')            ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')            ->select('book_configs.bid', 'book_configs.force_subscribe_chapter_seq', 'book_configs.vip_seq', 'book_configs.price',                'book_configs.cover', 'book_configs.book_name', 'book_configs.copyright', 'book_configs.charge_type', 'book_configs.is_on_shelf',                'books.author', 'books.intro', 'book_categories.category_name', 'category_id', 'status', 'chapter_count', 'book_configs.click_count',                'first_cid', 'last_cid', 'size', 'last_chapter', 'books.keyword', 'book_configs.recommend_index', 'book_configs.is_show_index_content',                'book_configs.product_id', 'book_categories.channel_name', 'books.last_cid', 'books.last_chapter', 'book_configs.product_id', 'books.updated_at as last_update_time',                'book_configs.copyright_limit_data', 'book_configs.promotion_domain', 'books.name as old_name', 'book_configs.recommend_cid'            )            ->whereIn('book_configs.bid', $bid_arr);        if ($order) {            $res->orderBy($order[0], $order[1]);        } else {            $str = implode(',', $bid_arr);            $field = 'bid,' . $str;            $res->orderBy(DB::raw('field(' . $field . ')'));        }        return $res->limit(30)->get();    }    /**     * 根据bid获取图书信息     * @param $bid     * @return mixed     */    public static function getBookById($bid)    {        if (empty($bid)) return null;        return self::join('books', 'book_configs.bid', '=', 'books.id')            ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')            ->select('book_configs.bid', 'book_configs.is_on_shelf', 'book_configs.force_subscribe_chapter_seq', 'book_configs.vip_seq', 'book_configs.cp_source', 'book_configs.price', 'book_configs.cover', 'book_configs.book_name',                'book_configs.copyright', 'book_configs.created_at', 'book_configs.charge_type', 'book_configs.is_on_shelf', 'books.author', 'books.intro', 'book_categories.category_name',                'category_id', 'status', 'chapter_count', 'first_cid', 'last_cid', 'size', 'last_chapter', 'books.keyword', 'book_configs.recommend_index','book_configs.test_status',                'book_configs.is_show_index_content', 'book_configs.click_count', 'book_configs.product_id', 'book_categories.channel_name', 'books.last_cid', 'books.updated_at as last_update_time',                'books.last_chapter', 'book_configs.product_id', 'book_configs.copyright_limit_data', 'book_configs.promotion_domain', 'books.name as old_name', 'book_configs.recommend_cid', 'book_configs.is_high_quality'            )->where('book_configs.bid', $bid)->first();    }    /**     * 根据关键词获取图书     * @param $key     * @param int $page_size     * @param null $is_on_shelf     * @return mixed     */    public static function getBooksByKey($key, $page_size = 15, $is_on_shelf = null)    {        $res = self::join('books', 'book_configs.bid', '=', 'books.id')            ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')            ->select('book_configs.bid', 'book_configs.force_subscribe_chapter_seq', 'book_configs.vip_seq', 'book_configs.price',                'book_configs.cover', 'book_configs.book_name', 'book_configs.copyright', 'book_configs.charge_type', 'book_configs.is_on_shelf',                'books.author', 'books.intro', 'book_categories.category_name', 'category_id', 'status', 'chapter_count', 'book_configs.click_count',                'first_cid', 'last_cid', 'size', 'last_chapter', 'books.keyword', 'book_configs.recommend_index', 'book_configs.is_show_index_content',                'book_configs.product_id', 'book_categories.channel_name', 'books.last_cid', 'books.last_chapter', 'book_configs.product_id', 'books.updated_at as last_update_time',                'book_configs.copyright_limit_data', 'book_configs.promotion_domain', 'books.name as old_name', 'book_configs.recommend_cid', 'book_configs.is_high_quality'            )            ->where('book_configs.book_name', 'like', '%' . $key . '%');        //->orWhere('books.intro', 'like', '%' . $key . '%')        //->orWhere('books.keyword', 'like', '%' . $key . '%')        //->orWhere('books.category_name', 'like', '%' . $key . '%')        //->orWhere('books.author', 'like', '%' . $key . '%');        /*        if ($is_on_shelf) {            if (is_array($is_on_shelf)) {                $res->whereIn('book_configs.is_on_shelf', $is_on_shelf);            } else {                $res->where('book_configs.is_on_shelf', '=', $is_on_shelf);            }        }*/        $res->whereIn('book_configs.is_on_shelf', [1, 2]);        $res = $res->paginate($page_size);        foreach ($res as $v) {            $v->book_url = '/detail?id=' . Hashids::encode($v->bid);        }        return $res;    }    /**     * 根据product_id获取图书     * @param $product_id     * @return mixed     */    public static function getBookByProduct($product_id)    {        return self::join('books', 'book_configs.bid', '=', 'books.id')            ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')            ->select('book_configs.bid', 'book_configs.force_subscribe_chapter_seq', 'book_configs.vip_seq', 'book_configs.price',                'book_configs.cover', 'book_configs.book_name', 'book_configs.copyright', 'book_configs.charge_type', 'book_configs.is_on_shelf',                'books.author', 'books.intro', 'book_categories.category_name', 'category_id', 'status', 'chapter_count', 'first_cid', 'last_cid', 'size', 'last_chapter',                'books.keyword', 'book_configs.recommend_index', 'book_configs.is_show_index_content', 'book_configs.click_count', 'book_configs.product_id'                , 'book_categories.channel_name', 'books.last_cid', 'books.last_chapter', 'book_configs.product_id', 'book_configs.recommend_cid', 'book_configs.is_high_quality'            )->where('book_configs.product_id', $product_id)->first();    }    /**     * 更新图书     * @param $bid     * @param array $param     * @return bool     */    public static function updateBookInfo($bid, array $param)    {        $book_info = self::getBookById($bid);        if (!$book_info) return false;        $update_data = [];        if (isset($param['force_subscribe_chapter_seq']) && !empty($param['force_subscribe_chapter_seq'])) $update_data['force_subscribe_chapter_seq'] = $param['force_subscribe_chapter_seq'];        if (isset($param['product_id']) && !empty($param['product_id'])) $update_data['product_id'] = $param['product_id'];        if (isset($param['book_name']) && !empty($param['book_name'])) $update_data['book_name'] = $param['book_name'];        if (isset($param['price']) && !empty($param['price'])) $update_data['price'] = $param['price'];        if (isset($param['cover']) && !empty($param['cover'])) $update_data['cover'] = $param['cover'];        if (isset($param['charge_type']) && !empty($param['charge_type'])) {            $update_data['charge_type'] = $param['charge_type'];            if (is_numeric($update_data['charge_type'])) {                $update_data['charge_type'] = 'CHAPTER';            }        }        if (isset($param['hot']) && !empty($param['hot'])) $update_data['hot'] = $param['hot'];        if (isset($param['roles']) && !empty($param['roles'])) $update_data['roles'] = $param['roles'];        if (isset($param['is_on_shelf']) && $param['is_on_shelf'] != '') $update_data['is_on_shelf'] = $param['is_on_shelf'];        if (isset($param['recommend_index']) && !empty($param['recommend_index'])) $update_data['recommend_index'] = $param['recommend_index'];        if (isset($param['is_show_index_content'])) $update_data['is_show_index_content'] = $param['is_show_index_content'];        if (isset($param['click_count']) && $param['click_count'] != '') $update_data['click_count'] = $param['click_count'];        if (isset($param['copyright_limit_data']) && $param['copyright_limit_data'] != '') $update_data['copyright_limit_data'] = $param['copyright_limit_data'];        if (isset($param['promotion_domain']) && $param['promotion_domain'] != '') $update_data['promotion_domain'] = $param['promotion_domain'];        if (isset($param['copyright']) && $param['copyright'] != '') $update_data['copyright'] = $param['copyright'];        $res1 = null;        if (isset($param['status'])) {            $res1 = Book::where('id', $bid)->update(['status' => $param['status']]);        }        if (isset($param['book_category_id'])) {            $catagory = BookCategory::select('category_name')->where('id', $param['book_category_id'])->first();            Book::where('id', $bid)->update(['category_id' => $param['book_category_id'], 'category_name' => $catagory->category_name]);        }        if (empty($update_data) && !$res1) return false;        return self::where('bid', $bid)->update($update_data);    }    /*     * 获取渠道,用户的全部书籍列表    */    public static function getLeftRecommendBook($channel_name, $is_high_quality,$force_update=false): array    {    	if($force_update){    		\Log::info('force_set_full_book_channel_name:'.$channel_name);    		Redis::set('full_book_channel_name:'.$channel_name,null);    	}    	    	// 存redis里面    	$full_book_bids = Redis::get('full_book_channel_name:'.$channel_name);    	$full_book_bids = json_decode($full_book_bids);    	if(!empty($full_book_bids)){    		\Log::info('direct_get_full_book_bids_from_redis:'.$channel_name);    	}else{    		// 获取全集    		$full_book_bids = self::join('books', 'book_configs.bid', '=', 'books.id')    		->leftjoin('book_categories', 'books.category_id', 'book_categories.id')    		->select('book_configs.bid')    		->where('book_categories.channel_name', $channel_name)    		->where('book_configs.is_high_quality', $is_high_quality)    		->where('book_configs.test_status', 0)// 不含测书    		->whereIn('book_configs.is_on_shelf', [2])    		->orderBy('book_configs.id', 'desc')    		->get()->pluck('bid')->all();    		if(!empty($full_book_bids)){    			\Log::info('set_full_book_channel_name:'.$channel_name.' data:'.json_encode($full_book_bids));    			Redis::set('full_book_channel_name:'.$channel_name,json_encode($full_book_bids));    		}    	}    	//     	\Log::info('$full_book_bids:'.json_encode($full_book_bids));        return $full_book_bids;            }    /*     * 获取渠道,用户的全部需要测试的书籍列表    */    public static function getLeftRecommendTestBook($channel_name)    {        // 获取test全集        $test_bids = self::getLeftRecommendTestBookConfigs($channel_name);//     	\Log::info('getLeftRecommendTestBook:'.json_encode($test_bids));        $last_bids = [];        if (!empty($test_bids)) {            foreach ($test_bids as $test_bid) {                $bid = $test_bid->bid;                $redis_bid_push_num = Redis::hget('SmartPushBookUserNum', $bid);                $plan_push_user_num = $test_bid->plan_push_user_num;                \Log::info('left_test_book,bid:' . $bid . ' redis_bid_push_num:' . $redis_bid_push_num . ' plan_push_user_num:' . $plan_push_user_num);                if ($redis_bid_push_num >= $plan_push_user_num) {                    \Log::info('full_update_test_book,bid:' . $bid . ' redis_bid_push_num:' . $redis_bid_push_num . ' plan_push_user_num:' . $plan_push_user_num);                    self::where('bid', $bid)->update(['test_status' => 2, 'test_update_time' => date('Y-m-d H:i:s')]);                    continue;                }                $last_bids[] = $bid;            }        }        return $last_bids;    }    /*     * 获取渠道,用户的全部需要测试的书籍列表    */    public static function getLeftRecommendTestBookConfigs($channel_name)    {        // 获取全集        return self::join('books', 'book_configs.bid', '=', 'books.id')            ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')            ->select('book_configs.bid', 'book_configs.plan_push_user_num')            ->where('book_categories.channel_name', $channel_name)            ->where('book_configs.test_status', 1)// 待测            ->groupBy('book_configs.bid')            ->orderBy('book_configs.test_update_time', 'asc')            ->limit(1)// 每次1本            ->get();    }    /*     * 获取用户的曾经推荐过的书籍列表    */    public static function getUserRecommendRecords($uid)    {        $recommend_bids = Redis::smembers('userRecommendBids:' . $uid);        return $recommend_bids;    }    /*     * 添加用户的曾经推荐过的书籍列表    */    public static function addUserRecommendRecords($uid, $bids)    {        foreach ($bids as $bid) {            Redis::sadd('userRecommendBids:' . $uid, $bid);        }    }    /*     * 清楚用户的曾经推荐过的书籍列表    */    public static function truncateUserRecommendRecords($uid)    {        \Log::info('truncateUserRecommendRecords:' . $uid);        Redis::del('userRecommendBids:' . $uid);    }    /*     * 书籍推送量+1    */    public static function incrBidPushNum($last_bids)    {        if (!empty($last_bids)) {            foreach ($last_bids as $last_bid) {//     			\Log::info('incrBidPushNum:test_bid' . $last_bid);                Redis::hincrby('SmartPushBookUserNum', $last_bid, 1);            }        }    }    /*     * 获取相同频道的4本高推荐图书    * 1、新书倒序  2、用户推荐过的,有阅读记录的不再推荐    */    public static function getLeftRecommendBids($uid = '', $channel_name, $num = 4, $loop = 1)    {//     	\Log::info('getLeftRecommendBids_loop:'.$loop.' $uid:'.$uid.' $channel_name:'.$channel_name.' $num:'.$num.' $loop:'.$loop);        if ($loop > 3) {            \Log::info('getLeftRecommendBids_return_loop:' . $loop . ' $uid:' . $uid . ' $channel_name:' . $channel_name);            return [];        }        // 测试书籍优先        $test_bids = self::getLeftRecommendTestBook($channel_name);        // 获取全集,不含测试书籍        $full_bid_no_tests = self::getLeftRecommendBook($channel_name, 1,false);        $full_bids = array_merge($test_bids, $full_bid_no_tests);        // 获取用户推荐过的详情        $recommend_bids = self::getUserRecommendRecords($uid);        // 获取用户阅读记录详情        $read_bids = ReadRecordService::getSimpleReadRecord($uid);        // 得到差集        $left_bids = array_diff($full_bids, $recommend_bids, $read_bids);//     	\Log::info('full_bids:'.json_encode($full_bids).' full_bid_no_tests:'.json_encode($full_bid_no_tests).' test_bids:'.json_encode($test_bids).' recommend_bids:'.json_encode($recommend_bids).' read_bids:'.json_encode($read_bids).' left_bids:'.json_encode($left_bids));        $left_bid_num = count($left_bids);        // 如果不够则清空推荐记录,重新追加剩下的        $last_bids = $need_bids = array();        if ($left_bid_num < $num) {            self::truncateUserRecommendRecords($uid);            $need_bids = self::getLeftRecommendBids($uid, $channel_name, $num - $left_bid_num, $loop + 1);//     		\Log::info('full_bids2:'.json_encode($full_bids));//     		\Log::info('merge_left_bids:'.json_encode($left_bids).' need_bids:'.json_encode($need_bids));            $last_bids = array_merge($left_bids, $need_bids);        } else {            $last_bids = array_slice($left_bids, 0, $num, false);        }//     	\Log::info('uid:'.$uid.' last_bids:'.json_encode($last_bids));        // 加入已经推荐        self::addUserRecommendRecords($uid, $last_bids);        // 书籍推送量+1        if ($loop == 1) {            self::incrBidPushNum($last_bids);        }        return $last_bids;    }    /*     * 获取相同频道的4本高推荐图书(循环获取)     * 1、新书倒序  2、用户推荐过的,有阅读记录的不再推荐     */    public static function getSimpleChannelBookLoop($bid, $num = 4, $uid = '')    {//     	\Log::info('getSimpleChannelBookLoop:bid:'.$bid.' num:'.$num.' uid:'.$uid);        if (empty($uid)) {            return self::getSimpleChannelBook($bid, $num);        }        $book_info = self::getBookById($bid);        $channel_name = isset($book_info->channel_name) ? $book_info->channel_name : '女频';        // 获取全集,减去阅读记录和推荐过的书籍id        $bids = self::getLeftRecommendBids($uid, $channel_name, $num, 1);        $res = self::join('books', 'book_configs.bid', '=', 'books.id')            ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')            ->select('book_configs.bid', 'book_configs.force_subscribe_chapter_seq', 'book_configs.vip_seq', 'book_configs.price', 'books.updated_at as last_update_time',                'book_configs.cover', 'book_configs.book_name', 'book_configs.copyright', 'book_configs.charge_type', 'book_configs.is_on_shelf',                'books.author', 'books.intro', 'book_categories.category_name', 'category_id', 'status', 'chapter_count', 'first_cid', 'last_cid', 'size', 'last_chapter',                'books.keyword', 'book_configs.recommend_index', 'book_configs.is_show_index_content', 'book_configs.click_count', 'book_configs.product_id'                , 'book_categories.channel_name', 'books.last_cid', 'books.last_chapter', 'book_configs.product_id', 'books.name as old_name'                , 'book_configs.recommend_cid', 'book_configs.is_high_quality'            )            ->whereIn('book_configs.bid', $bids)            ->orderBy('book_configs.id', 'desc')            ->get();        foreach ($res as $v) {            $v->url = '/reader?bid=' . Hashids::encode($v->bid) . '&cid=' . $v->first_cid;        }        return $res;    }        public static function  getHotRandomRecommendBooks($uid, $num=2){    	$sex = ForceSubscribeService::getSimpleSexByUid($uid);    	$channel_name = $sex==1?'男频':'女频';    	\Log::info('getHotRandomRecommendBooks,uid:'.$uid.' num:'.$num.' channel_name:'.$channel_name);    	$bids = [];    	$bids = self::getRandomRecommendBooks($channel_name, $num);    	return $bids;    }        public static function  getHotRandomRecommendBookText($distribution_channel_id,$uid, $num){    	$bids = self::getHotRandomRecommendBooks($uid, $num);    	$recomm_books = BookConfigService::getBooksByIds($bids,['bid','asc']);    	$content = '';    	if ($recomm_books) {    		$content .= "\n\n" . '热门书籍推荐';    		foreach ($recomm_books as $book) {    			$url = env('PROTOCOL') . '://site' . encodeDistributionChannelId($distribution_channel_id) . '.' . env('CUSTOM_HOST') . '.com/reader?bid=' . Hashids::encode($book->bid) . '&cid=' . $book->first_cid;    			$content .= "\n\n" . '<a href="' . $url . '"> ☞ 《' . $book->book_name . '》</a>';    		}    	}    	return $content;    }            /**     * 获取h5推荐的图书     */    public static function  getH5RecommendBooks($uid, $pos, $num=4){    	// 先从缓存取,1天有效期    	$h5_book_cache = Redis::get('userH5RecommendBids:' . $uid.':'.$pos);    	if(!empty($h5_book_cache)){    		\Log::info('h5_book_cache_exist:'.$uid);    		return json_decode($h5_book_cache);    	}    	    	// 判断渠道男女频    	$user = User::getById($uid);    	$distribution_channel_id = isset($user->distribution_channel_id)?$user->distribution_channel_id:'';    	// 男频强制推广男频书    	$channel_sex = ChannelService::getChannelCompanySex($distribution_channel_id);    	$channel_name = '';    	if($channel_sex == 1){    		$channel_name = '男频';    	}else{	    	$sex = ForceSubscribeService::getSimpleSexByUid($uid);	    	$channel_name = $sex==1?'男频':'女频';    	}    	\Log::info('getH5RecommendBooks:pos:'.$pos.' uid:'.$uid.' num:'.$num.' channel_name:'.$channel_name.' channel_sex:'.$channel_sex.' distribution_channel_id:'.$distribution_channel_id);    	    	$bids = [];    	$random_recommend = true;    	if($random_recommend){    		$bids = self::getRandomRecommendBooks($channel_name, $num);    	}    	    	$forceSubscribeUser = ForceSubscribeService::forceSubscribeUsersByUid(['uid'=>$uid]);    	$distribution_channel_id = isset($forceSubscribeUser->distribution_channel_id)?$forceSubscribeUser->distribution_channel_id:'';    	     	if (in_array($distribution_channel_id, [4042, 4043, 4044]) && $sex==2) {    		$bids = [2323, 1347, 2168, 1550, 1295, 1574];    	}    	    	\Log::info('getH5RecommendBooks:uid:'.$uid.' distribution_channel_id:'.$distribution_channel_id.' bids:'.json_encode($bids));    	     	if(!empty($bids)){    		$books = BookConfigService::getBooksByIds($bids,['bid','asc']);    		$data = $books->toArray();    		// 有效期24小时    		$redis_key = 'userH5RecommendBids:' . $uid.':'.$pos;    		Redis::set($redis_key,json_encode(object_to_array($data)));    		Redis::expire($redis_key,3600*24);    	}    	    	return $books;    }        /**     * 获取随机的推荐书籍bid     */    public static function  getRandomRecommendBooks($channel_name, $num){        if($channel_name == '男频'){            $channel_name_replace = 'male';        }else{            $channel_name_replace = 'female';        }        $redis_key = sprintf('channel_name:%s:num:%s',$channel_name_replace,$num);        $cache = Redis::get($redis_key);        if($cache) return explode(',',$cache);	    $bids = self::join('books', 'book_configs.bid', '=', 'books.id')	    ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')	    ->select('book_configs.bid')	    ->where('book_categories.channel_name', $channel_name)	    ->where('book_configs.is_high_quality', 1)	    ->where('book_configs.test_status', 0)// 不含测书	    ->whereIn('book_configs.is_on_shelf', [2])	    ->inRandomOrder()	    ->limit($num)	    ->get()->pluck('bid')->all();        if($bids){            Redis::setex($redis_key,7200,implode(',',$bids));        }	    return $bids;    }    /*     * 获取相同频道的4本高推荐图书    */    public static function getSimpleChannelBook($bid, $num = 4)    {        $book_info = self::getBookById($bid);        if (!$book_info) return false;        $channel_name = $book_info->channel_name;        $res = self::join('books', 'book_configs.bid', '=', 'books.id')            ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')            ->select('book_configs.bid', 'book_configs.force_subscribe_chapter_seq', 'book_configs.vip_seq', 'book_configs.price', 'books.updated_at as last_update_time',                'book_configs.cover', 'book_configs.book_name', 'book_configs.copyright', 'book_configs.charge_type', 'book_configs.is_on_shelf',                'books.author', 'books.intro', 'book_categories.category_name', 'category_id', 'status', 'chapter_count', 'first_cid', 'last_cid', 'size', 'last_chapter',                'books.keyword', 'book_configs.recommend_index', 'book_configs.is_show_index_content', 'book_configs.click_count', 'book_configs.product_id'                , 'book_categories.channel_name', 'books.last_cid', 'books.last_chapter', 'book_configs.product_id', 'books.name as old_name'                , 'book_configs.recommend_cid', 'book_configs.is_high_quality'            )            ->where('book_categories.channel_name', $channel_name)            ->where('book_configs.is_high_quality', 1)            ->whereIn('book_configs.is_on_shelf', [1, 2])            ->orderBy('recommend_index', 'desc')            ->get()            ->random($num);        foreach ($res as $v) {            $v->url = '/reader?bid=' . Hashids::encode($v->bid) . '&cid=' . $v->first_cid;        }        return $res;    }    /*     * 获取托管智能推送的书籍,头条要95分以上,其余4条优质书库随机,按分数倒叙排列     * 新版1条    */    public static function getTrusteeShipChannelBook($distribution_channel_id, $channel_name, $num = 4)    {    	// 找头条    	$first_res = self::join('books', 'book_configs.bid', '=', 'books.id')    	->leftjoin('book_categories', 'books.category_id', 'book_categories.id')    	->select('book_configs.bid', 'book_configs.recommend_index')    	->where('book_categories.channel_name', $channel_name)    	->where('book_configs.is_high_quality', 1)    	//     	->where('book_configs.recommend_index', '>=',95)    	->whereIn('book_configs.is_on_shelf', [2])    	->orderBy('recommend_index', 'desc')    	->limit(50)    	->get()    	->random(1);        	\Log::info('$first_res');    	\Log::info($first_res);        	$bids = [];    	$bids[] = $first_res[0]->bid;        	\Log::info('getTrusteeShipChannelBook_bids:' . json_encode($bids));        	$res = self::join('books', 'book_configs.bid', '=', 'books.id')    	->leftjoin('book_categories', 'books.category_id', 'book_categories.id')    	->select('book_configs.bid', 'book_configs.force_subscribe_chapter_seq', 'book_configs.vip_seq', 'book_configs.price', 'books.updated_at as last_update_time',    			'book_configs.cover', 'book_configs.book_name', 'book_configs.copyright', 'book_configs.charge_type', 'book_configs.is_on_shelf',    			'books.author', 'books.intro', 'book_categories.category_name', 'category_id', 'status', 'chapter_count', 'first_cid', 'last_cid', 'size', 'last_chapter',    			'books.keyword', 'book_configs.recommend_index', 'book_configs.is_show_index_content', 'book_configs.click_count', 'book_configs.product_id'    			, 'book_categories.channel_name', 'books.last_cid', 'books.last_chapter', 'book_configs.product_id', 'books.name as old_name'    			, 'book_configs.recommend_cid', 'book_configs.is_high_quality'    	)    	->where('book_categories.channel_name', $channel_name)    	->where('book_configs.is_high_quality', 1)    	->whereIn('book_configs.bid', $bids)    	->orderBy('recommend_index', 'desc')    	->get();        	foreach ($res as $v) {    		$v->url = '/reader?bid=' . Hashids::encode($v->bid) . '&cid=' . $v->first_cid;    	}    	\Log::info('last_res');    	\Log::info($res);    	return $res;    }        /*     * 获取托管智能推送的书籍,头条要95分以上,其余4条优质书库随机,按分数倒叙排列     * 老版多条    */    public static function getTrusteeShipChannelBookMulty($distribution_channel_id, $channel_name, $num = 4)    {        // TODO 内部渠道的书=内部+外部,外部渠道的书=外部        // 内部上架判断有点复杂,先统一外部上架        // 找头条        $first_res = self::join('books', 'book_configs.bid', '=', 'books.id')            ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')            ->select('book_configs.bid', 'book_configs.recommend_index')            ->where('book_categories.channel_name', $channel_name)            ->where('book_configs.is_high_quality', 1)//     	->where('book_configs.recommend_index', '>=',95)            ->whereIn('book_configs.is_on_shelf', [2])            ->orderBy('recommend_index', 'desc')            ->limit(10)            ->get()            ->random(1);        \Log::info('$first_res');        \Log::info($first_res);        $bids = [];        $bids[] = $first_res[0]->bid;        // 找其余3条        $left_res = self::join('books', 'book_configs.bid', '=', 'books.id')            ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')            ->select('book_configs.bid')            ->where('book_categories.channel_name', $channel_name)            ->where('book_configs.is_high_quality', 1)            ->whereNotIn('book_configs.bid', $bids)            ->whereIn('book_configs.is_on_shelf', [2])            ->orderBy('recommend_index', 'desc')            ->get()            ->random(3);        \Log::info('left_res');        \Log::info($left_res);        foreach ($left_res as $left_r) {            $bids[] = $left_r->bid;        }        \Log::info('getTrusteeShipChannelBook_bids:' . json_encode($bids));        $res = self::join('books', 'book_configs.bid', '=', 'books.id')            ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')            ->select('book_configs.bid', 'book_configs.force_subscribe_chapter_seq', 'book_configs.vip_seq', 'book_configs.price', 'books.updated_at as last_update_time',                'book_configs.cover', 'book_configs.book_name', 'book_configs.copyright', 'book_configs.charge_type', 'book_configs.is_on_shelf',                'books.author', 'books.intro', 'book_categories.category_name', 'category_id', 'status', 'chapter_count', 'first_cid', 'last_cid', 'size', 'last_chapter',                'books.keyword', 'book_configs.recommend_index', 'book_configs.is_show_index_content', 'book_configs.click_count', 'book_configs.product_id'                , 'book_categories.channel_name', 'books.last_cid', 'books.last_chapter', 'book_configs.product_id', 'books.name as old_name'                , 'book_configs.recommend_cid', 'book_configs.is_high_quality'            )            ->where('book_categories.channel_name', $channel_name)            ->where('book_configs.is_high_quality', 1)            ->whereIn('book_configs.bid', $bids)            ->orderBy('recommend_index', 'desc')            ->get();        foreach ($res as $v) {            $v->url = '/reader?bid=' . Hashids::encode($v->bid) . '&cid=' . $v->first_cid;        }        \Log::info('last_res');        \Log::info($res);        return $res;    }    /*    * H5专用,用户阅读完推荐    * 获取相同推荐    */    public static function getRecommendBooks($bid, $channel_name, $num = 4)    {        $res = self::join('books', 'book_configs.bid', '=', 'books.id')            ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')            ->select('book_configs.bid', 'book_configs.force_subscribe_chapter_seq', 'book_configs.vip_seq', 'book_configs.price',                'book_configs.cover', 'book_configs.book_name', 'book_configs.copyright', 'book_configs.charge_type', 'book_configs.is_on_shelf',                'books.author', 'books.intro', 'book_categories.category_name', 'category_id', 'status', 'chapter_count', 'first_cid', 'last_cid', 'size', 'last_chapter',                'books.keyword', 'book_configs.recommend_index', 'book_configs.is_show_index_content', 'book_configs.click_count', 'book_configs.product_id'                , 'book_categories.channel_name', 'books.last_cid', 'books.last_chapter', 'book_configs.product_id', 'books.name as old_name'                , 'book_configs.recommend_cid', 'book_configs.is_high_quality', 'books.updated_at as last_update_time'            )            ->where('book_categories.channel_name', $channel_name)            ->where('book_configs.bid', '!=', $bid)            ->where('book_configs.is_high_quality', 1)            ->orderBy('recommend_index', 'desc')->get();        $count = $res->count() >= $num ? $num : $res->count();        return $res->random($count);    }    /*    * 签到专用    * 获取相同推荐    */    public static function getSignRecommendBooks(array $bid, $channel_name, $num = 2)    {        $res = self::join('books', 'book_configs.bid', '=', 'books.id')            ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')            ->select('book_configs.bid', 'book_configs.force_subscribe_chapter_seq', 'book_configs.vip_seq', 'book_configs.price',                'book_configs.cover', 'book_configs.book_name', 'book_configs.copyright', 'book_configs.charge_type', 'book_configs.is_on_shelf',                'books.author', 'books.intro', 'book_categories.category_name', 'category_id', 'status', 'chapter_count', 'first_cid', 'last_cid', 'size', 'last_chapter',                'books.keyword', 'book_configs.recommend_index', 'book_configs.is_show_index_content', 'book_configs.click_count', 'book_configs.product_id'                , 'book_categories.channel_name', 'books.last_cid', 'books.last_chapter', 'book_configs.product_id', 'books.name as old_name'                , 'book_configs.recommend_cid', 'book_configs.is_high_quality', 'books.updated_at as last_update_time'            )            ->where('book_categories.channel_name', $channel_name)            ->where('book_configs.is_on_shelf', 2)            ->whereNotIn('book_configs.bid', $bid)            ->where('book_configs.is_high_quality', 1)            ->get();        $count = $res->count() >= $num ? $num : $res->count();        return $res->random($count);    }    /*    * 获取指定bid的书籍推荐    */    public static function getBidRecommendBooks(array $bids)    {        $res = self::join('books', 'book_configs.bid', '=', 'books.id')            ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')            ->select('book_configs.bid', 'book_configs.force_subscribe_chapter_seq', 'book_configs.vip_seq', 'book_configs.price',                'book_configs.cover', 'book_configs.book_name', 'book_configs.copyright', 'book_configs.charge_type', 'book_configs.is_on_shelf',                'books.author', 'books.intro', 'book_categories.category_name', 'category_id', 'status', 'chapter_count', 'first_cid', 'last_cid', 'size', 'last_chapter',                'books.keyword', 'book_configs.recommend_index', 'book_configs.is_show_index_content', 'book_configs.click_count', 'book_configs.product_id'                , 'book_categories.channel_name', 'books.last_cid', 'books.last_chapter', 'book_configs.product_id', 'books.name as old_name'                , 'book_configs.recommend_cid', 'book_configs.is_high_quality', 'books.updated_at as last_update_time'            )            ->whereIn('book_configs.bid', $bids)            ->get();        return $res;    }    /**     * 修改vip章节     */    public static function updateVipSeq($bid, $seq)    {        return self::where('bid', $bid)->update(['vip_seq' => $seq]);    }    public static function getAllBooks($on_shelf, $order)    {        if (!$order) {            $order = ['id', 'asc'];        }        return self::whereIn('is_on_shelf', $on_shelf)->select('bid', 'book_name')->orderBy($order[0], $order[1])->get();    }    /**     * 根据条件获取书籍,没有分页     */    public static function getBooksNoPage(array $where = [], array $order = [], array $on_shelf, $limit = 20)    {        if (!$order) {            $order = [['recommend_index', 'desc']];        }        $res = self::join('books', 'book_configs.bid', '=', 'books.id')            ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')            ->select('book_configs.bid', 'book_configs.force_subscribe_chapter_seq', 'book_configs.cp_source', 'book_configs.vip_seq', 'book_configs.price', 'book_configs.cover', 'book_configs.book_name',                'book_configs.copyright', 'book_configs.charge_type', 'book_configs.is_on_shelf', 'books.author', 'books.intro', 'book_categories.category_name',                'category_id', 'status', 'chapter_count', 'book_configs.click_count', 'first_cid', 'last_cid', 'size', 'last_chapter', 'books.keyword',                'book_configs.recommend_index', 'book_configs.is_show_index_content', 'book_configs.product_id', 'book_categories.channel_name',                'books.last_cid', 'books.last_chapter', 'book_configs.product_id', 'book_configs.copyright_limit_data', 'books.updated_at as last_update_time',                'book_configs.promotion_domain', 'books.name as old_name', 'book_configs.recommend_cid', 'book_configs.is_high_quality'            );        if ($where) {            foreach ($where as $v) {                $res->where($v[0], $v[1], $v[2]);            }        }        $res->whereIn('is_on_shelf', $on_shelf);        foreach ($order as $v) {            $res->orderBy($v[0], $v[1]);        }        return $res->limit($limit)->get();    }    public static function getAllCps()    {        $cps = self::select('cp_source')->groupBy('cp_source')->get();        $result = array();        foreach ($cps as $cp) {            if (!empty($cp['cp_source'])) {                $result[] = $cp['cp_source'];            }        }        return $result;    }    public static function getAllCpBooks()    {        $result = array();        $cp_books = self::select('cp_source', 'bid')->groupBy('cp_source')->groupBy('bid')->get();        foreach ($cp_books as $cp_book) {            $result[$cp_book['cp_source']][] = $cp_book['bid'];        }        return $result;    }    /*     * 得到cp某段时间某本书的消费    */    public static function getAllCpBookConsume($start_date, $end_date, $cps)    {        $result = self::leftjoin('book_order_statistical', 'book_order_statistical.bid', '=', 'book_configs.bid')            ->select('book_order_statistical.bid',                DB::raw('sum(book_order_statistical.charge_balance) as charge_balance'),                'book_configs.book_name', 'book_configs.is_on_shelf', 'book_configs.cp_source'            )            ->whereIn('book_configs.cp_source', $cps)            ->where('book_order_statistical.day', '>=', $start_date)            ->where('book_order_statistical.day', '<=', $end_date)            ->groupBy('book_configs.cp_source')            ->groupBy('book_order_statistical.bid')            ->get();        return $result;    }    public static function getBookByIdAndStatus($bid, $status)    {        return self::where('bid', $bid)->whereIn('is_on_shelf', $status)->first();    }    public static function get_all_test_books($is_all=false)    {    	if($is_all){    		return self::where('test_status', '<>', 0)->orderBy('test_status', 'asc')->orderBy('test_update_time', 'desc')->get();    	}else{    		return self::where('test_status', '<>', 0)->orderBy('test_status', 'asc')->orderBy('test_update_time', 'desc')->paginate();    	}    }    public static function get_test_books($test_status)    {        return self::where('test_status', $test_status)->get();    }    public static function updateTestBook($bid, $test_status, $plan_push_user_num = 10000)    {        return self::where('bid', $bid)->update(['test_status' => $test_status, 'plan_push_user_num' => $plan_push_user_num, 'test_update_time' => date('Y-m-d H:i:s')]);    }    public static function get_all_smart_push_books($is_all = false)    {    	if($is_all){    		return self::where('is_on_shelf', 2)->where('is_high_quality', 1)->orderBy('id', 'desc')->get();    	}else{    		return self::where('is_on_shelf', 2)->where('is_high_quality', 1)->orderBy('id', 'desc')->paginate();    	}    }    /**     * 获取书本的id,名称,作者,封面 并带分页     * @param bool $isAll 是否查询所有     * @param int $pageSize 每页的条数     * @param int $pageCount 页数     * @return mixed     */    static function getBookCoverInfos($isAll = false, $pageSize = 200, $pageCount = 0)    {        $obj = self::join('books', 'book_configs.bid', '=', 'books.id')->select('book_configs.bid', 'book_configs.book_name', 'books.author', 'book_configs.cover');        if ($isAll) {            return $obj->get();        } else {            return $obj->limit($pageSize)->offset($pageCount * $pageSize)->get();        }    }    /**     * 获取书本的总数     * @return mixed     */    static function getBooksCount()    {        return self::count();    }    /**     * 通过书名模糊搜索bid     * @param $book_name     * @return mixed     */    static function getIdByName($book_name)    {        return self::select('bid')->where('book_name', 'like', '%' . $book_name . '%')->get();    }}
 |