first prod
This commit is contained in:
8
app/modules/view/ViewModule.php
Normal file
8
app/modules/view/ViewModule.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace app\modules\view;
|
||||
|
||||
class ViewModule extends \kernel\app_modules\view\ViewModule
|
||||
{
|
||||
|
||||
}
|
8
app/modules/view/controllers/ViewController.php
Normal file
8
app/modules/view/controllers/ViewController.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace app\modules\view\controllers;
|
||||
|
||||
class ViewController extends \kernel\app_modules\view\controllers\ViewController
|
||||
{
|
||||
|
||||
}
|
12
app/modules/view/manifest.json
Normal file
12
app/modules/view/manifest.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "Просмотры",
|
||||
"version": "0.1",
|
||||
"author": "ITGuild",
|
||||
"slug": "view",
|
||||
"description": "Просмотры module",
|
||||
"module_class": "app\\modules\\view\\ViewModule",
|
||||
"module_class_file": "{APP}/modules/view/ViewModule.php",
|
||||
"routs": "routs/view.php",
|
||||
"migration_path": "migrations",
|
||||
"dependence": "menu"
|
||||
}
|
2
app/modules/view/routs/view.php
Normal file
2
app/modules/view/routs/view.php
Normal file
@@ -0,0 +1,2 @@
|
||||
<?php
|
||||
include KERNEL_APP_MODULES_DIR . "/view/routs/view.php";
|
@@ -10,12 +10,27 @@ class AdminSliderAssets extends Assets
|
||||
|
||||
protected function createCSS(): void
|
||||
{
|
||||
$this->registerCSS(slug: "select2", resource: "https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css", addResourceURI: false);
|
||||
$this->registerCSS(
|
||||
slug: "select2",
|
||||
resource: "https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css",
|
||||
addResourceURI: false,
|
||||
after: 'bootstrap'
|
||||
);
|
||||
}
|
||||
|
||||
protected function createJS(): void
|
||||
{
|
||||
$this->registerJS(slug: "select2", resource: "https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js", addResourceURI: false);
|
||||
$this->registerJS(
|
||||
slug: "select2",
|
||||
resource: "https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js",
|
||||
addResourceURI: false,
|
||||
after: 'jquery',
|
||||
);
|
||||
$this->registerJS(
|
||||
slug: "slider",
|
||||
resource: "/slider.js",
|
||||
after: 'select2',
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@@ -11,6 +11,7 @@ class SvoLpThemeAssets extends Assets
|
||||
{
|
||||
$this->registerCSS(slug: "bootstrap", resource: "/css/netic/bootstrap.css");
|
||||
$this->registerCSS(slug: "style", resource: "/css/netic/style.css");
|
||||
$this->registerCSS(slug: "posts", resource: "/css/netic/posts.css");
|
||||
$this->registerCSS(slug: "responsive", resource: "/css/netic/responsive.css");
|
||||
$this->registerCSS(slug: "mCustomScrollbar", resource: "/css/netic/jquery.mCustomScrollbar.min.css");
|
||||
}
|
||||
|
@@ -2,13 +2,18 @@
|
||||
|
||||
namespace app\themes\svo\controllers;
|
||||
|
||||
use app\themes\svo\services\MainPageSliderService;
|
||||
use kernel\Controller;
|
||||
use kernel\helpers\Debug;
|
||||
use kernel\modules\post\models\Post;
|
||||
use kernel\modules\post\service\PostService;
|
||||
use kernel\modules\user\service\UserService;
|
||||
|
||||
class LpController extends Controller
|
||||
{
|
||||
|
||||
protected \kernel\modules\user\models\User $user;
|
||||
protected MainPageSliderService $mainPageSliderService;
|
||||
|
||||
protected function init(): void
|
||||
{
|
||||
@@ -19,6 +24,7 @@ class LpController extends Controller
|
||||
$this->cgView->addVarToLayout("resources", "/resources/themes/svo/assets");
|
||||
|
||||
$user = UserService::getAuthUser();
|
||||
$this->mainPageSliderService = new MainPageSliderService();
|
||||
if ($user){
|
||||
$this->cgView->addVarToLayout("currentUser", $user);
|
||||
$this->user = $user;
|
||||
@@ -27,7 +33,14 @@ class LpController extends Controller
|
||||
|
||||
public function actionIndex(): void
|
||||
{
|
||||
$this->cgView->render('index.php');
|
||||
$this->cgView->render('index.php', []);
|
||||
}
|
||||
|
||||
public function actionPost(int $postId): void
|
||||
{
|
||||
$post = Post::find($postId);
|
||||
|
||||
$this->cgView->render('post.php', ['post' => $post]);
|
||||
}
|
||||
|
||||
}
|
@@ -2,7 +2,13 @@
|
||||
|
||||
namespace app\themes\svo\controllers;
|
||||
|
||||
use app\themes\svo\services\MainPageSliderService;
|
||||
use app\themes\svo\services\SvoThemeService;
|
||||
use JetBrains\PhpStorm\NoReturn;
|
||||
use kernel\AdminController;
|
||||
use kernel\Flash;
|
||||
use kernel\helpers\Debug;
|
||||
use kernel\Request;
|
||||
|
||||
class SvoAdminController extends AdminController
|
||||
{
|
||||
@@ -11,6 +17,7 @@ class SvoAdminController extends AdminController
|
||||
{
|
||||
parent::init();
|
||||
$this->cgView->viewPath = APP_DIR . "/themes/svo/views/admin/";
|
||||
$this->cgView->addVarToLayout("svo_theme_resources", "/resources/themes/svo");
|
||||
}
|
||||
|
||||
public function actionThemeSettings(): void
|
||||
@@ -18,4 +25,24 @@ class SvoAdminController extends AdminController
|
||||
$this->cgView->render('theme_settings.php');
|
||||
}
|
||||
|
||||
#[NoReturn] public function actionAddSlide(): void
|
||||
{
|
||||
$request = new Request();
|
||||
$slideId = $request->post('slide');
|
||||
|
||||
SvoThemeService::addPostSlide($slideId);
|
||||
|
||||
Flash::setMessage('success', 'Слайд добавлен.');
|
||||
$this->redirect('/admin/svo-theme/settings?tab=slider', 302);
|
||||
}
|
||||
|
||||
#[NoReturn] public function actionDeleteSlide(int $post_id): void
|
||||
{
|
||||
$mainPageSlideService = new MainPageSliderService();
|
||||
$mainPageSlideService->removeSlide($post_id);
|
||||
|
||||
Flash::setMessage('success', 'Слайд удален.');
|
||||
$this->redirect('/admin/svo-theme/settings?tab=slider', 302);
|
||||
}
|
||||
|
||||
}
|
@@ -6,11 +6,14 @@ use kernel\CgRouteCollector;
|
||||
App::$collector->filter("auth", [\app\themes\svo\middlewares\LkAuthMiddleware::class, "handler"]);
|
||||
|
||||
App::$collector->get('/', [\app\themes\svo\controllers\LpController::class, 'actionIndex']);
|
||||
App::$collector->get('/post/{postId}', [\app\themes\svo\controllers\LpController::class, 'actionPost']);
|
||||
|
||||
App::$collector->group(["prefix" => "admin"], function (CgRouteCollector $router) {
|
||||
App::$collector->group(["before" => "auth"], function (CGRouteCollector $router) {
|
||||
App::$collector->group(["prefix" => "svo-theme"], function (CGRouteCollector $router) {
|
||||
App::$collector->get('/settings', [\app\themes\svo\controllers\SvoAdminController::class, 'actionThemeSettings']);
|
||||
App::$collector->get('/delete_slide/{post_id}', [\app\themes\svo\controllers\SvoAdminController::class, 'actionDeleteSlide']);
|
||||
App::$collector->post('/add_slide', [\app\themes\svo\controllers\SvoAdminController::class, 'actionAddSlide']);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
90
app/themes/svo/services/MainPageSliderService.php
Normal file
90
app/themes/svo/services/MainPageSliderService.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace app\themes\svo\services;
|
||||
|
||||
use kernel\App;
|
||||
use kernel\helpers\Debug;
|
||||
use kernel\models\Option;
|
||||
use kernel\modules\option\service\OptionService;
|
||||
|
||||
class MainPageSliderService
|
||||
{
|
||||
protected OptionService $optionService;
|
||||
protected string $sliderKey = 'main_news_slider';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->optionService = new OptionService();
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить список слайдов
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSlides(): array
|
||||
{
|
||||
$option = Option::where('key', $this->sliderKey)->first();
|
||||
|
||||
if (!$option || empty($option->value)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$data = json_decode($option->value, true);
|
||||
|
||||
return $data['ids'] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавить слайд
|
||||
*
|
||||
* @param int $slideId
|
||||
* @return bool
|
||||
*/
|
||||
public function addSlide(int $slideId): bool
|
||||
{
|
||||
return App::$db->capsule::connection()->transaction(function () use ($slideId) {
|
||||
$option = Option::firstOrNew(['key' => $this->sliderKey]);
|
||||
|
||||
$currentValue = $option->value ? json_decode($option->value, true) : ['ids' => []];
|
||||
|
||||
if (in_array($slideId, $currentValue['ids'])) {
|
||||
return true; // слайд уже есть, ничего не делаем
|
||||
}
|
||||
|
||||
$currentValue['ids'][] = $slideId;
|
||||
$option->value = json_encode($currentValue);
|
||||
|
||||
return $option->save();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Удалить слайд
|
||||
*
|
||||
* @param int $slideId
|
||||
* @return bool
|
||||
*/
|
||||
public function removeSlide(int $slideId): bool
|
||||
{
|
||||
return App::$db->capsule::connection()->transaction(function () use ($slideId) {
|
||||
/** @var Option $option */
|
||||
$option = Option::where('key', $this->sliderKey)->first();
|
||||
|
||||
if (!$option || empty($option->value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$currentValue = json_decode($option->value, true);
|
||||
|
||||
if (!in_array($slideId, $currentValue['ids'] ?? [])) {
|
||||
return false; // слайда нет в списке
|
||||
}
|
||||
|
||||
$currentValue['ids'] = array_diff($currentValue['ids'], [$slideId]);
|
||||
$option->value = json_encode($currentValue);
|
||||
|
||||
return $option->save();
|
||||
});
|
||||
}
|
||||
}
|
34
app/themes/svo/services/SvoThemeService.php
Normal file
34
app/themes/svo/services/SvoThemeService.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace app\themes\svo\services;
|
||||
|
||||
use kernel\helpers\Debug;
|
||||
use kernel\models\Option;
|
||||
use kernel\modules\option\service\OptionService;
|
||||
use kernel\modules\post\models\Post;
|
||||
|
||||
class SvoThemeService
|
||||
{
|
||||
|
||||
public static function getSliderPosts()
|
||||
{
|
||||
$slides = json_decode(OptionService::getItem('main_news_slider'), true);
|
||||
|
||||
return Post::whereIn('id', $slides['ids'])->get();
|
||||
}
|
||||
|
||||
public static function addPostSlide(int $postId)
|
||||
{
|
||||
$slides = json_decode(OptionService::getItem('main_news_slider'), true);
|
||||
|
||||
if (!in_array($postId, $slides['ids'])) {
|
||||
$slides['ids'][] = $postId;
|
||||
OptionService::createOrUpdate('main_news_slider', json_encode($slides));
|
||||
}
|
||||
|
||||
return $slides;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
3
app/themes/svo/views/admin/_slider_post_list.php
Normal file
3
app/themes/svo/views/admin/_slider_post_list.php
Normal file
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
?>
|
||||
Посты
|
@@ -1,24 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* @var string $resources
|
||||
* @var string $svo_theme_resources
|
||||
* @var \kernel\CgView $view
|
||||
*/
|
||||
new \app\themes\svo\assets\AdminSliderAssets($resources);
|
||||
\kernel\Theme::$assetsCollector->registerAsset(new \app\themes\svo\assets\AdminSliderAssets($svo_theme_resources));
|
||||
?>
|
||||
|
||||
<ul class="nav nav-tabs" id="myTab" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link active" id="home-tab" data-toggle="tab" data-target="#home" type="button" role="tab" aria-controls="home" aria-selected="true">
|
||||
<button class="nav-link active" id="home-tab" data-toggle="tab" data-target="#home" type="button" role="tab"
|
||||
aria-controls="home" aria-selected="true">
|
||||
Основные
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="slider-tab" data-toggle="tab" data-target="#slider" type="button" role="tab" aria-controls="slider" aria-selected="false">
|
||||
<button class="nav-link" id="slider-tab" data-toggle="tab" data-target="#slider" type="button" role="tab"
|
||||
aria-controls="slider" aria-selected="false">
|
||||
Слайдер
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="contact-tab" data-toggle="tab" data-target="#contact" type="button" role="tab" aria-controls="contact" aria-selected="false">
|
||||
<button class="nav-link" id="contact-tab" data-toggle="tab" data-target="#contact" type="button" role="tab"
|
||||
aria-controls="contact" aria-selected="false">
|
||||
Contact
|
||||
</button>
|
||||
</li>
|
||||
@@ -29,16 +33,24 @@ new \app\themes\svo\assets\AdminSliderAssets($resources);
|
||||
</div>
|
||||
<div class="tab-pane fade" id="slider" role="tabpanel" aria-labelledby="slider-tab">
|
||||
<div class="form-group">
|
||||
<label>Заголовок</label>
|
||||
<label>Новости в сладере</label>
|
||||
<br>
|
||||
<select id="postSelect" style="width: 300px">
|
||||
<option value="1">Option 1</option>
|
||||
<option value="2">Option 2</option>
|
||||
<option value="3">Option 3</option>
|
||||
<option value="4">Option 4</option>
|
||||
</select>
|
||||
<form id="add_slide_form" action="/admin/svo-theme/add_slide" method="post">
|
||||
<select name="slide" class="form-control" id="postSelect" style="width: 300px">
|
||||
<?php foreach (\kernel\modules\post\service\PostService::getListArr() as $key => $item): ?>
|
||||
<option value="<?= $key ?>"><?= $item ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<?= \kernel\helpers\Html::link('Добавить', '#', [
|
||||
'id' => 'saveSliderPost',
|
||||
'class' => 'btn btn-success',
|
||||
'onclick' => 'document.getElementById("add_slide_form").submit(); return false;'
|
||||
]) ?>
|
||||
<br>
|
||||
<?php \app\themes\svo\widgets\AdminSliderPostsList::create()->run(); ?>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="contact" role="tabpanel" aria-labelledby="contact-tab">
|
||||
Contact
|
||||
@@ -46,8 +58,15 @@ new \app\themes\svo\assets\AdminSliderAssets($resources);
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Инициализация Select2
|
||||
$('#postSelect').select2();
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Получаем параметр из URL
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const activeTab = urlParams.get('tab');
|
||||
|
||||
// Если параметр есть, активируем соответствующую вкладку
|
||||
if (activeTab) {
|
||||
const tabTrigger = new bootstrap.Tab(document.querySelector(`[data-target="#${activeTab}"]`));
|
||||
tabTrigger.show();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
223
app/themes/svo/views/lp/post.php
Normal file
223
app/themes/svo/views/lp/post.php
Normal file
@@ -0,0 +1,223 @@
|
||||
<?php
|
||||
/**
|
||||
* @var \kernel\modules\post\models\Post $post
|
||||
*/
|
||||
?>
|
||||
|
||||
<main class="container my-5">
|
||||
<!-- Хлебные крошки -->
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="#">Главная</a></li>
|
||||
<li class="breadcrumb-item"><a href="#">Новости</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page"><?= $post->title ?></li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<!-- Заголовок новости -->
|
||||
<article>
|
||||
<header class="mb-4">
|
||||
<h1 class="font-weight-bold"><?= $post->title ?></h1>
|
||||
<div class="d-flex align-items-center text-muted mt-3">
|
||||
<span class="mr-3"><i class="fa fa-calendar mr-2"></i><?= $post->created_at ?></span>
|
||||
<span class="mr-3"><i class="fa fa-eye mr-2"></i>12 543 просмотра</span>
|
||||
<span><i class="fa fa-comments-o mr-2"></i>24 комментария</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Основное изображение -->
|
||||
<figure class="mb-4">
|
||||
<img src="https://via.placeholder.com/1200x600" alt="Иллюстрация к новости" class="img-fluid rounded">
|
||||
<figcaption class="text-center mt-2 text-muted">Иллюстрация: создание 3D-модели с помощью ИИ</figcaption>
|
||||
</figure>
|
||||
|
||||
<!-- Текст новости -->
|
||||
<div class="news-content mb-5">
|
||||
<p class="lead">Компания OpenAI представила новую версию своего алгоритма, способного генерировать трехмерные объекты на основе текстовых описаний.</p>
|
||||
|
||||
<p>Новая технология, получившая название 3D-GPT, позволяет создавать высокодетализированные модели всего за несколько секунд. Пользователю достаточно ввести описание объекта, например, "красный спортивный автомобиль с черными полосами", и система сгенерирует соответствующую 3D-модель.</p>
|
||||
|
||||
<h2 class="mt-4 mb-3">Как это работает</h2>
|
||||
|
||||
<p>Алгоритм основан на комбинации нескольких нейросетевых архитектур:</p>
|
||||
|
||||
<ul>
|
||||
<li>Текстовая модель анализирует описание и выделяет ключевые характеристики</li>
|
||||
<li>Генеративная сеть создает базовую геометрию объекта</li>
|
||||
<li>Дополнительные модули добавляют текстуры, материалы и освещение</li>
|
||||
</ul>
|
||||
|
||||
<p>По словам разработчиков, система особенно хорошо справляется с органическими формами и архитектурными объектами.</p>
|
||||
|
||||
<div class="alert alert-info mt-4">
|
||||
<h3 class="alert-heading">Экспертное мнение</h3>
|
||||
<p>"Эта технология может революционизировать индустрию 3D-моделирования, значительно сократив время и стоимость создания цифровых активов", - отмечает Джон Смит, профессор компьютерной графики в MIT.</p>
|
||||
</div>
|
||||
|
||||
<h2 class="mt-4 mb-3">Практическое применение</h2>
|
||||
|
||||
<p>Технология уже тестируется в нескольких областях:</p>
|
||||
|
||||
<div class="row mt-3">
|
||||
<div class="col-md-4 mb-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Игровая индустрия</h5>
|
||||
<p class="card-text">Быстрое прототипирование персонажей и объектов для видеоигр.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Архитектура</h5>
|
||||
<p class="card-text">Создание 3D-моделей зданий по словесным описаниям заказчиков.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Образование</h5>
|
||||
<p class="card-text">Визуализация исторических объектов и научных концепций.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="mt-4">Ожидается, что коммерческая версия продукта будет выпущена в начале следующего года. Бета-тестирование начнется уже в сентябре для ограниченного круга разработчиков.</p>
|
||||
</div>
|
||||
|
||||
<!-- Теги и соцсети -->
|
||||
<div class="d-flex flex-wrap justify-content-between align-items-center border-top border-bottom py-3 mb-5">
|
||||
<div class="tags mb-2 mb-md-0">
|
||||
<span class="badge badge-secondary mr-2">#искусственный_интеллект</span>
|
||||
<span class="badge badge-secondary mr-2">#3d_моделирование</span>
|
||||
<span class="badge badge-secondary mr-2">#технологии</span>
|
||||
<span class="badge badge-secondary">#openai</span>
|
||||
</div>
|
||||
<div class="social-share">
|
||||
<button class="btn btn-outline-primary btn-sm mr-2"><i class="fab fa-facebook-f mr-1"></i> Поделиться</button>
|
||||
<button class="btn btn-outline-info btn-sm mr-2"><i class="fab fa-twitter mr-1"></i> Твитнуть</button>
|
||||
<button class="btn btn-outline-danger btn-sm"><i class="fab fa-telegram-plane mr-1"></i> Отправить</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Автор и источник -->
|
||||
<footer class="bg-light p-3 rounded mb-5">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<h5>Об авторе</h5>
|
||||
<div class="d-flex align-items-center">
|
||||
<img src="https://via.placeholder.com/50" alt="Автор" class="rounded-circle mr-3">
|
||||
<div>
|
||||
<h6 class="mb-0">Александра Петрова</h6>
|
||||
<p class="text-muted mb-0">Технологический обозреватель с 10-летним опытом</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 mt-3 mt-md-0">
|
||||
<h5>Источник</h5>
|
||||
<p>По материалам пресс-релиза OpenAI и эксклюзивного интервью с разработчиками</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- Похожие новости -->
|
||||
<section class="mb-5">
|
||||
<h3 class="mb-4">Похожие новости</h3>
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-4">
|
||||
<div class="card h-100">
|
||||
<img src="https://via.placeholder.com/400x200" class="card-img-top" alt="...">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Нейросети научились анимировать 2D-рисунки</h5>
|
||||
<p class="card-text text-muted">12 июля 2023</p>
|
||||
<a href="#" class="btn btn-outline-primary btn-sm">Читать</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 mb-4">
|
||||
<div class="card h-100">
|
||||
<img src="https://via.placeholder.com/400x200" class="card-img-top" alt="...">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">ИИ в дизайне: как алгоритмы меняют творческие профессии</h5>
|
||||
<p class="card-text text-muted">8 июля 2023</p>
|
||||
<a href="#" class="btn btn-outline-primary btn-sm">Читать</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 mb-4">
|
||||
<div class="card h-100">
|
||||
<img src="https://via.placeholder.com/400x200" class="card-img-top" alt="...">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Обзор новых инструментов для 3D-художников в 2023 году</h5>
|
||||
<p class="card-text text-muted">3 июля 2023</p>
|
||||
<a href="#" class="btn btn-outline-primary btn-sm">Читать</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Комментарии -->
|
||||
<section class="mb-5">
|
||||
<h3 class="mb-4">Комментарии (24)</h3>
|
||||
|
||||
<div class="mb-4">
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<textarea class="form-control" rows="3" placeholder="Оставьте ваш комментарий..."></textarea>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Отправить</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="comment-list">
|
||||
<div class="comment mb-4">
|
||||
<div class="d-flex">
|
||||
<img src="https://via.placeholder.com/40" alt="Аватар" class="rounded-circle mr-3">
|
||||
<div>
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<h6 class="mb-0">Иван Иванов</h6>
|
||||
<small class="text-muted">2 часа назад</small>
|
||||
</div>
|
||||
<p>Очень интересная технология! Интересно, насколько она будет доступна для индивидуальных разработчиков по цене.</p>
|
||||
<button class="btn btn-link btn-sm p-0 text-muted">Ответить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="comment mb-4 ml-5">
|
||||
<div class="d-flex">
|
||||
<img src="https://via.placeholder.com/40" alt="Аватар" class="rounded-circle mr-3">
|
||||
<div>
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<h6 class="mb-0">Мария Смирнова</h6>
|
||||
<small class="text-muted">1 час назад</small>
|
||||
</div>
|
||||
<p>@Иван Иванов, по предварительной информации, будет несколько тарифных планов, включая бесплатный с ограничениями.</p>
|
||||
<button class="btn btn-link btn-sm p-0 text-muted">Ответить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="comment mb-4">
|
||||
<div class="d-flex">
|
||||
<img src="https://via.placeholder.com/40" alt="Аватар" class="rounded-circle mr-3">
|
||||
<div>
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<h6 class="mb-0">Алексей Технарев</h6>
|
||||
<small class="text-muted">30 минут назад</small>
|
||||
</div>
|
||||
<p>Жду не дождусь, когда можно будет попробовать! Уже есть несколько идей, как это можно применить в нашем проекте.</p>
|
||||
<button class="btn btn-link btn-sm p-0 text-muted">Ответить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-outline-secondary">Показать еще комментарии</button>
|
||||
</div>
|
||||
</section>
|
||||
</article>
|
||||
</main>
|
25
app/themes/svo/views/widget/admin_slider_posts_list.php
Normal file
25
app/themes/svo/views/widget/admin_slider_posts_list.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* @var \Illuminate\Database\Eloquent\Collection $posts
|
||||
*/
|
||||
use kernel\CollectionTableRenderer;
|
||||
|
||||
$table = new CollectionTableRenderer($posts);
|
||||
|
||||
$table->setColumns([
|
||||
'id' => 'ID',
|
||||
'title' => 'Название',
|
||||
]);
|
||||
|
||||
$table->setTableAttributes([
|
||||
'style' => 'margin-top:20px;'
|
||||
]);
|
||||
|
||||
$table->addCustomColumn('action', 'Действия', function ($post) {
|
||||
$btn = '<a href="/admin/svo-theme/delete_slide/' . $post->id . '" class="btn btn-sm btn-danger">Удалить</a> ';
|
||||
|
||||
return $btn;
|
||||
});
|
||||
|
||||
|
||||
$table->render();
|
@@ -1,50 +1,31 @@
|
||||
<?php
|
||||
/**
|
||||
* @var string $resources
|
||||
* @var \Illuminate\Database\Eloquent\Collection $posts
|
||||
*/
|
||||
|
||||
$flag = 0;
|
||||
?>
|
||||
<div class="banner_section layout_padding">
|
||||
<div id="my_slider" class="carousel slide" data-ride="carousel">
|
||||
<div class="carousel-inner">
|
||||
<div class="carousel-item active">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h1 class="banner_taital">Hosting <br>And Domain</h1>
|
||||
<div class="read_bt"><a href="#">Read More</a></div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="banner_img"><img src="<?= $resources ?>/images/slide_img.jpg"></div>
|
||||
<?php foreach ($posts as $key => $post): ?>
|
||||
<?php /** @var \kernel\modules\post\models\Post $post */ ?>
|
||||
<div class="carousel-item <?= $flag === 0 ? 'active' : '' ?>">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h1 class="banner_taital main_slider_title"><?= $post->title ?></h1>
|
||||
<div class="read_bt"><a href="/post/<?= $post->id ?>">Читать</a></div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="banner_img"><img src="<?= $resources ?>/images/slide_img.jpg"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h1 class="banner_taital">Hosting <br>And Domain</h1>
|
||||
<div class="read_bt"><a href="#">Read More</a></div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="banner_img"><img src="<?= $resources ?>/images/slide_img.jpg"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h1 class="banner_taital">Hosting <br>And Domain</h1>
|
||||
<div class="read_bt"><a href="#">Read More</a></div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="banner_img"><img src="<?= $resources ?>/images/slide_img.jpg"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php $flag++; ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<a class="carousel-control-prev" href="#my_slider" role="button" data-slide="prev">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
|
19
app/themes/svo/widgets/AdminSliderPostsList.php
Normal file
19
app/themes/svo/widgets/AdminSliderPostsList.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace app\themes\svo\widgets;
|
||||
|
||||
use kernel\Widget;
|
||||
|
||||
class AdminSliderPostsList extends Widget
|
||||
{
|
||||
protected function init(): void
|
||||
{
|
||||
$this->cgView->viewPath = APP_DIR . "/themes/svo/views/widget/";
|
||||
}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$this->cgView->render("admin_slider_posts_list.php", ['posts' => \app\themes\svo\services\SvoThemeService::getSliderPosts()]);
|
||||
}
|
||||
|
||||
}
|
@@ -2,19 +2,29 @@
|
||||
|
||||
namespace app\themes\svo\widgets;
|
||||
|
||||
use app\themes\svo\services\MainPageSliderService;
|
||||
use kernel\modules\post\models\Post;
|
||||
use kernel\Widget;
|
||||
|
||||
class MainSliderWidget extends Widget
|
||||
{
|
||||
protected MainPageSliderService $mainPageSliderService;
|
||||
|
||||
protected function init(): void
|
||||
{
|
||||
$this->cgView->viewPath = APP_DIR . "/themes/svo/views/widget/";
|
||||
$this->mainPageSliderService = new MainPageSliderService();
|
||||
}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$this->cgView->render("main_slider.php", ['resources' => $this->data['resources']]);
|
||||
$slides = $this->mainPageSliderService->getSlides();
|
||||
$posts = Post::whereIn('id', $slides)->get();
|
||||
|
||||
$this->cgView->render("main_slider.php", [
|
||||
'resources' => $this->data['resources'],
|
||||
'posts' => $posts,
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user