|
|
@@ -2,7 +2,7 @@ import fabric from '../PictureEditor/js/fabric-adapter'
|
|
|
import { buildRenderPlans, normalizeGoods } from './generateImagesPlan'
|
|
|
|
|
|
/**
|
|
|
- * 根据渲染计划和拍平后的货号数据,真正生成图片(dataURL),按 canvasIndex & imageIndex 返回。
|
|
|
+ * 根据渲染计划和拍平后的货号数据,真正生成图片(dataURL),按 canvasIndex 返回。
|
|
|
*
|
|
|
* 注意:
|
|
|
* - 不做任何上传,只返回 dataURL,方便在 EXE 或其他环境里落地到本地文件。
|
|
|
@@ -11,7 +11,7 @@ import { buildRenderPlans, normalizeGoods } from './generateImagesPlan'
|
|
|
* @param {Array} plans 由 buildRenderPlans 生成的渲染计划
|
|
|
* @param {Array} canvasList 画布配置数组(包含 canvas_json / width / height / bg_color 等)
|
|
|
* @param {Array} skus normalizeGoods(goodsList) 的结果
|
|
|
- * @returns {Promise<Array<{canvasIndex:number,imageIndex:number,dataUrl:string,skuIndexes:number[],skus:any[]}>>}
|
|
|
+ * @returns {Promise<Array<{canvasIndex:number,dataUrl:string}>>}
|
|
|
*/
|
|
|
export async function renderImagesByPlans(plans, canvasList, skus) {
|
|
|
const results = []
|
|
|
@@ -19,12 +19,26 @@ export async function renderImagesByPlans(plans, canvasList, skus) {
|
|
|
// 工具:从 canvas_json 创建一个离屏 fabric.Canvas,并应用一次性的渲染逻辑
|
|
|
const renderOne = (canvasItem, planForCanvas, imagePlan) =>
|
|
|
new Promise((resolve) => {
|
|
|
- if (!canvasItem || !canvasItem.canvas_json) {
|
|
|
+ if (!canvasItem) {
|
|
|
return resolve(null)
|
|
|
}
|
|
|
|
|
|
const { canvasIndex } = planForCanvas
|
|
|
- const { imageIndex, skuIndexes } = imagePlan
|
|
|
+ const { skuIndexes } = imagePlan
|
|
|
+
|
|
|
+ // 模特/场景占位:直接返回类型,不渲染
|
|
|
+ if (canvasItem.canvas_json === 'model') {
|
|
|
+ return resolve({
|
|
|
+ canvasIndex,
|
|
|
+ dataUrl: 'model',
|
|
|
+ })
|
|
|
+ }
|
|
|
+ if (canvasItem.canvas_json === 'scene') {
|
|
|
+ return resolve({
|
|
|
+ canvasIndex,
|
|
|
+ dataUrl: 'scene',
|
|
|
+ })
|
|
|
+ }
|
|
|
|
|
|
// 解析 JSON 为可修改的对象
|
|
|
let json
|
|
|
@@ -186,10 +200,7 @@ export async function renderImagesByPlans(plans, canvasList, skus) {
|
|
|
|
|
|
resolve({
|
|
|
canvasIndex,
|
|
|
- imageIndex,
|
|
|
dataUrl,
|
|
|
- skuIndexes,
|
|
|
- skus: usedSkus,
|
|
|
})
|
|
|
} catch (e) {
|
|
|
console.warn('[generateImagesRender] render one failed in callback', e)
|
|
|
@@ -227,7 +238,7 @@ export async function renderImagesByPlans(plans, canvasList, skus) {
|
|
|
* @returns {Promise<Array<{
|
|
|
* styleKey: string,
|
|
|
* styleNo: string,
|
|
|
- * images: Array<{canvasIndex:number,imageIndex:number,dataUrl:string,skuIndexes:number[],skus:any[]}>,
|
|
|
+ * images: Array<{canvasIndex:number,dataUrl:string}>,
|
|
|
* combined?: { dataUrl: string, width: number, height: number }
|
|
|
* }>>}
|
|
|
*/
|
|
|
@@ -237,10 +248,13 @@ export async function generateAllStyleImageBundles(canvasList, goodsList) {
|
|
|
// 工具:把若干 dataURL 竖向拼接为一张长图
|
|
|
const composeCombinedImage = (images) =>
|
|
|
new Promise((resolve) => {
|
|
|
- if (!images || !images.length) return resolve(null)
|
|
|
+ const validImages = (images || []).filter(
|
|
|
+ img => img && typeof img.dataUrl === 'string' && img.dataUrl.startsWith('data:image')
|
|
|
+ )
|
|
|
+ if (!validImages.length) return resolve(null)
|
|
|
|
|
|
Promise.all(
|
|
|
- images.map(img =>
|
|
|
+ validImages.map(img =>
|
|
|
new Promise(res => {
|
|
|
fabric.Image.fromURL(
|
|
|
img.dataUrl,
|
|
|
@@ -306,11 +320,8 @@ export async function generateAllStyleImageBundles(canvasList, goodsList) {
|
|
|
const images = await renderImagesByPlans(plans, canvasList, skus)
|
|
|
if (!images.length) continue
|
|
|
|
|
|
- // 按 canvasIndex、imageIndex 排序,方便后续命名和组合
|
|
|
- images.sort((a, b) => {
|
|
|
- if (a.canvasIndex !== b.canvasIndex) return a.canvasIndex - b.canvasIndex
|
|
|
- return a.imageIndex - b.imageIndex
|
|
|
- })
|
|
|
+ // 按 canvasIndex 排序,方便后续命名和组合
|
|
|
+ images.sort((a, b) => a.canvasIndex - b.canvasIndex)
|
|
|
|
|
|
// 组合所有画布图片为一张长图(可以根据需要选择只取每个画布的第一张等)
|
|
|
const combined = await composeCombinedImage(images)
|
|
|
@@ -327,4 +338,19 @@ export async function generateAllStyleImageBundles(canvasList, goodsList) {
|
|
|
return bundles
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * 轻量入口:直接给模板列表与商品数据,返回每张图的 base64。
|
|
|
+ * 不做文件落地,也不做长图拼接,便于外部(如 Python 调用)直接获取切片。
|
|
|
+ *
|
|
|
+ * @param {Array} canvasList 画布配置数组
|
|
|
+ * @param {Array} goodsList 商品数据数组
|
|
|
+ * @returns {Promise<{plans:Array, images:Array<{canvasIndex:number,dataUrl:string}>}>}
|
|
|
+ */
|
|
|
+export async function generateImagesBase64(canvasList = [], goodsList = []) {
|
|
|
+ const skus = normalizeGoods(goodsList)
|
|
|
+ const plans = buildRenderPlans(canvasList, goodsList)
|
|
|
+ const images = await renderImagesByPlans(plans, canvasList, skus)
|
|
|
+ return { images }
|
|
|
+}
|
|
|
+
|
|
|
|