mirror of
https://gitee.com/koogua/course-tencent-cloud.git
synced 2025-06-26 20:52:44 +08:00
增加 XunSearch Paginator
This commit is contained in:
parent
8853bffc67
commit
d5dfd75c3d
@ -23,6 +23,8 @@ class NavTreeList extends Builder
|
||||
$list[] = [
|
||||
'id' => $nav->id,
|
||||
'name' => $nav->name,
|
||||
'target' => $nav->target,
|
||||
'url' => $nav->url,
|
||||
'children' => $this->handleChildren($nav),
|
||||
];
|
||||
}
|
||||
@ -44,6 +46,8 @@ class NavTreeList extends Builder
|
||||
$list[] = [
|
||||
'id' => $nav->id,
|
||||
'name' => $nav->name,
|
||||
'target' => $nav->target,
|
||||
'url' => $nav->url,
|
||||
];
|
||||
}
|
||||
|
||||
@ -70,7 +74,7 @@ class NavTreeList extends Builder
|
||||
{
|
||||
return NavModel::query()
|
||||
->where('position = :position:', ['position' => $position])
|
||||
->andWhere('deleted = 0')
|
||||
->andWhere('level = 1 AND deleted = 0')
|
||||
->execute();
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ namespace App\Console\Tasks;
|
||||
|
||||
use App\Models\Course as CourseModel;
|
||||
use App\Services\Search\CourseDocument;
|
||||
use App\Services\Search\CourseHandler;
|
||||
use App\Services\Search\CourseSearcher;
|
||||
use Phalcon\Cli\Task;
|
||||
use Phalcon\Mvc\Model\Resultset;
|
||||
use Phalcon\Mvc\Model\ResultsetInterface;
|
||||
@ -57,7 +57,7 @@ class CourseIndexTask extends Task
|
||||
*/
|
||||
protected function cleanCourseIndex()
|
||||
{
|
||||
$handler = new CourseHandler();
|
||||
$handler = new CourseSearcher();
|
||||
|
||||
$index = $handler->getXS()->getIndex();
|
||||
|
||||
@ -79,7 +79,7 @@ class CourseIndexTask extends Task
|
||||
return;
|
||||
}
|
||||
|
||||
$handler = new CourseHandler();
|
||||
$handler = new CourseSearcher();
|
||||
|
||||
$documenter = new CourseDocument();
|
||||
|
||||
@ -108,7 +108,7 @@ class CourseIndexTask extends Task
|
||||
*/
|
||||
protected function searchCourses($query)
|
||||
{
|
||||
$handler = new CourseHandler();
|
||||
$handler = new CourseSearcher();
|
||||
|
||||
return $handler->search($query);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ namespace App\Console\Tasks;
|
||||
use App\Library\Cache\Backend\Redis as RedisCache;
|
||||
use App\Repos\Course as CourseRepo;
|
||||
use App\Services\Search\CourseDocument;
|
||||
use App\Services\Search\CourseHandler;
|
||||
use App\Services\Search\CourseSearcher;
|
||||
use App\Services\Syncer\CourseIndex as CourseIndexSyncer;
|
||||
|
||||
class SyncCourseIndexTask extends Task
|
||||
@ -48,7 +48,7 @@ class SyncCourseIndexTask extends Task
|
||||
|
||||
$document = new CourseDocument();
|
||||
|
||||
$handler = new CourseHandler();
|
||||
$handler = new CourseSearcher();
|
||||
|
||||
$index = $handler->getXS()->getIndex();
|
||||
|
||||
|
@ -87,6 +87,10 @@ class Slide extends Service
|
||||
$data['cover'] = $validator->checkCover($post['cover']);
|
||||
}
|
||||
|
||||
if (isset($post['bg_color'])) {
|
||||
$data['bg_color'] = $validator->checkBgColor($post['bg_color']);
|
||||
}
|
||||
|
||||
if (isset($post['content'])) {
|
||||
if ($slide->target == SlideModel::TARGET_COURSE) {
|
||||
$course = $validator->checkCourse($post['content']);
|
||||
|
@ -29,6 +29,16 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">背景色</label>
|
||||
<div class="layui-input-inline">
|
||||
<input class="layui-input" type="text" name="bg_color" value="{{ slide.bg_color }}" lay-verify="required">
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<div id="bg-color"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">标题</label>
|
||||
<div class="layui-input-block">
|
||||
@ -75,4 +85,19 @@
|
||||
|
||||
</form>
|
||||
|
||||
{{ partial('partials/cover_uploader') }}
|
||||
{{ partial('partials/cover_uploader') }}
|
||||
|
||||
<script>
|
||||
layui.use(['jquery', 'colorpicker'], function () {
|
||||
var $ = layui.jquery;
|
||||
var colorPicker = layui.colorpicker;
|
||||
colorPicker.render({
|
||||
elem: '#bg-color',
|
||||
color: '{{ slide.bg_color }}',
|
||||
predefine: true,
|
||||
change: function (color) {
|
||||
$('input[name=bg_color]').val(color);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
25
app/Http/Web/Controllers/PageController.php
Normal file
25
app/Http/Web/Controllers/PageController.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Web\Controllers;
|
||||
|
||||
use App\Services\Frontend\Page\PageInfo as PageInfoService;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/page")
|
||||
*/
|
||||
class PageController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/{id:[0-9]+}", name="web.page.show")
|
||||
*/
|
||||
public function showAction($id)
|
||||
{
|
||||
$service = new PageInfoService();
|
||||
|
||||
$page = $service->handle($id);
|
||||
|
||||
$this->view->setVar('page', $page);
|
||||
}
|
||||
|
||||
}
|
@ -2,6 +2,8 @@
|
||||
|
||||
namespace App\Http\Web\Controllers;
|
||||
|
||||
use App\Services\Frontend\Search\CourseSearch;
|
||||
|
||||
/**
|
||||
* @RoutePrefix("/search")
|
||||
*/
|
||||
@ -9,80 +11,12 @@ class SearchController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @Get("/courses", name="web.search.courses")
|
||||
* @Get("/", name="web.search.show")
|
||||
*/
|
||||
public function coursesAction()
|
||||
public function showAction()
|
||||
{
|
||||
$query = $this->request->getQuery('q');
|
||||
|
||||
$indexer = new \App\Library\Indexer\Course();
|
||||
|
||||
$courses = $indexer->search($query);
|
||||
|
||||
echo "total: {$courses['total']}<br>";
|
||||
echo "<hr>";
|
||||
|
||||
foreach ($courses['items'] as $course) {
|
||||
echo "title:{$course->title}<br>";
|
||||
echo "summary:{$course->summary}<br>";
|
||||
echo "tags:{$course->tags}<br>";
|
||||
echo "<hr>";
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/course/update", name="web.search.update_course")
|
||||
*/
|
||||
public function updateCourseAction()
|
||||
{
|
||||
$indexer = new \App\Library\Indexer\Course();
|
||||
|
||||
$courseRepo = new \App\Repos\Course();
|
||||
|
||||
$course = $courseRepo->findById(1);
|
||||
|
||||
$indexer->updateIndex($course);
|
||||
|
||||
echo "update ok";
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/course/create", name="web.search.create_course")
|
||||
*/
|
||||
public function createCourseAction()
|
||||
{
|
||||
$indexer = new \App\Library\Indexer\Course();
|
||||
|
||||
$courseRepo = new \App\Repos\Course();
|
||||
|
||||
$course = $courseRepo->findById(1);
|
||||
|
||||
$indexer->addIndex($course);
|
||||
|
||||
echo "create ok";
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Get("/course/delete", name="web.search.delete_course")
|
||||
*/
|
||||
public function deleteCourseAction()
|
||||
{
|
||||
$indexer = new \App\Library\Indexer\Course();
|
||||
|
||||
$courseRepo = new \App\Repos\Course();
|
||||
|
||||
$course = $courseRepo->findById(1);
|
||||
|
||||
$indexer->deleteIndex($course);
|
||||
|
||||
echo "delete ok";
|
||||
|
||||
$service = new CourseSearch();
|
||||
dd($service->handle());
|
||||
exit;
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ use App\Caches\IndexLiveList as IndexLiveListCache;
|
||||
use App\Caches\IndexNewCourseList as IndexNewCourseListCache;
|
||||
use App\Caches\IndexSlideList as IndexSlideListCache;
|
||||
use App\Caches\IndexVipCourseList as IndexVipCourseListCache;
|
||||
use App\Models\Slide as SlideModel;
|
||||
|
||||
class Index extends Service
|
||||
{
|
||||
@ -15,7 +16,36 @@ class Index extends Service
|
||||
{
|
||||
$cache = new IndexSlideListCache();
|
||||
|
||||
return $cache->get();
|
||||
/**
|
||||
* @var array $slides
|
||||
*/
|
||||
$slides = $cache->get();
|
||||
|
||||
if (!$slides) return [];
|
||||
|
||||
foreach ($slides as $key => $slide) {
|
||||
switch ($slide['target']) {
|
||||
case SlideModel::TARGET_COURSE:
|
||||
$slides[$key]['url'] = $this->url->get([
|
||||
'for' => 'web.course.show',
|
||||
'id' => $slide['content'],
|
||||
]);
|
||||
break;
|
||||
case SlideModel::TARGET_PAGE:
|
||||
$slides[$key]['url'] = $this->url->get([
|
||||
'for' => 'web.page.show',
|
||||
'id' => $slide['content'],
|
||||
]);
|
||||
break;
|
||||
case SlideModel::TARGET_LINK:
|
||||
$slides[$key]['url'] = $slide['content'];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $slides;
|
||||
}
|
||||
|
||||
public function getLives()
|
||||
|
@ -2,18 +2,77 @@
|
||||
|
||||
{% block content %}
|
||||
|
||||
{%- macro model_info(value) %}
|
||||
{% if value == 'vod' %}
|
||||
<span class="layui-badge layui-bg-green">点播{{ request.get('id') }}</span>
|
||||
{% elseif value == 'live' %}
|
||||
<span class="layui-badge layui-bg-blue">直播</span>
|
||||
{% elseif value == 'read' %}
|
||||
<span class="layui-badge layui-bg-black">图文</span>
|
||||
{% endif %}
|
||||
{%- macro category_courses(courses) %}
|
||||
<div class="layui-tab layui-tab-brief">
|
||||
<ul class="layui-tab-title">
|
||||
{% for category in courses %}
|
||||
<li {% if loop.first %}class="layui-this"{% endif %}>{{ category.name }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<div class="layui-tab-content">
|
||||
{% for category in courses %}
|
||||
<div class="layui-tab-item {% if loop.first %}layui-show{% endif %}">
|
||||
{% for course in category.courses %}
|
||||
<div class="course-card">
|
||||
<div class="cover"></div>
|
||||
<div class="title">{{ course.title }}</div>
|
||||
<div class="info"></div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{%- endmacro %}
|
||||
|
||||
<div class="model">{{ model_info('vod') }}</div>
|
||||
<h1>I am body</h1>
|
||||
<h2>ID:{{ request.get('id') }}</h2>
|
||||
<div class="index-module">
|
||||
<div class="layui-carousel" id="carousel">
|
||||
<div class="carousel" carousel-item>
|
||||
{% for slide in slides %}
|
||||
<div class="item" style="background-color:{{ slide.bg_color }}">
|
||||
<a href="{{ slide.url }}">
|
||||
<img src="{{ slide.cover }}" alt="{{ slide.title }}">
|
||||
</a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="index-module">
|
||||
<div class="header">新上课程</div>
|
||||
<div class="content">
|
||||
{{ category_courses(new_courses) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="index-module">
|
||||
<div class="header">免费课程</div>
|
||||
<div class="content">
|
||||
{{ category_courses(free_courses) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="index-module">
|
||||
<div class="header">会员课程</div>
|
||||
<div class="content">
|
||||
{{ category_courses(vip_courses) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block inline_js %}
|
||||
|
||||
<script>
|
||||
layui.use(['carousel'], function () {
|
||||
var carousel = layui.carousel;
|
||||
carousel.render({
|
||||
elem: '#carousel',
|
||||
width: '600px',
|
||||
height: '338px'
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
@ -1 +1,14 @@
|
||||
<h1>I am footer</h1>
|
||||
<div class="bottom-nav">
|
||||
{% for nav in site_navs.bottom %}
|
||||
<a href="{{ nav.url }}" target="{{ nav.target }}">{{ nav.name }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="copyright">
|
||||
{{ site_settings.copyright }}
|
||||
{% if site_settings.icp_sn %}
|
||||
<a href="{{ site_settings.icp_link }}">{{ site_settings.icp_sn }}</a>
|
||||
{% endif %}
|
||||
{% if site_settings.police_sn %}
|
||||
<a href="{{ site_settings.police_link }}">{{ site_settings.police_sn }}</a>
|
||||
{% endif %}
|
||||
</div>
|
@ -1 +1,54 @@
|
||||
<h1>I am header</h1>
|
||||
<div class="logo"></div>
|
||||
|
||||
<div class="top-nav">
|
||||
<ul class="layui-nav">
|
||||
{% for nav in site_navs.top %}
|
||||
{% if nav.children %}
|
||||
<li class="layui-nav-item">
|
||||
<a href="javascript:">{{ nav.name }}</a>
|
||||
<dl class="layui-nav-child">
|
||||
{% for child in nav.children %}
|
||||
<dd><a href="{{ child.url }}" target="{{ child.target }}">{{ child.name }}</a></dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="layui-nav-item">
|
||||
<a href="{{ nav.url }}">{{ nav.name }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="search">
|
||||
<form class="layui-form" action="{{ url({'for':'web.search.show'}) }}">
|
||||
<div class="layui-inline">
|
||||
<input type="text" name="q" placeholder="请输入课程关键字...">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="user layui-layout-right">
|
||||
{% if auth_user %}
|
||||
<ul class="layui-nav">
|
||||
<li class="layui-nav-item"><a href="{{ url({'for':'web.my.courses'}) }}">消息</a></li>
|
||||
<li class="layui-nav-item">
|
||||
<a href="javascript:">{{ auth_user.name }}</a>
|
||||
<dl class="layui-nav-child">
|
||||
<dd><a href="{{ url({'for':'web.my.courses'}) }} }}">我的课程</a></dd>
|
||||
<dd><a href="{{ url({'for':'web.my.courses'}) }} }}">我的收藏</a></dd>
|
||||
<dd><a href="{{ url({'for':'web.my.courses'}) }} }}">我的咨询</a></dd>
|
||||
<dd><a href="{{ url({'for':'web.my.courses'}) }} }}">我的订单</a></dd>
|
||||
<dd><a href="{{ url({'for':'web.my.courses'}) }} }}">个人设置</a></dd>
|
||||
<dd><a href="{{ url({'for':'web.my.courses'}) }} }}">退出登录</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
</ul>
|
||||
{% else %}
|
||||
<ul class="layui-nav">
|
||||
<li class="layui-nav-item"><a href="{{ url({'for':'web.account.login'}) }}">登录</a></li>
|
||||
<li class="layui-nav-item"><a href="{{ url({'for':'web.account.register'}) }}">注册</a></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
@ -1,29 +1,42 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html lang="zh-CN-Hans">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<meta name="keywords" content="{{ site_seo.getKeywords() }}">
|
||||
<meta name="description" content="{{ site_seo.getDescription() }}">
|
||||
<title>{{ site_seo.getTitle() }}</title>
|
||||
{{ icon_link("favicon.ico") }}
|
||||
{{ css_link("lib/layui/css/layui.css") }}
|
||||
{{ css_link("web/css/common.css") }}
|
||||
{{ icon_link('favicon.ico') }}
|
||||
{{ css_link('lib/layui/css/layui.css') }}
|
||||
{{ css_link('web/css/common.css') }}
|
||||
{% block link_css %}{% endblock %}
|
||||
{% block inline_css %}{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="header">
|
||||
{{ partial('partials/header') }}
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
|
||||
<div id="footer">
|
||||
{{ partial('partials/footer') }}
|
||||
</div>
|
||||
{{ js_include("lib/layui/layui.js") }}
|
||||
|
||||
{{ js_include('lib/layui/layui.js') }}
|
||||
|
||||
<script>
|
||||
layui.use(['element'], function () {
|
||||
var element = layui.element;
|
||||
})
|
||||
</script>
|
||||
|
||||
{% block include_js %}{% endblock %}
|
||||
|
||||
{% block inline_js %}{% endblock %}
|
||||
|
||||
</body>
|
||||
</html>
|
155
app/Library/Paginator/Adapter/XunSearch.php
Normal file
155
app/Library/Paginator/Adapter/XunSearch.php
Normal file
@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
namespace App\Library\Paginator\Adapter;
|
||||
|
||||
use Phalcon\Http\Request as HttpRequest;
|
||||
use Phalcon\Paginator\Adapter as PaginatorAdapter;
|
||||
use Phalcon\Paginator\Exception as PaginatorException;
|
||||
|
||||
/**
|
||||
*
|
||||
* Pagination using xunsearch as source of data
|
||||
*
|
||||
* <code>
|
||||
* use App\Library\Paginator\Adapter\XunSearch;
|
||||
*
|
||||
* $paginator = new XunSearch(
|
||||
* [
|
||||
* "xs" => $xs,
|
||||
* "query" => $query,
|
||||
* "highlight" => $highlight,
|
||||
* "page" => $page,
|
||||
* "limit" => $limit,
|
||||
* ]
|
||||
* );
|
||||
*</code>
|
||||
*/
|
||||
class XunSearch extends PaginatorAdapter
|
||||
{
|
||||
|
||||
protected $config;
|
||||
|
||||
protected $url;
|
||||
|
||||
protected $params = [];
|
||||
|
||||
public function __construct(array $config)
|
||||
{
|
||||
if (!isset($config['xs']) || ($config['xs'] instanceof \XS) == false) {
|
||||
throw new PaginatorException('Invalid xs parameter');
|
||||
}
|
||||
|
||||
if (empty($config['query'])) {
|
||||
throw new PaginatorException('Invalid query parameter');
|
||||
}
|
||||
|
||||
if (empty($config['page']) || $config['page'] != intval($config['page'])) {
|
||||
throw new PaginatorException('Invalid page parameter');
|
||||
}
|
||||
|
||||
if (empty($config['limit']) || $config['limit'] != intval($config['limit'])) {
|
||||
throw new PaginatorException('Invalid limit parameter');
|
||||
}
|
||||
|
||||
if (isset($config['highlight']) && !is_array($config['highlight'])) {
|
||||
throw new PaginatorException('Invalid highlight parameter');
|
||||
}
|
||||
|
||||
$this->config = $config;
|
||||
$this->_page = $config['page'] ?? 1;
|
||||
$this->_limitRows = $config['limit'] ?? 15;
|
||||
}
|
||||
|
||||
public function paginate()
|
||||
{
|
||||
/**
|
||||
* @var \XS $xs
|
||||
*/
|
||||
$xs = $this->config['xs'];
|
||||
|
||||
$page = $this->_page;
|
||||
$limit = $this->_limitRows;
|
||||
$offset = ($page - 1) * $limit;
|
||||
|
||||
$search = $xs->getSearch();
|
||||
|
||||
$docs = $search->setQuery($this->config['query'])
|
||||
->setLimit($limit, $offset)
|
||||
->search();
|
||||
|
||||
$totalCount = $search->getLastCount();
|
||||
|
||||
$fields = array_keys($xs->getAllFields());
|
||||
|
||||
$items = [];
|
||||
|
||||
foreach ($docs as $doc) {
|
||||
$item = [];
|
||||
foreach ($fields as $field) {
|
||||
if (in_array($field, $this->config['highlight'])) {
|
||||
$item[$field] = $search->highlight($doc->{$field});
|
||||
} else {
|
||||
$item[$field] = $doc->{$field};
|
||||
}
|
||||
}
|
||||
$items[] = $item;
|
||||
}
|
||||
|
||||
$totalPages = ceil($totalCount / $limit);
|
||||
|
||||
$pager = new \stdClass();
|
||||
|
||||
$pager->first = 1;
|
||||
$pager->previous = $page > 1 ? $page - 1 : 1;
|
||||
$pager->next = $page < $totalPages ? $page + 1 : $page;
|
||||
$pager->last = $totalPages;
|
||||
$pager->total_items = $totalCount;
|
||||
$pager->items = $items;
|
||||
|
||||
$this->initParams();
|
||||
|
||||
$pager->first = $this->buildPageUrl($pager->first);
|
||||
$pager->previous = $this->buildPageUrl($pager->previous);
|
||||
$pager->next = $this->buildPageUrl($pager->next);
|
||||
$pager->last = $this->buildPageUrl($pager->last);
|
||||
|
||||
return $pager;
|
||||
}
|
||||
|
||||
public function getPaginate()
|
||||
{
|
||||
return $this->paginate();
|
||||
}
|
||||
|
||||
protected function initParams()
|
||||
{
|
||||
$request = new HttpRequest();
|
||||
|
||||
$params = $request->get();
|
||||
|
||||
if ($params) {
|
||||
foreach ($params as $key => $value) {
|
||||
if (strlen($value) == 0) {
|
||||
unset($params[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->params = $params;
|
||||
|
||||
if (!empty($this->params['_url'])) {
|
||||
$this->url = $this->params['_url'];
|
||||
unset($this->params['_url']);
|
||||
} else {
|
||||
$this->url = $request->get('_url');
|
||||
}
|
||||
}
|
||||
|
||||
protected function buildPageUrl($page)
|
||||
{
|
||||
$this->params['page'] = $page;
|
||||
|
||||
return $this->url . '?' . http_build_query($this->params);
|
||||
}
|
||||
|
||||
}
|
@ -36,6 +36,13 @@ class Slide extends Model
|
||||
*/
|
||||
public $cover;
|
||||
|
||||
/**
|
||||
* 背景色
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $bg_color;
|
||||
|
||||
/**
|
||||
* 摘要
|
||||
*
|
||||
|
32
app/Services/Frontend/Page/PageInfo.php
Normal file
32
app/Services/Frontend/Page/PageInfo.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Frontend\Page;
|
||||
|
||||
use App\Models\Page as PageModel;
|
||||
use App\Services\Frontend\PageTrait;
|
||||
use App\Services\Frontend\Service as FrontendService;
|
||||
|
||||
class PageInfo extends FrontendService
|
||||
{
|
||||
|
||||
use PageTrait;
|
||||
|
||||
public function handle($id)
|
||||
{
|
||||
$page = $this->checkPageCache($id);
|
||||
|
||||
return $this->handlePage($page);
|
||||
}
|
||||
|
||||
protected function handlePage(PageModel $page)
|
||||
{
|
||||
return [
|
||||
'id' => $page->id,
|
||||
'title' => $page->title,
|
||||
'content' => $page->content,
|
||||
'create_time' => $page->create_time,
|
||||
'update_time' => $page->update_time,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
24
app/Services/Frontend/PageTrait.php
Normal file
24
app/Services/Frontend/PageTrait.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Frontend;
|
||||
|
||||
use App\Validators\Page as PageValidator;
|
||||
|
||||
trait PageTrait
|
||||
{
|
||||
|
||||
public function checkPage($id)
|
||||
{
|
||||
$validator = new PageValidator();
|
||||
|
||||
return $validator->checkPage($id);
|
||||
}
|
||||
|
||||
public function checkPageCache($id)
|
||||
{
|
||||
$validator = new PageValidator();
|
||||
|
||||
return $validator->checkPageCache($id);
|
||||
}
|
||||
|
||||
}
|
37
app/Services/Frontend/Search/CourseSearch.php
Normal file
37
app/Services/Frontend/Search/CourseSearch.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Frontend\Search;
|
||||
|
||||
use App\Library\Paginator\Adapter\XunSearch as XunSearchPaginator;
|
||||
use App\Library\Paginator\Query as PagerQuery;
|
||||
use App\Services\Frontend\Service as FrontendService;
|
||||
use App\Services\Search\CourseSearcher as CourseSearcherService;
|
||||
|
||||
class CourseSearch extends FrontendService
|
||||
{
|
||||
|
||||
public function handle()
|
||||
{
|
||||
|
||||
$pagerQuery = new PagerQuery();
|
||||
|
||||
$params = $pagerQuery->getParams();
|
||||
$page = $pagerQuery->getPage();
|
||||
$limit = $pagerQuery->getLimit();
|
||||
|
||||
$courseSearcher = new CourseSearcherService();
|
||||
|
||||
$paginator = new XunSearchPaginator([
|
||||
'xs' => $courseSearcher->getXS(),
|
||||
'highlight' => $courseSearcher->getHighlightFields(),
|
||||
'query' => $params['query'],
|
||||
'page' => $page,
|
||||
'limit' => $limit,
|
||||
]);
|
||||
|
||||
$pager = $paginator->getPaginate();
|
||||
|
||||
dd($pager);
|
||||
}
|
||||
|
||||
}
|
@ -4,7 +4,7 @@ namespace App\Services\Search;
|
||||
|
||||
use Phalcon\Mvc\User\Component;
|
||||
|
||||
class CourseHandler extends Component
|
||||
class CourseSearcher extends Component
|
||||
{
|
||||
|
||||
/**
|
||||
@ -29,6 +29,16 @@ class CourseHandler extends Component
|
||||
return $this->xs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取高亮字段
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getHighlightFields()
|
||||
{
|
||||
return ['title', 'summary'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索课程
|
||||
*
|
@ -66,6 +66,17 @@ class Slide extends Validator
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function checkBgColor($bgColor)
|
||||
{
|
||||
$value = $this->filter->sanitize($bgColor, ['trim', 'string']);
|
||||
|
||||
if (!preg_match('/^#[0-9a-fA-F]{6}$/', $bgColor)) {
|
||||
throw new BadRequestException('slide.invalid_bg_color');
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function checkTarget($target)
|
||||
{
|
||||
$list = SlideModel::targetTypes();
|
||||
|
Loading…
x
Reference in New Issue
Block a user