| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- import canvasTemplate from './canvas.json'
- import goodsTemplate from './goods.json'
- import goodsTemplate1 from './goods1.json'
- /**
- * 规范化商品数据:拍平为一个货号数组
- * 每个元素结构:
- * {
- * sku: 'A596351',
- * color: '黑色',
- * pics: { '俯视': '...', '侧视': '...' },
- * design: '设计理念文案',
- * styleKey: 'AC5120913',
- * styleNo: 'E305-01003',
- * raw: 原始对象
- * }
- */
- export function normalizeGoods(goodsList = []) {
- const skus = []
- goodsList.forEach(group => {
- if (!group) return
- Object.entries(group).forEach(([styleKey, entry]) => {
- if (!entry || !Array.isArray(entry['货号资料'])) return
- const styleNo = entry['款号'] || styleKey
- entry['货号资料'].forEach(sku => {
- const design = sku['设计理念'] || entry['设计理念'] || ''
- skus.push({
- sku: sku['货号'],
- color: sku['颜色'],
- pics: sku['pics'] || {},
- design,
- styleKey,
- styleNo,
- // raw 中同时带上整条 entry(可能包含 卖点 / 使用场景 等其他字段)
- raw: {
- ...entry,
- ...sku,
- },
- })
- })
- })
- })
- return skus
- }
- /**
- * 根据画布配置和商品数据,计算每个画布需要生成多少张图片、每张图片使用哪些货号。
- *
- * 这里只做「任务规划」,不真正去用 fabric 生成图片,方便在任意地方静默调用。
- *
- * @param {Array} canvasList - 画布配置数组(同 marketingEdit 保存出去的结构)
- * @param {Array} goodsList - 商品数据数组,例如 [goods, goods1]
- * @returns {Array} renderPlans
- *
- * renderPlans 结构示例:
- * [
- * {
- * canvasIndex: 2,
- * multi_goods_mode: 'multiple',
- * max_goods_count: 2,
- * perCanvasSlots: 2, // 此画布里,单张图最多可展示的货号数(same-angle 图层个数)
- * images: [
- * { imageIndex: 0, skuIndexes: [0,1] },
- * { imageIndex: 1, skuIndexes: [2,null] } // null 表示该位置需要隐藏图层
- * ]
- * },
- * ...
- * ]
- */
- export function buildRenderPlans(canvasList = canvasTemplate, goodsList = [goodsTemplate, goodsTemplate1]) {
- const skus = normalizeGoods(goodsList)
- const totalSkuCount = skus.length
- if (!totalSkuCount) return []
- const plans = []
- canvasList.forEach((canvasItem, cIdx) => {
- if (!canvasItem || !canvasItem.canvas_json) return
- const mode = canvasItem.multi_goods_mode || '' // '' | 'single' | 'multiple'
- const maxGoods = Number(canvasItem.max_goods_count) || null
- // 解析 canvas_json,统计「货号相关图层」数量,用于 multiple 模式下计算每张图可放几个货号
- let perCanvasSlots = 1
- try {
- const json = typeof canvasItem.canvas_json === 'string'
- ? JSON.parse(canvasItem.canvas_json)
- : canvasItem.canvas_json
- const objs = (json && Array.isArray(json.objects)) ? json.objects : []
- const imgPlaceholders = objs.filter(o => o && o['data-type'] === 'img')
- if (mode === 'multiple') {
- perCanvasSlots = Math.max(imgPlaceholders.length, 1)
- } else {
- perCanvasSlots = 1
- }
- } catch (e) {
- perCanvasSlots = 1
- }
- const images = []
- if (!mode) {
- /**
- * 默认(单货号):
- * - 无论有多少货号,只生成 1 张图片
- * - 画布内所有动态文字 / 图片都使用「第一个货号」的数据
- */
- images.push({
- imageIndex: 0,
- skuIndexes: [0], // 始终只用第一个货号
- })
- } else if (mode === 'single') {
- /**
- * 一个货号多角度:
- * - 一张图只展示一个货号
- * - 生成张数 = min(总货号数, 最多货号数量)
- * 例:总 3 个货号,最多货号数为 2 -> 生成 2 张图,分别用前两个货号
- */
- const limit = maxGoods
- ? Math.min(totalSkuCount, maxGoods)
- : totalSkuCount
- for (let i = 0; i < limit; i++) {
- images.push({
- imageIndex: i,
- skuIndexes: [i], // 每张图只使用一个货号
- })
- }
- } else if (mode === 'multiple') {
- /**
- * 多个货号同角度:
- * - 一张图里可以有 perCanvasSlots 个货号位(根据画布中 img 占位层数量推算)
- * - 需要的张数 = ceil(总货号数 / 每张可展示数)
- * - 最终张数 = min(需要的张数, 最多货号数量(如果有的话))
- * 例:画布中有 2 个货号位,商品有 3 个货号,最多货号数=4
- * -> 需要张数 ceil(3/2)=2,受限于 4 -> 实际生成 2 张:
- * 第 1 张:[sku0, sku1],第 2 张:[sku2, null]
- */
- let maxImagesByGoods = Math.ceil(totalSkuCount / perCanvasSlots)
- if (maxGoods) {
- maxImagesByGoods = Math.min(maxImagesByGoods, maxGoods)
- }
- for (let i = 0; i < maxImagesByGoods; i++) {
- const skuIndexes = []
- for (let s = 0; s < perCanvasSlots; s++) {
- const skuIdx = i * perCanvasSlots + s
- skuIndexes.push(skuIdx < totalSkuCount ? skuIdx : null)
- }
- images.push({
- imageIndex: i,
- skuIndexes,
- })
- }
- }
- if (!images.length) return
- plans.push({
- canvasIndex: cIdx,
- multi_goods_mode: mode,
- max_goods_count: maxGoods,
- perCanvasSlots,
- images,
- })
- })
- return plans
- }
|