feat(product): add option to disable store feature

This commit is contained in:
2025-09-27 00:08:24 +03:00
parent f066069a1b
commit d7dd055e24
8 changed files with 97 additions and 34 deletions

View File

@@ -31,6 +31,7 @@ if (is_readable($sysLibPath . '/oc_telegram_shop.phar')) {
* @property ModelCustomerCustomerGroup $model_customer_customer_group
* @property ModelLocalisationOrderStatus $model_localisation_order_status
* @property DB $db
* @property Log $log
*/
class ControllerExtensionModuleTgshop extends Controller
{
@@ -342,11 +343,11 @@ TEXT,
'module_tgshop_theme_light' => 'light',
'module_tgshop_theme_dark' => 'dark',
'module_tgshop_mainpage_products' => 'most_viewed',
'module_tgshop_featured_products' => [],
'module_tgshop_order_customer_group_id' => 1,
'module_tgshop_order_default_status_id' => 1,
'module_tgshop_mini_app_url' => rtrim(HTTPS_CATALOG, '/') . '/image/catalog/tgshopspa/#/',
'module_tgshop_mainpage_categories' => 'latest10'
'module_tgshop_mainpage_categories' => 'latest10',
'module_tgshop_enable_store' => 1,
];
}
@@ -445,6 +446,17 @@ HTML,
],
'shop' => [
'module_tgshop_enable_store' => [
'type' => 'select',
'options' => [
0 => 'Выключено',
1 => 'Включено',
],
'help' => <<<HTML
Если опция <strong>включена</strong> пользователи смогут оформлять заказы прямо в Telegram-магазине. <br>
Если <strong>выключена</strong> оформление заказов будет недоступно. Вместо кнопки «Добавить в корзину» пользователи увидят кнопку «Перейти к товару», которая откроет страницу товара на вашем сайте. В этом режиме Telecart работает как каталог.
HTML,
],
'module_tgshop_mainpage_products' => [
'type' => 'select',
'options' => [
@@ -457,7 +469,7 @@ HTML,
'module_tgshop_featured_products' => [
'type' => 'products',
'help' => 'На главной странице будут отображаться избранные товары, если вы выберете этот вариант в настройке “Товары на главной”.',
'help' => 'На главной странице будут отображаться избранные товары, если вы выберете этот вариант в настройке “Товары на главной”. Если товары не выбраны, то будут показаны популярные товары.',
],
'module_tgshop_mainpage_categories' => [
@@ -522,7 +534,7 @@ HTML,
$diff = [];
foreach ($defaults as $key => $value) {
if (! isset($settings[$key])) {
if (! array_key_exists($key, $settings)) {
$diff[$key] = $defaults[$key];
}
}
@@ -530,6 +542,15 @@ HTML,
if ($diff) {
$settings = array_merge($settings, $diff);
$this->model_setting_setting->editSetting('module_tgshop', $settings);
$this->log->write('[TELECART] Выполнено обновление настроек по умолчанию для модуля.');
$this->session->data['success'] = 'Выполнено обновление настроек по умолчанию для модуля.';
}
}
public function install(): void
{
$this->log->write('[TELECART] Запуск установки модуля.');
$this->updateConfigFromDefaults();
$this->log->write('[TELECART] Установка модуля завершена.');
}
}

View File

@@ -29,6 +29,7 @@ $_['lbl_module_tgshop_order_default_status_id'] = 'Статус заказов';
$_['lbl_module_tgshop_mini_app_url'] = 'Ссылка на Telegram Mini App';
$_['lbl_module_tgshop_mainpage_categories'] = 'Категории на главной';
$_['lbl_module_tgshop_featured_categories'] = 'Избранные категории';
$_['lbl_module_tgshop_enable_store'] = 'Разрешить покупки';
// Entry
$_['entry_status'] = 'Статус';

View File

@@ -58,9 +58,10 @@ class ControllerExtensionTgshopHandle extends Controller
'theme_light' => $this->config->get('module_tgshop_theme_light'),
'theme_dark' => $this->config->get('module_tgshop_theme_dark'),
'mainpage_products' => $this->config->get('module_tgshop_mainpage_products'),
'featured_products' => $this->config->get('module_tgshop_featured_products'),
'featured_products' => (array) $this->config->get('module_tgshop_featured_products'),
'mainpage_categories' => $this->config->get('module_tgshop_mainpage_categories'),
'featured_categories' => $this->config->get('module_tgshop_featured_categories'),
'featured_categories' => (array) $this->config->get('module_tgshop_featured_categories'),
'store_enabled' => filter_var($this->config->get('module_tgshop_enable_store'), FILTER_VALIDATE_BOOLEAN),
'base_url' => HTTPS_SERVER,
'ya_metrika_enabled' => ! empty(trim($this->config->get('module_tgshop_yandex_metrika'))),
'telegram' => [

View File

@@ -51,6 +51,7 @@ class SettingsHandler
'theme_dark' => $this->settings->get('theme_dark'),
'ya_metrika_enabled' => $this->settings->get('ya_metrika_enabled'),
'app_enabled' => $this->settings->get('app_enabled'),
'store_enabled' => $this->settings->get('store_enabled'),
]);
}

View File

@@ -245,6 +245,11 @@ class ProductsService
$data['reward'] = $product_info['reward'];
$data['points'] = (int) $product_info['points'];
$data['description'] = html_entity_decode($product_info['description'], ENT_QUOTES, 'UTF-8');
$data['share'] = html_entity_decode(
$this->oc->url->link('product/product', 'product_id=' . $productId),
ENT_QUOTES | ENT_HTML5,
'UTF-8'
);
if ($product_info['quantity'] <= 0) {
$data['stock'] = $product_info['stock_status'];

View File

@@ -6,7 +6,7 @@
<component :is="Component" :key="route.fullPath" />
</Transition>
</RouterView>
<CartButton/>
<CartButton v-if="settings.store_enabled"/>
</div>
</template>
@@ -16,6 +16,7 @@ import {useWebAppViewport, useBackButton} from 'vue-tg';
import {useMiniApp, FullscreenViewport} from 'vue-tg';
import {useRoute, useRouter} from "vue-router";
import CartButton from "@/components/CartButton.vue";
import {useSettingsStore} from "@/stores/SettingsStore.js";
const tg = useMiniApp();
const platform = ref();
@@ -26,6 +27,7 @@ disableVerticalSwipes();
const router = useRouter();
const route = useRoute();
const settings = useSettingsStore();
watch(
() => route.name,

View File

@@ -4,6 +4,7 @@ import {fetchSettings} from "@/utils/ftch.js";
export const useSettingsStore = defineStore('settings', {
state: () => ({
app_enabled: true,
store_enabled: true,
app_name: 'OpenCart Telegram магазин',
app_icon: '',
app_icon192: '',
@@ -38,6 +39,7 @@ export const useSettingsStore = defineStore('settings', {
this.theme.dark = settings.theme_dark;
this.ya_metrika_enabled = settings.ya_metrika_enabled;
this.app_enabled = settings.app_enabled;
this.store_enabled = settings.store_enabled;
}
}
});

View File

@@ -91,6 +91,7 @@
<div v-if="product.product_id"
class="fixed px-4 pb-10 pt-4 bottom-0 left-0 w-full bg-base-200 z-50 flex flex-col gap-2 border-t-1 border-t-base-300">
<template v-if="settings.store_enabled">
<div class="text-error">
{{ error }}
</div>
@@ -119,6 +120,25 @@
size="lg"
/>
</div>
</template>
<template v-else>
<button
class="btn btn-primary btn-lg w-full"
:disabled="! product.share"
@click="openProductInMarketplace"
>
<template v-if="product.share">
Открыть товар
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25" />
</svg>
</template>
<template>Товар недоступен</template>
</button>
</template>
</div>
<ProductNotFound v-else/>
@@ -144,6 +164,7 @@ import {apiFetch} from "@/utils/ftch.js";
import FullScreenImageViewer from "@/components/FullScreenImageViewer.vue";
import LoadingFullScreen from "@/components/LoadingFullScreen.vue";
import ProductNotFound from "@/components/ProductNotFound.vue";
import {useSettingsStore} from "@/stores/SettingsStore.js";
const route = useRoute();
const productId = computed(() => route.params.id);
@@ -157,6 +178,7 @@ const btnText = computed(() => isInCart.value ? 'В корзине' : 'Купи
const isFullScreen = ref(false);
const initialFullScreenIndex = ref(0);
const isLoading = ref(false);
const settings = useSettingsStore();
const canAddToCart = computed(() => {
if (!product.value || product.value.options === undefined || product.value.options?.length === 0) {
@@ -204,6 +226,14 @@ async function actionBtnClick() {
}
}
function openProductInMarketplace() {
if (! product.value.share) {
return;
}
window.Telegram.WebApp.openLink(product.value.share, { try_instant_view: false });
}
function setQuantity(newQuantity) {
quantity.value = newQuantity;
window.Telegram.WebApp.HapticFeedback.selectionChanged();