refactor: move spa to frontend folder

This commit is contained in:
2025-10-27 12:32:38 +03:00
committed by Nikita Kiselev
parent 5681ac592a
commit 0cccc7e3d7
40 changed files with 1566 additions and 35 deletions

View File

@@ -95,6 +95,7 @@ class ControllerExtensionModuleTgshop extends Controller
if ($hasConfig) {
$this->updateConfigFromDefaults();
$this->cleanUpOldAssets();
$this->injectVueJs();
$this->config();
} else {
$this->init();
@@ -107,7 +108,12 @@ class ControllerExtensionModuleTgshop extends Controller
$this->document->setTitle($this->language->get('heading_title'));
if (($this->request->server['REQUEST_METHOD'] === 'POST') && $this->validate()) {
$this->model_setting_setting->editSetting('module_tgshop', $this->request->post);
$postData = $this->request->post;
$postData['module_tgshop_mainpage_banners'] = [];
if (! empty($_POST['module_tgshop_mainpage_banners'])) {
$postData['module_tgshop_mainpage_banners'] = $_POST['module_tgshop_mainpage_banners'];
}
$this->model_setting_setting->editSetting('module_tgshop', $postData);
$this->session->data['success'] = $this->language->get('text_success');
@@ -130,6 +136,13 @@ class ControllerExtensionModuleTgshop extends Controller
$data['settings'] = $this->getSettingsConfig();
$data['banners'] = [];
$banners = $this->config->get('module_tgshop_mainpage_banners');
if ($banners) {
$banners = html_entity_decode($banners);
$data['banners'] = $banners;
}
foreach ($data['settings'] as $configs) {
foreach ($configs as $key => $config) {
if ($config['type'] === 'image') {
@@ -355,6 +368,7 @@ TEXT,
'module_tgshop_text_no_more_products' => 'Это всё по текущему запросу. Попробуйте уточнить фильтры или поиск.',
'module_tgshop_text_empty_cart' => 'Ваша корзина пуста',
'module_tgshop_text_order_created_success' => 'Ваш заказ успешно оформлен и будет обработан в ближайшее время.',
'module_tgshop_mainpage_banners' => '[]',
];
}
@@ -535,14 +549,6 @@ HTML,
],
'help' => <<<HTML
Позволяет покупателям использовать <a href="{$ocVouchersLink}" target="_blank">подарочные сертификаты OpenCart</a> при оформлении заказа.
HTML,
],
'module_tgshop_home_banner_id' => [
'type' => 'select',
'options' => $this->getBannersList(),
'help' => <<<HTML
<a href="{$ocBannersLink}" target="_blank">Стандартный OpenCart баннер</a> отображаемый на главной странице магазина. Рекомендуемое соотношение сторон для изображений - 2.5:1 (например 500×200).
HTML,
],
],
@@ -703,4 +709,17 @@ HTML,
return [null => 'Не показывать'] + $map;
}
private function injectVueJs(): void
{
$appDir = rtrim(DIR_APPLICATION, '/');
if (file_exists("$appDir/view/javascript/telecart/telecart.js")) {
$this->document->addScript('view/javascript/telecart/telecart.js');
$this->document->addStyle('view/javascript/telecart/telecart.css');
} elseif (file_exists("$appDir/view/integration.js")) {
$this->document->addScript('view/integration.js');
} else {
throw new RuntimeException('Unable to load Vuejs frontend.');
}
}
}

View File

@@ -0,0 +1,18 @@
(function() {
function injectVueScript() {
const script = document.createElement('script');
script.type = 'module';
//if (window.vueIntegration && window.vueIntegration.developmentEnv) {
script.src = 'http://localhost:3000/src/main.js';
//} else {
// script.src = '/path/to/built/main.js';
//}
document.body.appendChild(script);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', injectVueScript);
} else { // Документ уже загружен
injectVueScript();
}
})();

View File

@@ -48,6 +48,11 @@
</a>
</li>
{% endfor %}
<li>
<a href="#banners" data-toggle="tab">
Баннеры
</a>
</li>
</ul>
<div class="tab-content">
@@ -442,6 +447,16 @@
{% endfor %}
</div>
{% endfor %}
<div id="banners" class="tab-pane">
<script>
window.TeleCart = {
user_token: '{{ user_token }}',
banners: '{{ banners }}',
};
</script>
<div id="app">App Loading...</div>
</div>
</div>
</form>
</div>

View File

@@ -94,7 +94,7 @@ class ControllerExtensionTgshopHandle extends Controller
$this->config->get('module_tgshop_feature_vouchers'),
FILTER_VALIDATE_BOOLEAN
),
'home_banner_id' => $this->config->get('module_tgshop_home_banner_id'),
'mainpage_banners' => $this->safeJsonDecode($this->config->get('module_tgshop_mainpage_banners'), []),
'texts' => [
'no_more_products' => $this->config->get('module_tgshop_text_no_more_products'),
'empty_cart' => $this->config->get('module_tgshop_text_empty_cart'),
@@ -141,6 +141,15 @@ class ControllerExtensionTgshopHandle extends Controller
return '';
}
private function safeJsonDecode(string $input, $default = null)
{
try {
return json_decode($input, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
return $default;
}
}
public function ya_metrika(): void
{
$raw = html_entity_decode($this->config->get('module_tgshop_yandex_metrika'), ENT_QUOTES | ENT_HTML5);

View File

@@ -79,4 +79,44 @@ class ImageTool implements ImageToolInterface
return [$img->getWidth(), $img->getHeight()];
}
public function cover(string $path, int $width, int $height, string $position = 'center'): ?string
{
$format = 'webp';
if (! $width && ! $height) {
throw new InvalidArgumentException('Width or height must be set');
}
if (! $path || ! is_file($this->imageDir . $path)) {
return null;
}
$realPath = realpath($this->imageDir . $path);
if (strpos($realPath, realpath($this->imageDir)) !== 0) {
return null; // безопасность
}
$extless = utf8_substr($path, 0, utf8_strrpos($path, '.'));
$imageNew = 'cache/' . $extless . '-' . $width . 'x' . $height . '.' . $format;
$fullNewPath = $this->imageDir . $imageNew;
$fullOldPath = $this->imageDir . $path;
if (! is_file($fullNewPath) || filemtime($fullOldPath) > filemtime($fullNewPath)) {
$dirPath = dirname($fullNewPath);
if (! is_dir($dirPath)) {
mkdir($dirPath, 0777, true);
}
$image = $this->manager->make($fullOldPath)
->fit($width, $height, function ($constraint) {
$constraint->upsize();
}, $position);
$image->encode($format, 75)->save($fullNewPath, 75, $format);
}
return rtrim($this->siteUrl, '/') . '/image/' . str_replace($this->imageDir, '', $fullNewPath);
}
}

View File

@@ -14,4 +14,6 @@ interface ImageToolInterface
?string $default = null,
string $format = 'webp'
): ?string;
public function cover(string $path, int $width, int $height, string $position = 'center'): ?string;
}

View File

View File

@@ -25,17 +25,16 @@ class BannerHandler
public function show(): JsonResponse
{
$data = [];
$bannerId = $this->settings->get('home_banner_id');
$slides = $this->settings->get('mainpage_banners', []);
if ($bannerId) {
$banner = $this->registry->model_design_banner->getBanner($bannerId);
foreach ($banner as $index => $result) {
if (is_file(DIR_IMAGE . $result['image'])) {
if ($slides) {
foreach ($slides as $index => $slide) {
if (is_file(DIR_IMAGE . $slide['image'])) {
$data[] = [
'id' => $index,
'title' => $result['title'],
'link' => rtrim($this->settings->get('base_url'), '/') . '/' . $result['link'],
'image' => $this->imageTool->resize($result['image'], null, 200),
'title' => $slide['title'],
'link' => $slide['link'],
'image' => $this->imageTool->cover($slide['image'], 1110, 600),
];
}
}