mirror of
https://github.com/primedigitaltech/market-assistant.git
synced 2026-07-24 17:21:40 +08:00
feat(dataset): 类目文案统一并支持按店铺名筛选
摘要 category_options;列/导出「类目」;查询参数 shop_q 模糊匹配店铺(搜索 shop_name、商详 detail_shop_name、宽表双列)。 Made-with: Cursor
This commit is contained in:
parent
d95189723c
commit
5ea55233b1
@ -1,4 +1,4 @@
|
|||||||
"""库内数据浏览 API:排序、价格与报告细类筛选(查询参数解析与 QuerySet 变换)。"""
|
"""库内数据浏览 API:排序、价格、类目(§5 矩阵)与店铺名筛选。"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
@ -57,10 +57,15 @@ def price_bounds_from_request(request: Request) -> tuple[float | None, float | N
|
|||||||
|
|
||||||
|
|
||||||
def report_group_from_request(request: Request) -> str:
|
def report_group_from_request(request: Request) -> str:
|
||||||
"""与 §5 矩阵一致的细类名(如「饼干」「米」);对应查询参数 ``report_group``。"""
|
"""与 §5 矩阵一致的类目名(如饼干、米);查询参数 ``report_group``。"""
|
||||||
return (request.query_params.get("report_group") or "").strip()
|
return (request.query_params.get("report_group") or "").strip()
|
||||||
|
|
||||||
|
|
||||||
|
def shop_q_from_request(request: Request) -> str:
|
||||||
|
"""店铺名模糊匹配;查询参数 ``shop_q``。"""
|
||||||
|
return (request.query_params.get("shop_q") or "").strip()
|
||||||
|
|
||||||
|
|
||||||
def detail_category_q_from_request(request: Request) -> str:
|
def detail_category_q_from_request(request: Request) -> str:
|
||||||
return (request.query_params.get("detail_category_q") or "").strip()
|
return (request.query_params.get("detail_category_q") or "").strip()
|
||||||
|
|
||||||
@ -68,6 +73,7 @@ def detail_category_q_from_request(request: Request) -> str:
|
|||||||
def filter_echo(
|
def filter_echo(
|
||||||
*,
|
*,
|
||||||
report_group: str,
|
report_group: str,
|
||||||
|
shop_q: str,
|
||||||
price_min: float | None,
|
price_min: float | None,
|
||||||
price_max: float | None,
|
price_max: float | None,
|
||||||
detail_category_q: str,
|
detail_category_q: str,
|
||||||
@ -76,6 +82,7 @@ def filter_echo(
|
|||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
return {
|
return {
|
||||||
"report_group": report_group or None,
|
"report_group": report_group or None,
|
||||||
|
"shop_q": shop_q or None,
|
||||||
"price_min": price_min,
|
"price_min": price_min,
|
||||||
"price_max": price_max,
|
"price_max": price_max,
|
||||||
"detail_category_q": detail_category_q or None,
|
"detail_category_q": detail_category_q or None,
|
||||||
@ -88,6 +95,9 @@ def apply_search_filters(qs: QuerySet, request: Request) -> QuerySet:
|
|||||||
rg = report_group_from_request(request)
|
rg = report_group_from_request(request)
|
||||||
if rg:
|
if rg:
|
||||||
qs = qs.filter(Q(matrix_group_label=rg) | Q(leaf_category=rg))
|
qs = qs.filter(Q(matrix_group_label=rg) | Q(leaf_category=rg))
|
||||||
|
sq = shop_q_from_request(request)
|
||||||
|
if sq:
|
||||||
|
qs = qs.filter(shop_name__icontains=sq)
|
||||||
pmin, pmax = price_bounds_from_request(request)
|
pmin, pmax = price_bounds_from_request(request)
|
||||||
if pmin is not None:
|
if pmin is not None:
|
||||||
qs = qs.filter(price_value__gte=pmin)
|
qs = qs.filter(price_value__gte=pmin)
|
||||||
@ -121,6 +131,9 @@ def apply_detail_filters(qs: QuerySet, request: Request) -> QuerySet:
|
|||||||
rg = report_group_from_request(request)
|
rg = report_group_from_request(request)
|
||||||
if rg:
|
if rg:
|
||||||
qs = qs.filter(matrix_group_label=rg)
|
qs = qs.filter(matrix_group_label=rg)
|
||||||
|
sq = shop_q_from_request(request)
|
||||||
|
if sq:
|
||||||
|
qs = qs.filter(detail_shop_name__icontains=sq)
|
||||||
q = detail_category_q_from_request(request)
|
q = detail_category_q_from_request(request)
|
||||||
if q:
|
if q:
|
||||||
qs = qs.filter(detail_category_path__icontains=q)
|
qs = qs.filter(detail_category_path__icontains=q)
|
||||||
@ -157,6 +170,11 @@ def apply_merged_filters(qs: QuerySet, request: Request) -> QuerySet:
|
|||||||
rg = report_group_from_request(request)
|
rg = report_group_from_request(request)
|
||||||
if rg:
|
if rg:
|
||||||
qs = qs.filter(matrix_group_label=rg)
|
qs = qs.filter(matrix_group_label=rg)
|
||||||
|
sq = shop_q_from_request(request)
|
||||||
|
if sq:
|
||||||
|
qs = qs.filter(
|
||||||
|
Q(shop_name__icontains=sq) | Q(detail_shop_name__icontains=sq)
|
||||||
|
)
|
||||||
q = detail_category_q_from_request(request)
|
q = detail_category_q_from_request(request)
|
||||||
if q:
|
if q:
|
||||||
qs = qs.filter(detail_category_path__icontains=q)
|
qs = qs.filter(detail_category_path__icontains=q)
|
||||||
|
|||||||
@ -14,7 +14,7 @@ from .csv_schema import (
|
|||||||
from .models import JdJobCommentRow, JdJobDetailRow, JdJobMergedRow, JdJobSearchRow, PipelineJob
|
from .models import JdJobCommentRow, JdJobDetailRow, JdJobMergedRow, JdJobSearchRow, PipelineJob
|
||||||
from .row_serialize import COMMENT_FIELDS_ORDER, DETAIL_FIELDS_ORDER
|
from .row_serialize import COMMENT_FIELDS_ORDER, DETAIL_FIELDS_ORDER
|
||||||
|
|
||||||
MATRIX_GROUP_COLUMN = {"key": "matrix_group_label", "label": "报告细类(§5矩阵)"}
|
MATRIX_GROUP_COLUMN = {"key": "matrix_group_label", "label": "类目"}
|
||||||
|
|
||||||
|
|
||||||
def _is_nonempty(val) -> bool:
|
def _is_nonempty(val) -> bool:
|
||||||
|
|||||||
@ -122,7 +122,7 @@ def _bulk_create_in_chunks(model, objects: list[Any]) -> None:
|
|||||||
def _sync_search_rows_matrix_labels(
|
def _sync_search_rows_matrix_labels(
|
||||||
job: PipelineJob, merged_kw_list: list[tuple[int, dict[str, str]]]
|
job: PipelineJob, merged_kw_list: list[tuple[int, dict[str, str]]]
|
||||||
) -> None:
|
) -> None:
|
||||||
"""按 SKU 将合并表解析出的报告细类回填到搜索行(与 §5 矩阵口径一致)。"""
|
"""按 SKU 将合并表解析出的类目回填到搜索行(与 §5 矩阵口径一致)。"""
|
||||||
sku_to_mg: dict[str, str] = {}
|
sku_to_mg: dict[str, str] = {}
|
||||||
for _, kw in merged_kw_list:
|
for _, kw in merged_kw_list:
|
||||||
sk = (kw.get("sku_id") or "").strip()
|
sk = (kw.get("sku_id") or "").strip()
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
"""
|
"""
|
||||||
与 ``jd_competitor_report._matrix_group_label_from_path`` 同源:
|
与 ``jd_competitor_report._matrix_group_label_from_path`` 同源:
|
||||||
从商详 ``detail_category_path`` 解析 §5 竞品矩阵用的细类展示名(如「饼干」「米」)。
|
从商详 ``detail_category_path`` 解析 §5 竞品矩阵用的类目展示名(如饼干、米)。
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,28 @@
|
|||||||
|
# Generated by Django 5.2.1 on 2026-04-16 02:04
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('pipeline', '0018_report_group_matrix_label'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='jdjobdetailrow',
|
||||||
|
name='matrix_group_label',
|
||||||
|
field=models.CharField(blank=True, db_index=True, default='', help_text='与 §5 矩阵同源:由 detail_category_path 解析', max_length=80, verbose_name='类目'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='jdjobmergedrow',
|
||||||
|
name='matrix_group_label',
|
||||||
|
field=models.CharField(blank=True, db_index=True, default='', help_text='与 §5 矩阵同源:由 detail_category_path 解析', max_length=80, verbose_name='类目'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='jdjobsearchrow',
|
||||||
|
name='matrix_group_label',
|
||||||
|
field=models.CharField(blank=True, db_index=True, default='', help_text='与 §5 矩阵同源:由合并表商详路径解析;可按 SKU 从合并表回填', max_length=80, verbose_name='类目'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -195,7 +195,7 @@ class JdJobSearchRow(models.Model):
|
|||||||
blank=True,
|
blank=True,
|
||||||
default="",
|
default="",
|
||||||
db_index=True,
|
db_index=True,
|
||||||
verbose_name="报告细类",
|
verbose_name="类目",
|
||||||
help_text="与 §5 矩阵同源:由合并表商详路径解析;可按 SKU 从合并表回填",
|
help_text="与 §5 矩阵同源:由合并表商详路径解析;可按 SKU 从合并表回填",
|
||||||
)
|
)
|
||||||
price_value = models.FloatField(null=True, blank=True, db_index=True)
|
price_value = models.FloatField(null=True, blank=True, db_index=True)
|
||||||
@ -246,7 +246,7 @@ class JdJobDetailRow(models.Model):
|
|||||||
blank=True,
|
blank=True,
|
||||||
default="",
|
default="",
|
||||||
db_index=True,
|
db_index=True,
|
||||||
verbose_name="报告细类",
|
verbose_name="类目",
|
||||||
help_text="与 §5 矩阵同源:由 detail_category_path 解析",
|
help_text="与 §5 矩阵同源:由 detail_category_path 解析",
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -340,7 +340,7 @@ class JdJobMergedRow(models.Model):
|
|||||||
blank=True,
|
blank=True,
|
||||||
default="",
|
default="",
|
||||||
db_index=True,
|
db_index=True,
|
||||||
verbose_name="报告细类",
|
verbose_name="类目",
|
||||||
help_text="与 §5 矩阵同源:由 detail_category_path 解析",
|
help_text="与 §5 矩阵同源:由 detail_category_path 解析",
|
||||||
)
|
)
|
||||||
price_value = models.FloatField(null=True, blank=True, db_index=True)
|
price_value = models.FloatField(null=True, blank=True, db_index=True)
|
||||||
|
|||||||
@ -32,6 +32,7 @@ from .dataset_api import (
|
|||||||
parse_sort_meta,
|
parse_sort_meta,
|
||||||
price_bounds_from_request,
|
price_bounds_from_request,
|
||||||
report_group_from_request,
|
report_group_from_request,
|
||||||
|
shop_q_from_request,
|
||||||
)
|
)
|
||||||
from .dataset_nonempty import (
|
from .dataset_nonempty import (
|
||||||
comment_columns_for_api,
|
comment_columns_for_api,
|
||||||
@ -756,7 +757,7 @@ def _read_page_params(request) -> tuple[int, int]:
|
|||||||
|
|
||||||
|
|
||||||
def _report_group_options_for_job(job: PipelineJob) -> list[str]:
|
def _report_group_options_for_job(job: PipelineJob) -> list[str]:
|
||||||
"""与 §5 矩阵一致的细类名列表(来自合并表 ``detail_category_path`` 解析)。"""
|
"""类目选项:与 §5 矩阵一致,来自合并表 ``detail_category_path`` 解析。"""
|
||||||
qs = (
|
qs = (
|
||||||
JdJobMergedRow.objects.filter(job=job)
|
JdJobMergedRow.objects.filter(job=job)
|
||||||
.exclude(matrix_group_label="")
|
.exclude(matrix_group_label="")
|
||||||
@ -794,7 +795,7 @@ class JobDatasetSummaryView(APIView):
|
|||||||
"detail_columns": detail_columns_for_api(job),
|
"detail_columns": detail_columns_for_api(job),
|
||||||
"comment_columns": comment_columns_for_api(job),
|
"comment_columns": comment_columns_for_api(job),
|
||||||
"merged_columns": merged_columns_for_api(job),
|
"merged_columns": merged_columns_for_api(job),
|
||||||
"report_group_options": _report_group_options_for_job(job),
|
"category_options": _report_group_options_for_job(job),
|
||||||
"detail_category_path_options": _detail_category_path_options(job),
|
"detail_category_path_options": _detail_category_path_options(job),
|
||||||
"dataset_sort_help": {
|
"dataset_sort_help": {
|
||||||
"search": sorted(SEARCH_SORT_FIELDS),
|
"search": sorted(SEARCH_SORT_FIELDS),
|
||||||
@ -813,6 +814,7 @@ class JobDatasetSearchView(APIView):
|
|||||||
sort, desc = parse_sort_meta(request)
|
sort, desc = parse_sort_meta(request)
|
||||||
sort_eff = sort if sort in SEARCH_SORT_FIELDS else "row_index"
|
sort_eff = sort if sort in SEARCH_SORT_FIELDS else "row_index"
|
||||||
rg = report_group_from_request(request)
|
rg = report_group_from_request(request)
|
||||||
|
sq = shop_q_from_request(request)
|
||||||
pmin, pmax = price_bounds_from_request(request)
|
pmin, pmax = price_bounds_from_request(request)
|
||||||
dcq = detail_category_q_from_request(request)
|
dcq = detail_category_q_from_request(request)
|
||||||
qs = JdJobSearchRow.objects.filter(job=job)
|
qs = JdJobSearchRow.objects.filter(job=job)
|
||||||
@ -828,6 +830,7 @@ class JobDatasetSearchView(APIView):
|
|||||||
"page_size": page_size,
|
"page_size": page_size,
|
||||||
"filters": filter_echo(
|
"filters": filter_echo(
|
||||||
report_group=rg,
|
report_group=rg,
|
||||||
|
shop_q=sq,
|
||||||
price_min=pmin,
|
price_min=pmin,
|
||||||
price_max=pmax,
|
price_max=pmax,
|
||||||
detail_category_q=dcq,
|
detail_category_q=dcq,
|
||||||
@ -846,6 +849,7 @@ class JobDatasetDetailView(APIView):
|
|||||||
sort, desc = parse_sort_meta(request)
|
sort, desc = parse_sort_meta(request)
|
||||||
sort_eff = sort if sort in DETAIL_SORT_FIELDS else "row_index"
|
sort_eff = sort if sort in DETAIL_SORT_FIELDS else "row_index"
|
||||||
rg = report_group_from_request(request)
|
rg = report_group_from_request(request)
|
||||||
|
sq = shop_q_from_request(request)
|
||||||
pmin, pmax = price_bounds_from_request(request)
|
pmin, pmax = price_bounds_from_request(request)
|
||||||
dcq = detail_category_q_from_request(request)
|
dcq = detail_category_q_from_request(request)
|
||||||
qs = JdJobDetailRow.objects.filter(job=job)
|
qs = JdJobDetailRow.objects.filter(job=job)
|
||||||
@ -861,6 +865,7 @@ class JobDatasetDetailView(APIView):
|
|||||||
"page_size": page_size,
|
"page_size": page_size,
|
||||||
"filters": filter_echo(
|
"filters": filter_echo(
|
||||||
report_group=rg,
|
report_group=rg,
|
||||||
|
shop_q=sq,
|
||||||
price_min=pmin,
|
price_min=pmin,
|
||||||
price_max=pmax,
|
price_max=pmax,
|
||||||
detail_category_q=dcq,
|
detail_category_q=dcq,
|
||||||
@ -901,6 +906,7 @@ class JobDatasetMergedView(APIView):
|
|||||||
sort, desc = parse_sort_meta(request)
|
sort, desc = parse_sort_meta(request)
|
||||||
sort_eff = sort if sort in MERGED_SORT_FIELDS else "row_index"
|
sort_eff = sort if sort in MERGED_SORT_FIELDS else "row_index"
|
||||||
rg = report_group_from_request(request)
|
rg = report_group_from_request(request)
|
||||||
|
sq = shop_q_from_request(request)
|
||||||
pmin, pmax = price_bounds_from_request(request)
|
pmin, pmax = price_bounds_from_request(request)
|
||||||
dcq = detail_category_q_from_request(request)
|
dcq = detail_category_q_from_request(request)
|
||||||
qs = JdJobMergedRow.objects.filter(job=job)
|
qs = JdJobMergedRow.objects.filter(job=job)
|
||||||
@ -916,6 +922,7 @@ class JobDatasetMergedView(APIView):
|
|||||||
"page_size": page_size,
|
"page_size": page_size,
|
||||||
"filters": filter_echo(
|
"filters": filter_echo(
|
||||||
report_group=rg,
|
report_group=rg,
|
||||||
|
shop_q=sq,
|
||||||
price_min=pmin,
|
price_min=pmin,
|
||||||
price_max=pmax,
|
price_max=pmax,
|
||||||
detail_category_q=dcq,
|
detail_category_q=dcq,
|
||||||
|
|||||||
@ -24,7 +24,7 @@ const SORT_LABELS = {
|
|||||||
sku_id: 'SKU',
|
sku_id: 'SKU',
|
||||||
title: '标题',
|
title: '标题',
|
||||||
leaf_category: '叶类目',
|
leaf_category: '叶类目',
|
||||||
matrix_group_label: '报告细类',
|
matrix_group_label: '类目',
|
||||||
detail_category_path: '类目路径',
|
detail_category_path: '类目路径',
|
||||||
detail_brand: '品牌',
|
detail_brand: '品牌',
|
||||||
}
|
}
|
||||||
@ -40,8 +40,9 @@ const err = ref('')
|
|||||||
const commentSkuFilter = ref('')
|
const commentSkuFilter = ref('')
|
||||||
const sortField = ref('row_index')
|
const sortField = ref('row_index')
|
||||||
const sortOrder = ref('asc')
|
const sortOrder = ref('asc')
|
||||||
/** 与 §5 矩阵一致的细类名(如饼干、米),对应接口参数 report_group */
|
/** 类目(§5 矩阵),对应接口参数 report_group */
|
||||||
const reportGroup = ref('')
|
const reportGroup = ref('')
|
||||||
|
const shopQ = ref('')
|
||||||
const priceMin = ref('')
|
const priceMin = ref('')
|
||||||
const priceMax = ref('')
|
const priceMax = ref('')
|
||||||
const detailCategoryQ = ref('')
|
const detailCategoryQ = ref('')
|
||||||
@ -70,7 +71,7 @@ const sortOptions = computed(() => {
|
|||||||
return keys.map((k) => ({ value: k, label: SORT_LABELS[k] || k }))
|
return keys.map((k) => ({ value: k, label: SORT_LABELS[k] || k }))
|
||||||
})
|
})
|
||||||
|
|
||||||
const reportGroupOptions = computed(() => summary.value?.report_group_options || [])
|
const categoryOptions = computed(() => summary.value?.category_options || [])
|
||||||
|
|
||||||
const displayColumns = computed(() => {
|
const displayColumns = computed(() => {
|
||||||
const s = summary.value
|
const s = summary.value
|
||||||
@ -162,6 +163,7 @@ async function refreshList() {
|
|||||||
sort: sortField.value,
|
sort: sortField.value,
|
||||||
order: sortOrder.value,
|
order: sortOrder.value,
|
||||||
reportGroup: reportGroup.value.trim(),
|
reportGroup: reportGroup.value.trim(),
|
||||||
|
shopQ: shopQ.value.trim(),
|
||||||
priceMin: priceMin.value,
|
priceMin: priceMin.value,
|
||||||
priceMax: priceMax.value,
|
priceMax: priceMax.value,
|
||||||
detailCategoryQ: detailCategoryQ.value.trim(),
|
detailCategoryQ: detailCategoryQ.value.trim(),
|
||||||
@ -196,6 +198,7 @@ watch(
|
|||||||
sortField.value = 'row_index'
|
sortField.value = 'row_index'
|
||||||
sortOrder.value = 'asc'
|
sortOrder.value = 'asc'
|
||||||
reportGroup.value = ''
|
reportGroup.value = ''
|
||||||
|
shopQ.value = ''
|
||||||
priceMin.value = ''
|
priceMin.value = ''
|
||||||
priceMax.value = ''
|
priceMax.value = ''
|
||||||
detailCategoryQ.value = ''
|
detailCategoryQ.value = ''
|
||||||
@ -214,6 +217,7 @@ watch(tab, () => {
|
|||||||
sortField.value = 'row_index'
|
sortField.value = 'row_index'
|
||||||
sortOrder.value = 'asc'
|
sortOrder.value = 'asc'
|
||||||
reportGroup.value = ''
|
reportGroup.value = ''
|
||||||
|
shopQ.value = ''
|
||||||
priceMin.value = ''
|
priceMin.value = ''
|
||||||
priceMax.value = ''
|
priceMax.value = ''
|
||||||
detailCategoryQ.value = ''
|
detailCategoryQ.value = ''
|
||||||
@ -224,6 +228,7 @@ watch(
|
|||||||
sortField,
|
sortField,
|
||||||
sortOrder,
|
sortOrder,
|
||||||
reportGroup,
|
reportGroup,
|
||||||
|
shopQ,
|
||||||
priceMin,
|
priceMin,
|
||||||
priceMax,
|
priceMax,
|
||||||
detailCategoryQ,
|
detailCategoryQ,
|
||||||
@ -243,6 +248,7 @@ watch(
|
|||||||
sortField,
|
sortField,
|
||||||
sortOrder,
|
sortOrder,
|
||||||
reportGroup,
|
reportGroup,
|
||||||
|
shopQ,
|
||||||
priceMin,
|
priceMin,
|
||||||
priceMax,
|
priceMax,
|
||||||
detailCategoryQ,
|
detailCategoryQ,
|
||||||
@ -428,12 +434,21 @@ async function runExport(format) {
|
|||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
<label class="filter-item">
|
<label class="filter-item">
|
||||||
报告细类(与矩阵一致)
|
类目(§5 矩阵)
|
||||||
<select v-model="reportGroup" class="filter-select wide">
|
<select v-model="reportGroup" class="filter-select wide">
|
||||||
<option value="">全部</option>
|
<option value="">全部</option>
|
||||||
<option v-for="g in reportGroupOptions" :key="g" :value="g">{{ g }}</option>
|
<option v-for="g in categoryOptions" :key="g" :value="g">{{ g }}</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
<label class="filter-item">
|
||||||
|
店铺名包含
|
||||||
|
<input
|
||||||
|
v-model="shopQ"
|
||||||
|
type="search"
|
||||||
|
class="filter-input wide"
|
||||||
|
placeholder="模糊匹配店铺名"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
<template v-if="tab === 'detail' || tab === 'merged'">
|
<template v-if="tab === 'detail' || tab === 'merged'">
|
||||||
<label class="filter-item">
|
<label class="filter-item">
|
||||||
类目路径包含
|
类目路径包含
|
||||||
|
|||||||
@ -209,6 +209,9 @@ export function jobDatasetPageUrl(jobId, kind, page = 1, pageSize = 50, opts = {
|
|||||||
o.reportGroup ?? o.report_group ?? o.categoryNormId ?? o.category_norm_id
|
o.reportGroup ?? o.report_group ?? o.categoryNormId ?? o.category_norm_id
|
||||||
if (rg !== undefined && rg !== null && String(rg).trim() !== '')
|
if (rg !== undefined && rg !== null && String(rg).trim() !== '')
|
||||||
p.set('report_group', String(rg).trim())
|
p.set('report_group', String(rg).trim())
|
||||||
|
const shopQ = o.shopQ ?? o.shop_q
|
||||||
|
if (shopQ !== undefined && shopQ !== null && String(shopQ).trim() !== '')
|
||||||
|
p.set('shop_q', String(shopQ).trim())
|
||||||
const pmin = o.priceMin ?? o.price_min
|
const pmin = o.priceMin ?? o.price_min
|
||||||
if (pmin !== undefined && pmin !== null && String(pmin).trim() !== '')
|
if (pmin !== undefined && pmin !== null && String(pmin).trim() !== '')
|
||||||
p.set('price_min', String(pmin).trim())
|
p.set('price_min', String(pmin).trim())
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user