В проекте можно реализовать несколько универсальных каталогов со своей разметкой и набором фильтров (товары, исполнители, заказы, проекты, портфолио и т.д).
Расположены каталоги по адресу /list/{code}
Вид каталога по умолчанию такой (слева категории и фильтры, по центру - основные элементы):

Формат URL категории
Формат URL категории с фильтрами
Формат URL товара
Управление выведено в панели управления Администратора в Компоненты / Универсальные каталоги - /aslists
Таблица БД as_lists
См также HOWTO по каталогам List
На входе:
На выходе множество SELECT, на основе которых осуществляется вывод каталога:
SELECT 1 результаты операции
SELECT 2 Фильтры каталога слева (ID, Code, Title, Tooltip, TypeCode, DefValue, ShowCount, CommaValues, CommaSelected, Options, Placeholder)
SELECT 3 Дерево категорий, показывающих текущее положение в каталоге (ID, Code, Name, Level, URL, ParentID, Count)
SELECT 4 Вложенные категории (ID, Code, Name, Level, URL, ParentID, Count)
SELECT 5 Элементы каталога (ID, Name, Desc, Price, Url, ImgUrl)
SELECT 6 Параметры элементов каталога (ID, Code, Name, Value, ItemID)
SELECT 7 Дополнительные атрибуты для вывода на странице поиска (ID, Code, Name, Value)
SELECT 8 Варианты сортировок (Key, Value)
SELECT 9 Начальное меню категорий (может выводиться наверху перед поиском, например, в самом корне каталога).
Примечание:
Пример процедуры search:
CREATE PROCEDURE [dbo].[list_new_search]
@filters DictionaryParameter READONLY,
@cats nvarchar(256),
@sort nvarchar(24),
@page int,
@username nvarchar(32)
AS
BEGIN
-- ПРОЦЕДУРА ПОИСКА ПО УНИВЕРСАЛЬНОМУ КАТАЛОГУ
/*Определяем какие фильтры есть в url, и с учетом этого
отбираем элементы для каталога*/
-- Для пагинации
declare @PAGE_SIZE int = 10, @total int = 0
/*Сохраняем ID элементов каталога во временной таблице.
Подсчитываем сразу полученное количество*/
declare @itemIDs table (id int)
/*Находим, на какой категории мы сейчас стоим, в общем дереве категорий
@cats - это часть url где указаны категории, например для
/list/suppliers/category1/category1_1/category1_1_3 будет @cats =
'category1,category1_1,category1_1_3'*/
CREATE TABLE dbo.#cats (id int, code nvarchar(256), name nvarchar(256), level
int, parentID int)
insert into #cats
select id, code, name, 1 [level], parentID
from au_projectCategories
where code in (select Value from dbo.split(@cats, ','))
-- Выбранных категорий может быть несколько, с учетом вложенности вложенность
declare @catCount int
select @catCount = count(*) from #cats
/* Находим конечную точку в дереве на которой остановились, то есть
максимального уровня (в примере выше это будет category1_1_3)*/
declare @selectedCatID int
select top 1 @selectedCatID = id from #cats order by level desc
-- Обработка возможных фильтров
-- declare @filterCity nvarchar(256)
-- select @filterCity = Value from @filters where [Key] = 'city'
--- добавляем сортировку в Динамический запрос SELECT 1
declare @sortStatement nvarchar(512)
set @sortStatement = (case @sort
when 'rating' then ' order by name '
end )
-- Итак, что находим учитывая выбранные категории и отмеченные фильтры?
insert into @itemIDs
select distinct id
from (select id, 111 catID
from au_suppliers) t
-- Категории поставщика входящие в выбранные категории, или в дочерние категории выбранных категорий
where (isnull(@cats,'')='' or t.catID = @selectedCatID
or (select parentID from au_projectCategories where id = t.catID) = @selectedCatID )
select @total = count(*) from @itemIDs
-- SELECT 1 - SearchItemsResult (настройки поиска, общие параметры каталога)
select 'Не найдено' EmptyText,
(case when isnull(@cats,'')='' then 'Каталог поставщиков услуг' else (select name from au_projectCategories where id = @selectedCatID) end) Title,
'desc' Text,
@sort Sort,
@page [Page],
@PAGE_SIZE PageSize,
@total Total,
'DEMO' SeoTitle,
'DEMO' SeoDescription,
'DEMO' SeoKeywords,
'' HeadSection,
'' BodyBottomSection,
1 Result,
iif(@langID=1, 'SQL Server', 'SQL Server') BreadcrumbRootTitle,
iif(@langID=1, 'Home', 'Главная')+'||/' preBreadcrumbs,
'' rightBreadcrumb,
'' redirectUrl,
301 redirectStatusCode,
'' Msg
-- SELECT 2 - FilterParameter - Показываем либо все услуги, либо относящиеся к выбранной категории
select 1
/*select 0 id,
'Город' title,
'Город' tooltip,
'city' Code,
'' defValue,
'checks' typeCode,
(select stuff( (
select ','+ name
from (select name from as_geo_regions) t1
for xml path(''), type
).value('.', 'varchar(max)'), 1, 1, ''
)
) as commaValues,
(select top 1 Value from @filters where [Key] = 'city') commaSelected,
3 showCount
*/
-- SELECT 3 - Cat CatChain - Выбранные категории
select * from #cats order by level
-- SELECT 4 - Cat InnerCats - отобразим сбоку либо все категории, либо категории входящие в выбранную
select *
from au_projectCategories
where parentID = @selectedCatID or (parentID is null and @catCount = 0)
drop table #cats
-- SELECT 5 - Item (ID, Desc, Price, Name, URL) -- Данные отображаемые в перечне элементов каталога
select s.id,
isnull(surname+' '+firstname+' '+lastname, username) as name,
'' [desc],
'0' price,
'/list/test/'+isnull(c.username,'')+'---'+try_cast(s.id as nvarchar) Url
from au_suppliers s join ctr_contacts c on c.id = s.contactID
where s.id in (select id from @itemIDs)
-- SELECT 6 - ItemParam
-- Атрибуты элементов каталога
-- Структура Атрибута: ID, Name, Code, Value, ItemID
-- В разметке listItemMakeup атрибут отобразится по {param-code}
select 1 as ID, 'Категории услуг' as Name, 'categories' as Code,
'value1' as Value, 111 as ItemID
union
select 2 as ID,
'О себе' as Name,
'description' as Code,
(select isnull(description,'О себе') from ctr_contacts where id = contactID) as value,
id as ItemID from au_suppliers
-- SELECT 7 - Param общие Атрибуты для каталога (ID, Name, Code, Value)
-- Атрибуты самого каталога
-- Структура Атрибута: ID, Name, Code, Value
-- В разметке listMakeup атрибут отобразится по {param-code}
select 1
-- SELECT 8 - DictionaryParameter Sorts
select 'rating' [key], 'По рейтингу' Value
-- select 9 -- Start cats (категории которые показываются на 1 экране каталога как дашборд {catList})
select id, code, name, 1 level, parentID,'' [Image],
'fas fa-wrench' iconClass
from au_projectCategories where @selectedCatID is null and (parentID is null or parentID in (select id from au_projectCategories where parentID is null) )
END
Входные параметры:
Результат работы процедуры GetItem:
SELECT 1 Данные по выбранному элементу
SELECT 2 Иерархия категорий к данному элементу, путь по категориям (ID, Code, Name, Level, URL, ParentID, Count)
SELECT 3 Дополнительные атрибуты элемента в виде таблицы (ID, Code, Name, Value, ItemID)
SELECT 4-8 Кастомные списки (используются только параметры с названиями p1, p2, p3, p4, p5, p6)
Примеры процедуры GetItem https://pastebin.com/WJFMKYTT
Примечание:
Параметры для вставки в разметку (используются как {name} и заменяются при рендеринге на данные из search процедуры):
Параметры (использовать как {code}):
Исходный базовый адрес должен учитывать текущую категорию:
// startUrl - это /list/xx
var url = $('.cat-cats li:last a').attr('href') || $('.cat-innerCats a.active').attr('href') || startUrl;
Либо это последний элемент в cat-cats (цепочка выбранных категорий), либо выбранный элемент из cat-innerCats (если это статичный список и всегода выводтся на странице. active определяется по полю url (текущий адрес включает в себя или нет URL этой категории) в SELECT 4 процедуры list_xx_search).
Если этого не учитывать, то текущая выбранная категория не будет учитываться при построении адреса (при пагинации или сортировке).