滚动加载

举例:获取文章列表,类似CSDN首页,加载
link->getArticleList
显示pagesize条articles
js控制滚动,符合加载条件时,ajax请求,到service,从当前page,加载pagesize条
service返回数据,js接受到的数据,显示在页面上


代码实例:


<?php
namespace App\Http\Controllers\Web;


use Illuminate\Http\Request;
use App\Models\Article;
use App\Models\User;
use App\Models\Comment;
use App\Models\UserArticle;
use App\Contracts\Editor\Renderer;
use Auth;


class ArticleController extends BaseController
{
    public function __construct()
    {
        $this->middleware('auth', ['except' => ['showList', 'detail']]);
    }


    public function showList(Request $request)
    {
        $params = [
            'page' => 1,
            'page_size' => config('config.default_page_size', 20),
        ];


        $articleDao = new Article();
        $articles = $articleDao->getArticles($params);


        $cdn = app('cdn');
        $imageDimension = config('config.article_cover_image_size', [
            'width' => 160,
            'height' => 120,
        ]);


        $articleIds = [];
        foreach ($articles as $article) {
            $articleIds[] = $article['article_id'];
            if (count($article->medias)) {
                $media = $article->medias[0];
                $article['cover_media'] = $media['cdn_path'] ? $cdn->getCdnMogr2Resource($media['cdn_path'], $imageDimension) : '';
            }
            if (count($article->user)) {
                $user = $article->user;
                $article['user_avatar'] = $user['avatar'] ? $cdn->getCdnMogr2Resource($user['avatar'], ['width' => 20, 'height' => 20]) : '';
            }
        }


        $user = Auth::user();
        if ($user && $articleIds) {
            $userArticleDao = new UserArticle();
            $userArticles = $userArticleDao->getUserArticles($user->user_id, $articleIds);
            $userArticleIds = $userArticles->pluck('article_id')->all();


            foreach ($articles as $article) {
                $article['is_favorite'] = in_array($article['article_id'], $userArticleIds);
            }
        }


        $data = [
            'articles' => $articles,
        ];


        return response()->view('article.list', $data);
    }


    public function detail(Renderer $renderer, $articleId)
    {
        $article = Article::find($articleId);


        if (!$article || $article->is_deleted) {
            abort(404);
        }


        $user = Auth::user();


        $articleDao = new Article();
        $articleDao->updateArticleViewCount(($user ? $user['user_id'] : null), $articleId);


        $article['content'] = $renderer->render($article['content']);


        if ($user) {
            $isFavorited = UserArticle::where([
                'user_id' => $user->user_id,
                'article_id' => $article['article_id'],
            ])->exists();
            $article['is_favorite'] = $isFavorited;
        }


        $commentDao = new Comment;
        $comments = $commentDao->getApprovedList([
            'article_id' => $articleId,
        ]);


        $data = [
            'article' => $article,
            'comments' => $comments
        ];


        return view('article.detail', $data);
    }


    public function getEdit(Request $request, Renderer $renderer)
    {
        $user = Auth::user();
        $articleId = $request->input('article_id');
        if ($articleId) {
            $article = Article::where([
                'article_id' => $articleId,
                'user_id' => $user->user_id,
                'is_deleted' => 0,
            ])->first();
        } else {
            $article = new Article();
            $article->title = '';
            $article->user_id = $user['user_id'];
            $article->is_active = 1;
            $article->is_deleted = 0;
            $article->review_count = 0;
            $article->favorited_count = 0;
        }


        if (!isset($article)) {
            abort(404);
        }


        $article['content'] = $renderer->render($article['content']);


        $data = [
            'user' => \Auth::user(),
            'article' => $article,
        ];


        return view('article.edit', $data);
    }
}


requirejs(['../config'], function () {
    require(['jquery', 'underscore', 'util', 'layzr', 'article_favorite'], function ($, _, util, Layzr) {
        $(function () {
            var pageSize = 20,
                page = 1,
                hasMore = true,
                container = $('.main-content'),
                listTemplate = _.template($('#article-list-template').html()),
                isLoading = false,
                $window = $(window),
                layzr = new Layzr();


            function renderArticles(articles) {
                if (articles && articles.length <= 0) {
                    return false;
                }


                contentContainer = container.find('.article-row');


                contentContainer.append(listTemplate({
                    articles: articles
                }));
            }


            function loadMore(params) {
                isLoading = true;
                $.ajax({
                    url: '/service/article/list',
                    type: 'GET',
                    data: params,
                }).done(function (response) {
                    if (response.status === 'SUCCESS') {
                        hasMore = response.body.hasMore;
                        renderArticles(response.body.articles);
                        layzr.updateSelector();
                        layzr.update();
                    }
                }).always(function () {
                    isLoading = false;
                });
            }


            $window.on('scroll', function () {
                if (!hasMore || isLoading) {
                    return;
                }


                if ($window.height() + $window.scrollTop() + 300 >= $(document).height()) {
                    loadMore({
                        page: ++page
                    });
                }
            });


            util.initGotoTop();
        });
    });
});


<?php
namespace App\Http\Controllers\Web\Service;


use App\Http\Controllers\Web\BaseController;
use Illuminate\Http\Request;
use App\Models\User;
use App\Models\Article;
use App\Models\Media;
use App\Models\UserArticle;
use App\Models\ArticleMedia;
use Auth;


class ArticleController extends BaseController
{
    public function __construct()
    {
        $this->middleware('auth', [
            'except' => ['getList'],
        ]);
    }


    public function getList(Request $request)
    {
        $params = [
            'page' => $request->input('page', 1),
            'page_size' => $request->input('page_size', config('config.default_page_size', 20)),
        ];


        $articleDao = new Article();
        $articles = $articleDao->getArticles($params);


        $cdn = app('cdn');
        $imageDimension = config('config.article_cover_image_size', [
            'width' => 160,
            'height' => 120,
        ]);


        $articleIds = $articles->pluck('article_id')->all();
        $user = Auth::user();
        if ($user && $articleIds) {
            $userArticleDao = new UserArticle();
            $userArticles = $userArticleDao->getUserArticles($user->user_id, $articleIds);
            $userArticleIds = $userArticles->pluck('article_id')->all();


            foreach ($articles as $article) {
                $article['is_favorite'] = in_array($article['article_id'], $userArticleIds);
            }
        }


        foreach ($articles as $article) {
            $coverMedia = '';
            if (count($article->medias)) {
                $media = $article->medias[0];
                $article['cover_media'] = $media['cdn_path'] ? $cdn->getResourceUrl($media['cdn_path'], $imageDimension) : '';
            }


            if (count($article->user)) {
                $user = $article->user;
                $article['user_avatar'] = $user['avatar'] ? $cdn->getCdnMogr2Resource($user['avatar'], ['width' => 20, 'height' => 20]) : '';
            }


            $article['article_url'] = route('article_detail', ['articleId' => $article['article_id']]);
            $article['user_url'] = route('user_home', ['userId' => $article['user_id']]);
            $article['user_name'] = $article['user_id'] ? $article->user->getDisplayName() : '系统';
        }


        $data = [
            'hasMore' => count($articles) == $params['page_size'],
            'articles' => $articles,
        ];


        return response()->json(format_json_success($data));
    }


    public function postFavorite(Request $request)
    {
        $this->validate($request, [
            'article_id' => 'required|integer',
        ]);


        $user = Auth::user();
        $userId = $user->user_id;


        if ($articleId = $request->input('article_id')) {
            $article = Article::actived()->find($articleId);
        }


        if (!isset($article)) {
            return response()->json(format_json_failed('invalid_parameter'));
        }


        if ($article['user_id'] == $userId) {
            return response()->json([
                'status' => 'SELF_ARTICLE'
            ]);
        }


        $userArticle = UserArticle::firstOrNew([
            'user_id' => $userId,
            'article_id' => $articleId,
        ]);


        $favoritedCount = $article['favorited_count'];
        if (!isset($userArticle['created'])) {
            $userArticle['created'] = now();
            $userArticle->save();


            $favoritedCount++;
            $article->increment('favorited_count', 1);
        }


        $data = [
            'favorited_count' => $favoritedCount,
        ];


        return response()->json(format_json_success($data));
    }


    public function postUnfavorite(Request $request)
    {
        $this->validate($request, [
            'article_id' => 'required|integer',
        ]);


        $user = Auth::user();
        $userId = $user->user_id;


        if ($articleId = $request->input('article_id')) {
            $article = Article::actived()->find($articleId);
        }


        if (!isset($article)) {
            return response()->json(format_json_failed('invalid_parameter'));
        }


        $result = UserArticle::where([
            'user_id' => $userId,
            'article_id' => $articleId,
        ])->delete();


        $favoritedCount = $article['favorited_count'];
        if ($result) {
            $favoritedCount--;
            try {
                $article->decrement('favorited_count', 1);
            } catch (\Exception $e) {
                // empty
            }
        }


        $data = [
            'favorited_count' => $favoritedCount < 0 ? 0 : $favoritedCount,
        ];


        return response()->json(format_json_success($data));
    }


    public function postDelete(Request $request)
    {
        $this->validate($request, [
            'article_id' => 'required|integer',
        ]);
        $articleId = $request->input('article_id');
        $article = Article::find($articleId);
        if (!isset($article)) {
            return response()->json(format_json_failed('invalid_parameter'));
        }
        $article['is_deleted'] = 1;
        $article->save();


        return response()->json(format_json_success());
    }


    public function postSaveMedia(Request $request)
    {
        $this->validate($request, [
            'type' => 'required|in:' . join(',', [Media::TYPE_IMAGE, Media::TYPE_VIDEO]),
            'path' => 'required',
        ]);


        $type = $request->input('type');
        $path = $request->input('path');
        $now = now();
        $media = Media::firstOrNew(['cdn_path' => $path]);
        if (!$media->media_id) {
            $media['type'] = $type;
            $media['cdn_path'] = $path;
            $media['user_id'] = 0;
            $media['created'] = $now;
            $media->save();
        }


        if ($media->media_id) {
            $articleId = $request->input('article_id');
            $article = Article::find($articleId);
            if ($article) {
                $articleMedia = ArticleMedia::firstOrNew([
                    'article_id' => $articleId,
                    'media_id' => $media->media_id,
                ]);
                $articleMedia['created'] = data_get($articleMedia, 'created', $now);
                $articleMedia->save();
            }


            $response = format_json_success([
                'media_id' => $media->media_id,
            ]);
        } else {
            $response = format_json_failed('request_failed');
        }


        return response()->json($response);
    }


    public function postSave(Request $request)
    {
        $this->validate($request, [
            'user_id' => 'required|integer',
            'title' => 'required|string|max:120',
            'article_id' => 'exists:article,article_id,is_deleted,0',
        ]);


        $articleId = $request->input('article_id');
        $userId = $request->input('user_id');
        if ($articleId) {
            $article = Article::find($articleId);
        } else {
            $article = new Article();
            $article->user_id = $userId;
            $article->is_active = 1;
            $article->is_deleted = 0;
            $article->review_count = 0;
            $article->favorited_count = 0;
        }


        $article->title = $request->input('title');
        $content = $request->input('content');
        $article->content = $content;


        $blocks = @json_decode($content, true);
        $mediaIds = [];
        $textContent = [];


        if ($blocks) {
            foreach ($blocks as $block) {
                $blockType = array_get($block, 'type');
                if (in_array($blockType, ['image', 'video'])
                    && ($mediaId = array_get($block, 'mediaId'))
                ) {
                    $mediaIds[] = $mediaId;
                }


                if ($blockType == 'text') {
                    $blockContent = str_replace('&nbsp;', ' ', array_get($block, 'content'));
                    $blockContent = strip_tags(html_entity_decode($blockContent));
                    $blockContent = trim($blockContent);
                    if ($blockContent !== '') {
                        $textContent[] = $blockContent;
                    }
                }
            }
        }


        if (count($textContent)) {
            $article->text_content = join("\n", $textContent);
            // TODO $article->preview_content = '';
        }


        $datas = [
            'media_ids' => $mediaIds,
        ];


        $result = $article->updateWithCallback(function ($article) use ($datas, $request) {
            $now = now();
            $articleId = $article->article_id;


            $mediaIds = array_get($datas, 'media_ids', []);


            $oldMediaIds = [];
            $removeMediaIds = [];
            $articleMedias = ArticleMedia::where('article_id', $articleId)->get();
            foreach ($articleMedias as $articleMedia) {
                if (!in_array($articleMedia->media_id, $mediaIds)) {
                    $removeMediaIds[] = $articleMedia->media_id;
                } else {
                    $oldMediaIds[] = $articleMedia->media_id;
                }
            }


            if ($removeMediaIds) {
                ArticleMedia::where('article_id', $articleId)
                        ->whereIn('media_id', $removeMediaIds)
                        ->delete();
            }


            $newMediaIds = array_diff($mediaIds, $oldMediaIds);
            if ($newMediaIds) {
                foreach ($newMediaIds as $mediaId) {
                    $articleMedia = new ArticleMedia([
                        'article_id' => $articleId,
                        'media_id' => $mediaId,
                        'is_cover' => 0,
                        'created' => $now,
                    ]);
                    $articleMedia->save();
                }
            }
        });


        if ($result) {
            $response = format_json_success();
        } else {
            $response = format_json_failed('request_failed');
        }


        return response()->json($response);
    }
}


@extends('layout.app')


@section('lib_styles')
@parent
@stop


@section('stylesheets')
@parent
<link href="{{ asset('/static/css/article/list.css') }}" rel="stylesheet" />
@endsection


@section('scripts')
<script type="text/javascript" src="{{ asset('static/libs/require.js') }}"
    data-main="{{ asset('static/js/article/list') }}"></script>
@stop


@section('content')
<div class="container">
    <div class="row padding-row list-container article-view">
        <div class="col-sm-12">
            <div class="main-content clearfix">
                <?php $currentUserId = Auth::user() ? Auth::user()->user_id : null ?>
                @if (count($articles))
                <div class="row article-row">
                    @foreach ($articles as $article)
                    <div class="col-xs-6 col-sm-6 article-item">
                        <div class="article-wrapper">
                            <div class="image-col">
                                <div class="article-image layzr-bg-image">
                                    <a class="image-link" href="{{ url('article/' . $article['article_id']) }}">
                                    <div class="img"
                                        @if ($article['cover_media'])
                                        data-layzr="{{ $article['cover_media'] }}"
                                        data-layzr-bg
                                        @else
                                         id="default-image"
                                        style="background-image: url({{ asset('/static/image/hero_image_1407x685.png') }})"
                                        @endif
                                    ></div>
                                    <div class="loading"></div>
                                    </a>
                                </div>
                            </div>
                            <div class="article-info">
                                <div class="name-group tag-left">
                                    <p class="article-name ellipsis" title="{{ $article['title'] }}">
                                        <a href="{{ url('article/' . $article['article_id']) }}">{{ $article['title'] }}</a>
                                    </p>
                                    <p class="article-user ellipsis" title="{{ $article['user_id'] ? $article->user->getDisplayName() : '系统'}}">
                                        <a href="{{ url('user/' . $article->user['user_id']) }}">
                                        @if ($article['user_id'])
                                        <img class="user-avator" src="{{ $article['user_avatar'] }}" />
                                        @endif
                                        </a>
                                        @if ($article['user_id'])
                                        <a href="{{ url('user/' . $article->user['user_id']) }}">
                                        {{ $article->user->getDisplayName() }}</a>
                                        @else
                                        系统
                                        @endif
                                        <span>{{ $article['created'] }}</span>
                                    </p>
                                    <p>{{ $article['text_content'] }}</p>
                                </div>
                                <p class="article-stats favorite-container" data-article-id="{{ $article['article_id'] }}">
                                    <span class="favorite-icon glyphicon {{ $article['is_favorite'] ? 'article-heart js-remove-favorite' : 'article-heart-empty js-add-favorite' }} {{ $article['user_id'] == $currentUserId ? 'default-cursor' : '' }}"
                                        title="{{ $article['is_favorite'] ? '取消收藏' : '收藏' }}"></span>
                                    <span class="ellipsis favorite-num" title="{{ $article['favorited_count'] }}">{{ $article['favorited_count'] }}</span>
                                </p>
                            </div>
                        </div>
                    </div>
                    @endforeach
                </div>
                @else
                    <p class="text-center">还没有发布任何物品,赶紧去发布吧!</p>
                @endif
            </div>
        </div>
    </div>
</div>


<script id="article-list-template" type="text/template">
    <% _.each(articles, function (article) { %>
    <div class="col-xs-6 col-sm-6 article-item">
        <div class="article-wrapper">
            <div class="image-col">
                <div class="article-image layzr-bg-image">
                    <a class="image-link" href="<%- article['article_url'] %>">
                    <div class="img"
                        <% if (article['cover_media']) { %>
                        data-layzr="<%- article['cover_media'] %>"
                        data-layzr-bg
                        <% } else { %>
                        id="default-image"
                        style="background-image: url({{ asset('/static/image/hero_image_1407x685.png') }})"
                        <% } %>
                    ></div>
                    <div class="loading"></div>
                    </a>
                </div>
            </div>
            <div class="article-info">
                <div class="name-group tag-left">
                    <p class="article-name ellipsis" title="<%- article.title %>">
                        <a href="<%- article['article_url'] %>"><%- article.title %></a>
                    </p>
                    <p class="article-user ellipsis" title="<%- article.user_name %>">
                        <% if (article.user_id != 0) { %>
                            <a href="<%- article['user_url'] %>">
                                <img class="user-avator" src="<%- article['user_avatar'] %>" />
                            </a>
                        <% } %>
                        <% if (article.user_id != 0) { %>
                        <a href="<%- article['user_url'] %>"><%- article.user_name %></a>
                        <% } else { %>
                        系统
                        <% } %>
                        <span><%- article.created %></span>
                    </p>
                    <p><%- article['text_content'] %></p>
                </div>
                <p class="article-stats favorite-container" data-article-id="<%- article['article_id'] %>">
                    <span class="favorite-icon glyphicon <%= article['is_favorite'] ? 'article-heart js-remove-favorite' : 'article-heart-empty js-add-favorite' %> <%= (article.user_id == '{{ $currentUserId }}') ? 'default-cursor' : '' %>"></span>
                    <span class="ellipsis favorite-num" title="<%- article['favorited_count'] %>"><%- article['favorited_count'] %></span>
                </p>
            </div>
        </div>
    </div>
    <% }); %>
</script>
@endsection



  • 0
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JFrameSea

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值