2,351

(18 ответов, оставленных в Вопросы по работе с системой)

Тут есть 2 пути. 1 через мильтисайтовость, другой через партнёрский модуль.

1. Мультисайтовость.
При покупке полной лицензии вы получаете дополнительно лицензию на 2 домена, под управлением одной системы. Но в данном случае, Всё будет разное в системе, кроме пользователей. Пользователи будут одинаковые для всех. Переключатся можно через админку.
Это будет как будто 2 разных сайта.

Соответственно, если у Вас сайтов больше 2-х, то Вам надо будет докупить лицензии на доп домены, до скольки Вам необходимо. Дополнительный сайт на Вашей лицензии будет стоить  3 750 на данный момент.
http://readyscript.ru/internet-magazin/shop-full/

Как сделать мультисайтовость можно почитать здесь:
Мультисайтовость
Причём править robots.txt, .htaccess не надо, т.к. у нас предусмотрено это действие на автомате при создании нового сайт.

2. Партнёрский модуль.
Он присутствует в версии Гипермаркет и позволяет добавлять сколько угодно сайтов на данную систему, но дело в том, что в данном случае, товары будут те же самые и Вы назначаете в каждый филиал нужные для показа товары, админ у них тоже будет свой. "Мордочки" сайтам можно тоже менять. Вам останется просто на хостинге настроить алиас поддомена на основную папку со скриптом. Добавить в админке сайты можно через Разное->Партнёрский модуль. Папочки с поддоменами соответственно на хостинге.

PS. Какую нагрузку на БД потянет скрипт? 10 000? 50 000? 200 000?

Скрипт потянет все, но надо понимать, что сайт это одна сторона, а хостинг другая. У нас есть сайты 35 000 и 60 000 товаров, которые себя спокойно чувствуют на обычном shared хостинге. Но надо смотреть по нагрузке, если посещаемость высокая, то соотвественно надо и хостинг по лучше. Но у нас скрипт не очень требовательный к ресурсом. Просто здесь всё индивидуально и зависит от хостинга.

2,352

(3 ответов, оставленных в Вопросы по работе с системой)

При вызове поля через getPropertyView есть несколько параметров первым из которых является имя поля соответствующего объекта. А второй парамер принимает массив атрибутов для этого поля. Поэтому для Вашего случая конструкция будет выглядеть примерно так:

{$order->getPropertyView('reg_surname', ['placeholder'=>'Мой плэйсхолдер'])} 

Другое дело, что у нас действует ещё плагин data-deftext, который выполняет туже функцию, что и placeholder, только чуточку лучше и под все браузеры.
Поэтому можно и так:

{$order->getPropertyView('reg_surname', ['data-deftext'=>'Мой плэйсхолдер'])} 

В этой теме так как и в остальных используется activeTabs плагин для js. Находится он в jquery.activetabs.js. Там скрываются нужные контейнеры с классом tabFrame Скорее всего надо будет дообернуть нужный кусочек данным контейнером. Т.к. повидимому он не обёрнут.
Соответственно, нужно учесть, что данные контейнеры обладают своими идентификаторами, например первый это id="user-tab1", в него надо и обернуть.

Ну если у Вас присутствует домен xxxxx.ru, то поддомен, это просто папка как вы и указали. Т.е. по идее достаточно просто в браузере открыть поддомен, чтобы началась установка.

У нас такое реализовано было здесь
http://nefertiti-gsfr.ru/product/plat-e-00410-61061/
Кнопка в корзину представляет собой такой вид:

<div class="addToCartContainer" data-cart-url="{$router->getUrl('shop-front-cartpage')}">
     <a href="{$router->getUrl('shop-front-cartpage', ["add" => $product.id])}" class="buyButton addToCart noShowCart" data-product-page="1">В корзину <i></i></a>
</div>

А на класс addToCartContainer навешено событие, которое дописывает внутрь нужный нам код. В данном случае это выглядит так(theme.js):

var qCartAdd; //Таймер показа подсказки при покупке
    
/**
* Скрывать подсказку показывающую, что товар добавлен в корзину
* 
*/
function hideCartHint(){
    clearTimeout(qCartAdd); //Очищаем таймер, если он установлен
    $("#cartHint").stop(true,true).fadeOut('slow',function(){ //Делаем затухание
        $("#cartHint").remove(); //Удаляем добавлнный нами HTML
    }); 
} 

$(function() {

  /**
  * Событие которое вешается добавление в корзину, чтобы расширить функционал при добавлении в корзину. 
  * product.add это событие которое вызывается при добавлении в корзину
  * @param object e - объект события
  * @param object params - параметры из функции добавления в корзину
  */
  $('body').on('product.add',function(e, params){
        clearTimeout(qCartAdd); //Очищаем таймер, если он установлен
        var _this = e.target; //Сама кнопка
        var url   = $(_this).closest('[data-cart-url]').data('cart-url'); //Откуда берём url корзины
        $('#cartHint').stop(true,true).remove(); //Погасим прошлое всплывание, если несколько раз сразу нажали
        $(_this).closest('.addToCartContainer').append('<div id="cartHint" class="cartHint"><div><i></i>Товар добавлен в корзину<br/><a href="'+url+'">Перейти в корзину</a></div></div>'); //Добавляем код внутрь
        $("#cartHint").fadeIn(200,function(){ //Делаем плавный показ
            qCartAdd = setTimeout('hideCartHint()', 3000); //Делаем затухание через 3 секунды
        });
    });
});

Ну соответственно, надо будет настроить css под себя и разобраться javascript, по другому никак.
Если я Вас правильно понял, то это то что Вам нужно.

setFieldPrefix - это метод от родителя данного класса AbstructFilter

А нельзя чуть более подробнее описать процесс вывода кол-ва товаров в категории?

1. Вам нужно, это иметь шаблон блока, который выводит категории.
Он лежит по пути /templates/ВАША ТЕМА/moduleview/catalog/blocks/category/category.tpl
В нём идёт перебор циклом категорий и подкатегорий. Вывод категорий выглядит примерно так:

{$dir.fields.name}

Эту конструкцию надо дополнить так:

{$dir.fields.name} <sup>({$dir.fields.itemcount})</sup>

Т.е. {$dir.fields.itemcount} выводит нужное нам количество.
2. Если у Вас нет там шаблона, то просто скопируйте его из
/modules/catalog/view/blocks/category/category.tpl в
/templates/ВАША ТЕМА/moduleview/catalog/blocks/category/category.tpl
А дальше как в пункте 1.
3. Сохраняем шаблон и сбрасываем кэш.

И плюсом бы еще хотелось добавить кол-во товаров в фильтры (пример на картинке).

Пока такого функционала нет, для реализации задачи можно написать свой модуль.

В одном из ближайших обновлений этого можно будет избежать. В настройках модуля каталог появится флажок "Показывать фильтр по цене в виде слайдера". Если его установить, то всё будет работать сразу.

Да, дело именно в префиксе, т.к. передаётся массив параметрами для поиска и соответственно значение для поиска. Для объекта фильтра используйте функцию setFieldPrefix('f')

Обратитесь к нам в поддержку разберёмся. Вроде всё верно. Но нужно посмотреть.

Какая вкладка в конструкторе сайта у Вас выбрана?

Вроде всё верно. Кэш сбросили? И какая вкладка в конструкторе сайта у Вас выбрана?

А вы в настройках блока "Форма отправки на E-mail" указали форму для вывода?

Ну во первых посмотрите какие значения в списке регионов со значениями. Вероятно просто неверные значения в фильтр подставляются.
По сортировке... Сортировка запоминается в куках. Т.е. Вам надо выставить сортировку сначала нажав на нужную колонку и она запомнится.

У нас в системе действует система маршрутов(масок адресов), в данном случае /feedback-(номер формы)/ Поэтому url именно такой. По нему отслеживается, какую форму необходимо показать и обработать.
Как можно выкрутится?
Можно создать пункт меню в разделе Веб-сайт->Меню, у которого указать тип страница. В поле "Симв. идентификатор" укажем feedback. Далее идём в Веб-сайт->Конструктор сайта и добавляем нашу созданную страницу.
Если адаптивный дизайн, то нужно скопировать в центральной части контейнер из страницы "по-умолчанию" и в центральной части вставить блок с обратной связью.
А если не адаптивный(тема молодёжная), то указываем при создании страницы шаблон и вручную нужно прописать блок с вставкой обратной связи. Например, вот такая запись для вашего случая:

{moduleinsert name="\Feedback\Controller\Block\Feedback" form_id=1}

Всё равно мало сведений. Мне не совсем понятно. Вы хотите вывести информацию с одинаковой длинной символов, или вы хотите, чтобы у Вас были анонсы новостей разбиты по колонкам и эти колонки были одинаковыми по ширине?

Для данной задачи Ваши поля не подойдут. Т.к. в Вашем случае они в БД хранятся в сериализованном виде (зашифрованы). Вам надо написать свой доп модуль и добавить поля к объекту пользователя, тогда в админке можно будет вывести колонку.
О том как добавить поле объекту написано здесь:
http://forum.readyscript.ru/topic/287/k … adyscript/

А потом, уже расширять колонку из своего модуля.

Более конкретно укажите, какая колонка Вам нужна и с какими сведениями?

Желательно, чтобы понимать процессы пройти данный курс.
http://readyscript.ru/text-blog/Kak-soz … adyScript/

Вы можете сделать это с помощью правки css. Либо взять часть css, которая за это отвечает в файле styles.css из темы perfume, и соответственно шаблон /templates/perfume/catalog/blocks/category.tpl и скопировать.

Какие именно вы имеете ввиду?

Я не понял, т.к. функции addjs и addcss здесь не причём. Они добавляют всего лишь между тегами <head> теги с назначаемыми стилями.
http://readyscript.ru/dev-manual/dev_sm … ion_addcss
http://readyscript.ru/dev-manual/dev_sm … tion_addjs

Комментарий по основному вопросу, будет дан чуть позже.

Получилось?

Подскажите, пожалуйста, как можно вставить произвольный текст после DOCTYPE или как можно использовать конструкции типа "before" и "after" из smarty-функций "addcss" и "addjs" применительно к тегу HTML?

Приведите пожалуйста пример, что Вам конкретно нужно получить.

Интересный вопрос и сейчас я его раскрою.
Дело в том, что в системе для того, чтобы сформировать данный ползунок нужно каким-то образом получить максимальную и минимальную цену в зависимости от категории и применённых фильтров. По умолчанию мы не поддерживаем такое получение и не возвращаем сведений, поэтому придётся немного поколдовать, чтобы получить данные.
Первое что надо сделать это получить данные во фронт контроллере списка товаров, т.к. именно в нём применяются все фильтры. Соответственно там мы и должны получать данные.
Нам надо сделать копию файла
/modules/catalog/controller/front/listproducts.inc.php с таким же именем, но окончанием .my.inc.php

т.е.
/modules/catalog/controller/front/listproducts.my.inc.php

Откроем его и посмотрим в метод actionIndex().

Нам надо заменить:

$basefilter = $this->api->applyBaseFilters();
$total      = $this->api->getMultiDirCount();
                            
$this->api->queryObj()->groupby($this->api->defAlias().'.id');
//Устанавливаем сортировку
$sort_field = $this->cur_sort == 'rank' ? $this->cur_sort : $this->api->defAlias().'.'.$this->cur_sort;
$this->api->setSortOrder($sort_field, $this->cur_n_sort);

На:

/**
* @var \RS\Orm\Request
*/
$minmaxQuery = clone $this->api->queryObj();                                                  
                
$basefilter = $this->api->applyBaseFilters();
$total      = $this->api->getMultiDirCount();
                
//Добавим цены к запросу
$current_cost_type = \Catalog\Model\CostApi::getUserCost(); //Текущий тип цен
$current_cost_type = \Catalog\Model\CostApi::getInstance()->getManualType($current_cost_type);
$minmaxQuery->leftjoin(new \Catalog\Model\Orm\Xcost(), "A.id = XC.product_id AND XC.cost_id='{$current_cost_type}'", 'XC');

$minmaxQuery->orderby(''); 
$minmaxQuery->select = 'max(XC.cost_val) interval_to,min(XC.cost_val) interval_from';
$moneyArray = $minmaxQuery->exec()->fetchRow();
$moneyArray['step']  = 1;
$moneyArray['round'] = 1;
$moneyArray['unit']  = \Catalog\Model\CurrencyApi::getDefaultCurrency()->stitle;
$moneyArray['heterogeneity']  = $this->getHeterogeneity($moneyArray['interval_from'],$moneyArray['interval_to']);
                
$this->router->getCurrentRoute()->money_array = $moneyArray;
                            
$this->api->queryObj()->groupby($this->api->defAlias().'.id');
$this->api->setSortOrder($this->api->defAlias().'.'.$this->cur_sort, $this->cur_n_sort);

В указанном выше кусочке кода мы получаем массив $moneyArray на основе запроса максимальной и минимальной цены для формирования данных, которые нам понадобятся в шаблоне.
Эти значения мы поместим в наш класс роута который будет доступен по данному url в любом блок контроллере с помощью

$this->router->getCurrentRoute()->money_array = $moneyArray;

Это нам понадобится, чтобы передать в блок контроллер фильтров данные значения. Т.к. первым отработает фронт контроллер, то после него отработают блок контроллеры из обёртки. А это позволит нам передать туда наши данные для дальнейшего помещения в шаблон.

Функция getHeterogeneity это функция, которая подготавливает массив для рисочек нашего ползунка.
Теперь добавим эту функцию в наш класс.

/**
* Получает риски для цен диапозона цен
* 
* @return string
*/
function getHeterogeneity($min,$max){
       $max = floatval($max); 
       $min = floatval($min); 
       //Проверим возможно ли это
       if ($max==$min) return "";
       $delta = $max-$min;
       $d25 = ceil($min + (($delta/100)*25)); 
       $d50 = ceil($min + (($delta/100)*50)); 
       $d75 = ceil($min + (($delta/100)*75)); 
       return '"25/'.$d25.'","50/'.$d50.'","75/'.$d75.'"';
}

С этой часть мы покончили. Теперь нам необходимо перейти к блок контроллеру фильтров в которых обработать наши сведения и поместить в шаблон фильтров дополнительные сведения.
Для этого делаем копию блок контроллера фильтров

/modules/catalog/controller/block/sidefilters.inc.php

и  также

/modules/catalog/controller/block/sidefilters.my.inc.php

И заходим в класс SideFilters нашего нового файла в метод actionIndex().

Добавим в шаблон в массив через $this->view->assign новый элемента массива

$this->view->assign(array(
     ...
     'moneyArray' => $this->router->getCurrentRoute()->money_array,
     ...
));

Троеточие используется для примера данных.

Теперь нам нужен шаблон "blocks/sidefilters/filters.tpl" (У каждой темы соответственно в своей папке).
Строки, которые отвечают у нас за отображение фильтра надо заменить на:

{if $param.show_cost_filter}
                        <div class="priceFilter typeInterval">
                            <span class="title">Цена:</span>
                            <div class="typeInterval fromToPrice">
                                <input type="hidden" class="textinp fromto" name="bfilter[cost][from]" value="{$basefilters.cost.from}" data-start-value="">
                                <input type="hidden" class="textinp fromto" name="bfilter[cost][to]" value="{$basefilters.cost.to}" data-start-value="">
                            </div>
                            
                            <div class="priceInterval fromToLine">               
                                <input type="hidden" data-slider='{ "from":{$moneyArray.interval_from}, "to":{$moneyArray.interval_to}, "step": "{$moneyArray.step}", "round": {$moneyArray.round}, "dimension": " {$moneyArray.unit}", "heterogeneity": [{$moneyArray.heterogeneity}]  }' value="{$basefilters.cost.from|default:$moneyArray.interval_from};{$basefilters.cost.to|default:$moneyArray.interval_to}" class="pluginInput" data-closest=".fromToPrice" data-start-value="{$basefilters.cost.from|default:$moneyArray.interval_from};{$basefilters.cost.to|default:$moneyArray.interval_to}">
                            </div>  
                            <input type="submit" value="Применить" class="onemore submitFilter" style="display:none;"/>
   </div>
{/if}

html у нас готов теперь надо активировать js.
В примере я воспользуюсь нашим стандартным слайдером (jslider - jquery.slider.min.js), который есть во всех наших темах.
У нас это указано так.


<script type="text/javascript">
                $(function() {
                    $('.typeInterval .pluginInput').each(function() {
                        var $this = $(this);
                        
                        var fromTo = $($this.data('closest'));  
                        fromTo.hide(); 
                        $this.jslider( $.extend( $(this).data('slider'), { callback: function(value) {
                            
                            var values = value.split(';');
                            $('input[name$="[from]"]', fromTo).val(values[0]);
                            $('input[name$="[to]"]', fromTo).val(values[1]);
                            $this.trigger('change');
                        }}));
                        
                        $('input[name$="[from]"], input[name$="[to]"]', fromTo).change(function() {
                            var from = $('input[name$="[from]"]', fromTo).val();
                            var to = $('input[name$="[to]"]', fromTo).val();
                            $this.jslider('value', from, to);
                        });
                    });
</script>