(阶段三:整合)面向用户 & 面向商户,场景之:shop

1. 明确边界:cms配置的 PageInstance.sections 数组只用来配置

【默认内容 + 主题颜色(未来开放)】

 

[section_display]

props:
    // 商户定义“这个模块默认展示哪些分类”
  category_ids_default: ['software', 'education'], 
  sort_tag_default: 'latest' 
  priceRangeBreakpoints: [20, 40, 80] 
  pagination: { pageSize: 12 },
  CTA: {
    title: "现在开始",
    buttonText: "立即购买",
    description: "xxxxx"
    position: 6
  }
}

[section_detail]
------ 更新设计:“持久化时扁平,运行时结构化”-------

props: {
    category_ids_default: ['software', 'education'], // 或者null
    sort_tag_default: 'latest',
    price_range_breakpoints: [20, 40, 80],
    page_size: 12,

    CTA_title: '立即购买',
    CTA_buttonText: '现在开始',
    CTA_description: 'xxxxx',
    CTA_position: 6
}

渲染前将扁平字段还原成对象:

 

const CTA = {
 title: props.CTA_title,
 description: props.CTA_description,
 buttonText: props.CTA_buttonText,
 position: props.CTA_position,
}

 

数据型,如category,依然是放在数据库的table里面

2. 细说price range设计

CMS部分

 1. 💡 商户只输入数字数组(比如在 UI 上输入 tag:204080):

type PriceBreakpoints = number[] // e.g. [20, 40, 80]

SectionInstance.props存储

props: {
  priceRangeBreakpoints: [20, 40, 80]
}

前端渲染部分:根据 priceRangeBreakpoints 转化成标签

2. ✅ 平台自动转成区间列表:

type PriceRangeOption = {
  label: string
  min?: number
  max?: number
}

function generatePriceRanges(breakpoints: number[]): PriceRangeOption[] {
  const sorted = [...breakpoints].sort((a, b) => a - b)
  const ranges: PriceRangeOption[] = []

  if (sorted.length === 0) return []

  // Less than first
  ranges.push({
    max: sorted[0],
    label: `Less than $${sorted[0]}`
  })

  for (let i = 0; i < sorted.length - 1; i++) {
    ranges.push({
      min: sorted[i],
      max: sorted[i + 1],
      label: `$${sorted[i]} - $${sorted[i + 1]}`
    })
  }

  // More than last
  ranges.push({
    min: sorted[sorted.length - 1],
    label: `More than $${sorted[sorted.length - 1]}`
  })

  return ranges
}

sql查询部分:

标签为:

[
  { max: 20, label: "Less than $20" },
  { min: 20, max: 40, label: "$20 - $40" },
  { min: 40, max: 80, label: "$40 - $80" },
  { min: 80, label: "More than $80" }
]

当用户点击某个 price tag,你将这个 { min?, max? } 作为 query param 发给后端:

GET /api/products?price_min=20&price_max=40

后端查询:

function getProducts({ price_min, price_max }) {
  const conditions = []

  if (price_min !== undefined) {
    conditions.push(`price >= ${price_min}`)
  }
  if (price_max !== undefined) {
    conditions.push(`price < ${price_max}`)
  }

  const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''

  const sql = `
    SELECT * FROM products
    ${whereClause}
    ORDER BY price ASC
    LIMIT 20 OFFSET 0
  `

  return db.query(sql)
}

 3.  display页面整体流程分析

【layout的时候初始化redux】
把sorttagdefault,categorydefault, page=1,
pricerange = null,
注入redux;【涉及用户交互】

【SSR的时候,】

1. 查出sectionInstance.props,比如可以组装成CTA object+pagesize【商家固定】传给client comp

2. 根据pagesize+sortTagdefault+categorydefault(如果是all,就把这个condition忽视),进行products数据库查询。

3. products_count (用于pagination组件赋值)

【client component的时候,】
从redux里面拿出sorttagdefault,categorydefault, page,pricerange 和对应的dispatch方法
用于赋值初始值和onClick


【CSR的时候 】

1. priceRange发生改变,dispatch priceRange,触发react-query:用redux里面的pagesize,sortTag,category,到后台,组装的priceRange condition,进行sql查询。
查完了dispatch products_count

2. pagination发生改变, dispatch page ,触发react-query

3. category发生改变 ( dispatch category ;dispatch page = 1),触发react-query
查完了dispatch products_count

4. sortTag发生变化 ( dispatch sortTag; dispatch page = 1),触发react-query
查完了dispatch products_count

4. 具体修改实操

1. 把shopstack进行router改变:把原先所有路由加入/products下。
【首页】
【layout】的redux里面themeoptions里面拿sceneMap初始化,sceneList。
以及themeName
tenantId+tenantName

获得首页Header:目前暂时直接为null
Client Comp中间层引入themeHook:
1. dymamic import "cool-landing-header" 来setComponent

得到Styled_Header_component。

【page.tsx】目前暂时直接为null
Client Comp中间层引入themeHook:
dynamic import "cool-landing-mainPage"来setComponent


2. /products下的layout里面的查询和redux初始化:

涉及用户auth的redux初始化
把sorttagdefault,categorydefault, page=1,
pricerange = null, 注入redux;

=> 如果商家没有这个scene,那么根本查不到这些数据!!!可以直接return null

Client Comp中间层引入themeHook:
- dynamic import "cool-shop-header"来setComponent
- 往这个component里面注入 redux的用户auth数据!

得到 Styled_Product_Header。

3. /products的【page.tsx】里面

=> SSR里面判断themeOptions里面是否有这个scene,没有就404!

所有sectionInstance.props暂时都写死!

 

posted @ 2025-07-29 03:53  PEAR2020  阅读(11)  评论(0)    收藏  举报