Merge branch 'dev_vite' of ssh://18.167.251.121:10002/aidlab/aida_front into dev_vite

This commit is contained in:
2026-01-30 17:21:15 +08:00
25 changed files with 375 additions and 220 deletions

View File

@@ -5,4 +5,3 @@ VITE_USER_NODE_ENV = 'development'
VITE_APP_BASE_URL = 'https://develop.api.aida.com.hk' VITE_APP_BASE_URL = 'https://develop.api.aida.com.hk'
# VITE_APP_BASE_URL = 'http://localhost:22170' # VITE_APP_BASE_URL = 'http://localhost:22170'

View File

@@ -7,12 +7,11 @@ import {
insertObjectAtZIndex, insertObjectAtZIndex,
removeCanvasObjectByObject, removeCanvasObjectByObject,
createPatternTransform, createPatternTransform,
getTransformScaleAngle,
imageAddGapToCanvas, imageAddGapToCanvas,
} from "../utils/helper"; } from "../utils/helper";
import { restoreFabricObject } from "../utils/objectHelper"; import { restoreFabricObject } from "../utils/objectHelper";
const scale = 0.3;// 默认缩放比例
export const FillSourceToBase64 = (source) => { export const FillSourceToBase64 = (source) => {
if (source?.toDataURL) { if (source?.toDataURL) {
return source.toDataURL?.(); return source.toDataURL?.();
@@ -39,7 +38,6 @@ export class FillRepeatCommand extends Command {
this.fillRepeat = options.fillRepeat; this.fillRepeat = options.fillRepeat;
this.oldObjects = null; this.oldObjects = null;
this.oldLocked = null; this.oldLocked = null;
this.oldIsDisableUnlock = null;
} }
async execute() { async execute() {
@@ -64,17 +62,15 @@ export class FillRepeatCommand extends Command {
); );
}); });
image.set({ image.set({
id: object.id, ...this.copyObjectProperties(object),
layerId: object.layerId,
layerName: object.layerName,
...(fill_.originalInfo || { ...(fill_.originalInfo || {
top: object.top, top: object.top,
left: object.left, left: object.left,
}) })
}); });
layer.fabricObjects = [image.toObject(["id", "layerId", "layerName"])]; layer.fabricObjects = [image.toObject(["id", "layerId", "layerName"])];
this.oldLocked = layer.locked; // this.oldLocked = layer.locked;
layer.locked = false; // layer.locked = false;
this.canvas.add(image); this.canvas.add(image);
this.canvas.remove(object); this.canvas.remove(object);
@@ -113,23 +109,25 @@ export class FillRepeatCommand extends Command {
const fdObject = this.canvasManager.getFixedLayerObject(); const fdObject = this.canvasManager.getFixedLayerObject();
const bgObject = this.canvasManager.getBackgroundLayerObject(); const bgObject = this.canvasManager.getBackgroundLayerObject();
const tObject = fdObject || bgObject; const tObject = fdObject || bgObject;
// const offsetX = object.fill?.hasOwnProperty("offsetX") ? object.fill.offsetX : tObject.width / 2;
// const offsetY = object.fill?.hasOwnProperty("offsetY") ? object.fill.offsetY : tObject.height / 2;
const patternTransform = object.fill?.hasOwnProperty("patternTransform") ? object.fill.patternTransform : createPatternTransform(0.3, 0);
const scale = getTransformScaleAngle(patternTransform).scale;
const offsetX = tObject.width / 2 - img.width * scale / 2;
const offsetY = tObject.height / 2 - img.height * scale / 2;
const pattern = new fabric.Pattern({ const pattern = new fabric.Pattern({
source: img, source: img,
repeat: this.fillRepeat, repeat: this.fillRepeat,
patternTransform: object.fill?.hasOwnProperty("patternTransform") ? object.fill.patternTransform : createPatternTransform(scale, 0), patternTransform,
offsetX: object.fill?.hasOwnProperty("offsetX") ? object.fill.offsetX : tObject.width / 2, // 水平偏移 offsetX, // 水平偏移
offsetY: object.fill?.hasOwnProperty("offsetY") ? object.fill.offsetY : tObject.height / 2, // 垂直偏移 offsetY, // 垂直偏移
}); });
const rect = new fabric.Rect({ const rect = new fabric.Rect({
id: object.id, ...this.copyObjectProperties(object),
layerId: object.layerId,
layerName: object.layerName,
fill_, fill_,
}); });
layer.fabricObjects = [rect.toObject(["id", "layerId", "layerName"])]; layer.fabricObjects = [rect.toObject(["id", "layerId", "layerName"])];
this.oldLocked = layer.locked; // this.oldLocked = layer.locked;
// this.oldIsDisableUnlock = layer.isDisableUnlock;
// layer.isDisableUnlock = true;
if (this.oldObjects.type === "rect") { if (this.oldObjects.type === "rect") {
rect.set({ rect.set({
width: object.width, width: object.width,
@@ -155,7 +153,7 @@ export class FillRepeatCommand extends Command {
scaleX, scaleX,
scaleY, scaleY,
}); });
layer.locked = true; // layer.locked = true;
} }
rect.set("fill", pattern); rect.set("fill", pattern);
this.canvas.add(rect); this.canvas.add(rect);
@@ -184,14 +182,23 @@ export class FillRepeatCommand extends Command {
this.canvas.remove(object); this.canvas.remove(object);
this.canvas.add(this.oldObjects); this.canvas.add(this.oldObjects);
layer.fabricObjects = [this.oldObjects.toObject(["id", "layerId", "layerName"])]; layer.fabricObjects = [this.oldObjects.toObject(["id", "layerId", "layerName"])];
layer.locked = this.oldLocked; // layer.locked = this.oldLocked;
// layer.isDisableUnlock = this.oldIsDisableUnlock;
await this.layerManager?.updateLayersObjectsInteractivity(); await this.layerManager?.updateLayersObjectsInteractivity();
await this.layerManager?.sortLayersWithTool?.(); await this.layerManager?.sortLayersWithTool?.();
this.canvas.renderAll(); this.canvas.renderAll();
this.canvasManager.thumbnailManager?.generateLayerThumbnail(this.layerId); this.canvasManager.thumbnailManager?.generateLayerThumbnail(this.layerId);
return true; return true;
} }
// 复制原对象的属性
copyObjectProperties(object) {
return{
id: object.id,
layerId: object.layerId,
layerName: object.layerName,
isPrintTrims: object.isPrintTrims,
}
}
} }
@@ -230,6 +237,10 @@ export class FillRepeatChangeCommand extends Command {
...this.newPattern, ...this.newPattern,
}); });
object.set("fill", pattern); object.set("fill", pattern);
if (object.globalCompositeOperation_) {
object.globalCompositeOperation = object.globalCompositeOperation_;
object.globalCompositeOperation_ = null;
}
this.canvas.renderAll(); this.canvas.renderAll();
return true; return true;
} }
@@ -276,7 +287,7 @@ export class FillRepeatGapChangeCommand extends Command {
this.oldGapY = null; this.oldGapY = null;
} }
async execute(isUndo = false) { async execute(isCommand = true, isUndo = false) {
const { layer } = findLayerRecursively(this.layers.value, this.layerId); const { layer } = findLayerRecursively(this.layers.value, this.layerId);
if (!layer || !layer.fabricObjects || layer.fabricObjects.length === 0) { if (!layer || !layer.fabricObjects || layer.fabricObjects.length === 0) {
console.warn("图层不存在或没有 fabric 对象"); console.warn("图层不存在或没有 fabric 对象");
@@ -315,6 +326,10 @@ export class FillRepeatGapChangeCommand extends Command {
const fill = object.get("fill"); const fill = object.get("fill");
fill.source = imageAddGapToCanvas(image, object.fill_.gapX, object.fill_.gapY); fill.source = imageAddGapToCanvas(image, object.fill_.gapX, object.fill_.gapY);
object.set("fill", new fabric.Pattern(fill)); object.set("fill", new fabric.Pattern(fill));
if (isCommand && object.globalCompositeOperation_) {
object.globalCompositeOperation = object.globalCompositeOperation_;
object.globalCompositeOperation_ = null;
}
this.canvas.renderAll(); this.canvas.renderAll();
return true; return true;
} }
@@ -324,7 +339,7 @@ export class FillRepeatGapChangeCommand extends Command {
console.warn("没有旧间隙可恢复"); console.warn("没有旧间隙可恢复");
return false; return false;
} }
await this.execute(true); await this.execute(true, true);
return true; return true;
} }

View File

@@ -280,8 +280,13 @@ export class PasteLayerCommand extends Command {
isCut: undefined, isCut: undefined,
serializedObjects: undefined, serializedObjects: undefined,
}; };
if(this.newLayer.isPrintTrims){
if (this.insertIndex !== undefined && this.insertIndex !== null) { this.layers.value.forEach((layer) => {
if (layer.isPrintTrimsGroup) {
layer.children.push(this.newLayer);
}
})
}else if (this.insertIndex !== undefined && this.insertIndex !== null) {
this.layers.value.splice(this.insertIndex, 0, this.newLayer); this.layers.value.splice(this.insertIndex, 0, this.newLayer);
} else { } else {
this.layers.value.push(this.newLayer); this.layers.value.push(this.newLayer);

View File

@@ -25,7 +25,7 @@ export class TransformCommand extends Command {
this.layerManager = options.layerManager; this.layerManager = options.layerManager;
this.layers = options.layers || null; this.layers = options.layers || null;
this.lastSelectLayerId = options.lastSelectLayerId || null; // 最后选择的图层ID this.lastSelectLayerId = options.lastSelectLayerId || null; // 最后选择的图层ID
this.isCommand = options.isCommand == undefined ? true : options.isCommand
const targetObject = const targetObject =
findObjectById(this.canvas, this.objectId)?.object || null; findObjectById(this.canvas, this.objectId)?.object || null;
@@ -189,6 +189,11 @@ export class TransformCommand extends Command {
object.set(key, value); object.set(key, value);
}); });
if(this.isCommand && object.globalCompositeOperation_){
object.globalCompositeOperation = object.globalCompositeOperation_;
object.globalCompositeOperation_ = null;
}
// 确保对象更新 // 确保对象更新
object.setCoords(); object.setCoords();
} }

View File

@@ -132,8 +132,8 @@
const offsetY = object.fill?.offsetY; const offsetY = object.fill?.offsetY;
const twidth = object.fill_?.width; const twidth = object.fill_?.width;
const theight = object.fill_?.height; const theight = object.fill_?.height;
const x = ((offsetX - (twidth * scale) / 2) * 100) / object.width; const x = ((offsetX + (twidth * scale) / 2) * 100) / object.width;
const y = ((offsetY - (theight * scale) / 2) * 100) / object.height; const y = ((offsetY + (theight * scale) / 2) * 100) / object.height;
return { x, y }; return { x, y };
}); });
const inputFillOffset = (e) => setFillOffset(e, true); const inputFillOffset = (e) => setFillOffset(e, true);
@@ -143,8 +143,8 @@
const object = props.object; const object = props.object;
const patternTransform = object.fill?.patternTransform; const patternTransform = object.fill?.patternTransform;
const scale = getTransformScaleAngle(patternTransform).scale; const scale = getTransformScaleAngle(patternTransform).scale;
const x = (left / 100) * object.width + (object.fill_?.width * scale) / 2; const x = (left / 100) * object.width - (object.fill_?.width * scale) / 2;
const y = (top / 100) * object.height + (object.fill_?.height * scale) / 2; const y = (top / 100) * object.height - (object.fill_?.height * scale) / 2;
emit(isInput ? "inputFillOffset" : "changeFillOffset", { x, y }); emit(isInput ? "inputFillOffset" : "changeFillOffset", { x, y });
}; };
</script> </script>

View File

@@ -315,6 +315,7 @@
layerManager: props.layerManager, layerManager: props.layerManager,
layers: layers, layers: layers,
lastSelectLayerId: lastSelectLayerId, lastSelectLayerId: lastSelectLayerId,
isCommand,
}); });
if (isCommand) { if (isCommand) {
props.commandManager.execute(cmd); props.commandManager.execute(cmd);
@@ -336,6 +337,7 @@
const finalState = computeAngleState(angle, obj, initialState); const finalState = computeAngleState(angle, obj, initialState);
transformObject(obj, initialState, finalState, false); transformObject(obj, initialState, finalState, false);
if (!obj.hasOwnProperty("oldState")) obj.oldState = initialState; if (!obj.hasOwnProperty("oldState")) obj.oldState = initialState;
props.canvasManager.beforeChangeCanvas([obj]);
}; };
const changeAngle = (angle, obj) => { const changeAngle = (angle, obj) => {
var initialState; var initialState;
@@ -428,6 +430,7 @@
}); });
obj.set("fill", pattern); obj.set("fill", pattern);
props.canvas.renderAll(); props.canvas.renderAll();
props.canvasManager.beforeChangeCanvas([obj]);
}; };
const changeFillAngle = (angle, obj) => { const changeFillAngle = (angle, obj) => {
const fill = obj.get("fill"); const fill = obj.get("fill");
@@ -447,6 +450,7 @@
}); });
obj.set("fill", pattern); obj.set("fill", pattern);
props.canvas.renderAll(); props.canvas.renderAll();
props.canvasManager.beforeChangeCanvas([obj]);
}; };
const changeFillOffset = (value, obj) => { const changeFillOffset = (value, obj) => {
const pattern = new fabric.Pattern({ const pattern = new fabric.Pattern({
@@ -466,6 +470,7 @@
}); });
obj.set("fill", pattern); obj.set("fill", pattern);
props.canvas.renderAll(); props.canvas.renderAll();
props.canvasManager.beforeChangeCanvas([obj]);
}; };
const changeFillScale = (scale, obj) => { const changeFillScale = (scale, obj) => {
const fill = obj.get("fill"); const fill = obj.get("fill");
@@ -498,7 +503,8 @@
newGapY: gapY, newGapY: gapY,
record: true, record: true,
}); });
cmd.execute(); cmd.execute(false);
props.canvasManager.beforeChangeCanvas([obj]);
}; };
const changeFillGap = (gapX, gapY, obj) => { const changeFillGap = (gapX, gapY, obj) => {
if (obj.oldFill_) { if (obj.oldFill_) {

View File

@@ -896,7 +896,7 @@ const changeCanvas = async (command) => {
...command, // 传递完整的命令数据 ...command, // 传递完整的命令数据
}; };
emit("changeCanvas", commandData); emit("changeCanvas", commandData);
canvasManager.changeCanvas(commandData); canvasManager.changeCanvas();
if ((command.canUndo || command.canRedo) && props.enabledRedGreenMode) { if ((command.canUndo || command.canRedo) && props.enabledRedGreenMode) {
setTimeout(async () => { setTimeout(async () => {
try { try {

View File

@@ -74,6 +74,7 @@ export class CanvasManager {
this.props = options.props || {}; this.props = options.props || {};
this.emit = options.emit || (() => {}); this.emit = options.emit || (() => {});
this.awaitCanvasRun = null; this.awaitCanvasRun = null;
this.canvasChangeing = false;
// 初始化画布 // 初始化画布
this.initializeCanvas(); this.initializeCanvas();
} }
@@ -338,6 +339,7 @@ export class CanvasManager {
setupCanvasEvents(activeElementId, layerManager) { setupCanvasEvents(activeElementId, layerManager) {
// 创建画布事件管理器 // 创建画布事件管理器
this.eventManager = new CanvasEventManager(this.canvas, { this.eventManager = new CanvasEventManager(this.canvas, {
canvasManager: this,
toolManager: this.toolManager, toolManager: this.toolManager,
animationManager: this.animationManager, animationManager: this.animationManager,
thumbnailManager: this.thumbnailManager, thumbnailManager: this.thumbnailManager,
@@ -868,9 +870,9 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
return layerObjectByLayerId; return layerObjectByLayerId;
} }
getObjectsByIds(ids){ getObjectsByIdOrLayerId(ids){
const objects = this.canvas.getObjects().filter((obj) => { const objects = this.canvas.getObjects().filter((obj) => {
return ids.includes(obj.id); return ids.includes(obj.id) || ids.includes(obj.layerId);
}); });
return objects; return objects;
} }
@@ -1147,7 +1149,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
const glayer = this.layerManager.getLayerById(SpecialLayerId.SPECIAL_GROUP); const glayer = this.layerManager.getLayerById(SpecialLayerId.SPECIAL_GROUP);
if(!glayer) return Promise.reject("印花和元素图层组不存在"); if(!glayer) return Promise.reject("印花和元素图层组不存在");
const ids = glayer.children.map((v) => v.id); const ids = glayer.children.map((v) => v.id);
const objects = this.getObjectsByIds(ids); const objects = this.getObjectsByIdOrLayerId(ids);
const fixedLayerObj = this.getFixedLayerObject(); const fixedLayerObj = this.getFixedLayerObject();
if(!fixedLayerObj) return Promise.reject("固定图层不存在"); if(!fixedLayerObj) return Promise.reject("固定图层不存在");
const flWidth = fixedLayerObj.width const flWidth = fixedLayerObj.width
@@ -1159,7 +1161,8 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
const prints = []; const prints = [];
const trims = []; const trims = [];
objects.forEach((v) => { objects.forEach((v) => {
const sourceData = glayer.children.find((v_) => v_.id === v.id)?.metadata?.sourceData; const label = glayer.children.find((v_) => (v_.id === v.layerId || v_.id === v.id));
const sourceData = label?.metadata?.sourceData;
if(!sourceData) return; if(!sourceData) return;
const obj = { const obj = {
ifSingle: typeof v.fill === "string", ifSingle: typeof v.fill === "string",
@@ -1220,8 +1223,8 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
let scaleY = scale * 5 * v.fill_.height / flHeight; let scaleY = scale * 5 * v.fill_.height / flHeight;
let scaleXY = flWidth > flHeight ? scaleX : scaleY; let scaleXY = flWidth > flHeight ? scaleX : scaleY;
let left = fill.offsetX - v.fill_.width * scale / 2; let left = fill.offsetX + v.fill_.width * scale / 2;
let top = fill.offsetY - v.fill_.height * scale / 2; let top = fill.offsetY + v.fill_.height * scale / 2;
obj.scale = [scaleXY, scaleXY]; obj.scale = [scaleXY, scaleXY];
obj.angle = angle; obj.angle = angle;
@@ -1465,9 +1468,12 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
} }
/** 修复JSON数据中的ID丢失问题 */ /** 修复JSON数据中的ID丢失问题 */
FixJsonIdLoss(json){ FixJsonIdLoss(json){
const layerIds = [];
const layers = json?.layers || []; const layers = json?.layers || [];
const objects = json?.canvas?.objects || []; const objects = json?.canvas?.objects || [];
layers.forEach((layer) => { layers.forEach((layer) => {
layerIds.push(layer.id);
layer.children?.forEach((child) => layerIds.push(child.id));
if(!layer.fabricObjects?.[0]?.id && !layer.fabricObject?.id){ if(!layer.fabricObjects?.[0]?.id && !layer.fabricObject?.id){
const obj = objects?.find((o) => o.layerId === layer.id); const obj = objects?.find((o) => o.layerId === layer.id);
if(obj) { if(obj) {
@@ -1483,6 +1489,17 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
if (a.isBackground) return -1; if (a.isBackground) return -1;
if (b.isBackground) return 1; if (b.isBackground) return 1;
}) })
// 排除的对象id
const excludedObjects = [SpecialLayerId.PART_SELECTOR];
json.canvas.objects = objects.filter((v) => {
// 指定ID排除
if(excludedObjects.includes(v.id)) return false;
if(v.isBackground || v.isFixed) return true;
// 当前图层不存在当前对象
if(!layerIds.includes(v.layerId)) return false;
return true
});
} }
@@ -1670,7 +1687,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
let flipX = false; let flipX = false;
let flipY = false; let flipY = false;
let blendMode = BlendMode.MULTIPLY; let blendMode = BlendMode.MULTIPLY;
if(item.type === "trims") blendMode = BlendMode.NORMAL;// 元素正常 // if(item.type === "trims") blendMode = BlendMode.NORMAL;// 元素正常
if(item.object){ if(item.object){
opacity = item.object.opacity opacity = item.object.opacity
flipX = item.object.flipX flipX = item.object.flipX
@@ -1730,8 +1747,8 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
let scaleX_ = flWidth / image.width * (item.scale?.[0] || 1) / 5; let scaleX_ = flWidth / image.width * (item.scale?.[0] || 1) / 5;
let scaleY_ = flHeight / image.height * (item.scale?.[1] || 1) / 5; let scaleY_ = flHeight / image.height * (item.scale?.[1] || 1) / 5;
let scale = flWidth > flHeight ? scaleX_ : scaleY_; let scale = flWidth > flHeight ? scaleX_ : scaleY_;
let offsetX = (item.location?.[0] || 0) + image.width * scale / 2 let offsetX = (item.location?.[0] || 0) - image.width * scale / 2
let offsetY = (item.location?.[1] || 0) + image.height * scale / 2 let offsetY = (item.location?.[1] || 0) - image.height * scale / 2
let top = flTop - flHeight * flScaleY / 2 let top = flTop - flHeight * flScaleY / 2
let left = flLeft - flWidth * flScaleX / 2 let left = flLeft - flWidth * flScaleX / 2
let scaleX = flScaleX let scaleX = flScaleX
@@ -1743,7 +1760,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
let fillSource = image let fillSource = image
let flipX = false; let flipX = false;
let flipY = false; let flipY = false;
let blendMode = BlendMode.MULTIPLY; let blendMode = BlendMode.NORMAL;
let fill_repeat = "repeat" let fill_repeat = "repeat"
if(item.object){ if(item.object){
top += item.object.top * flScaleY top += item.object.top * flScaleY
@@ -1754,7 +1771,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
angle = item.object.angle angle = item.object.angle
flipX = item.object.flipX flipX = item.object.flipX
flipY = item.object.flipY flipY = item.object.flipY
blendMode = item.object.blendMode || BlendMode.MULTIPLY; if(item.object.blendMode) blendMode = item.object.blendMode;
gapX = item.object.gapX gapX = item.object.gapX
gapY = item.object.gapY gapY = item.object.gapY
fillSource = imageAddGapToCanvas(image, gapX, gapY); fillSource = imageAddGapToCanvas(image, gapX, gapY);
@@ -1797,10 +1814,10 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
name: name, name: name,
type: LayerType.BITMAP, type: LayerType.BITMAP,
visible: true, visible: true,
locked: true, locked: false,
opacity: opacity, opacity: opacity,
isPrintTrims: true, isPrintTrims: true,
blendMode: BlendMode.MULTIPLY, blendMode: blendMode,
fabricObjects: [rect.toObject(["id", "layerId", "layerName"])], fabricObjects: [rect.toObject(["id", "layerId", "layerName"])],
metadata: {sourceData: item}, metadata: {sourceData: item},
}) })
@@ -1841,12 +1858,13 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
/** /**
* 画布事件变更后 * 画布事件变更后
*/ */
async changeCanvas(){ async changeCanvas(fids = [], isBeforeChange = false){
if(!isBeforeChange) this.canvasChangeing = false;
const fixedLayerObj = this.getFixedLayerObject(); const fixedLayerObj = this.getFixedLayerObject();
if(!fixedLayerObj) return console.warn("固定图层对象不存在", fixedLayerObj) if(!fixedLayerObj) return console.warn("固定图层对象不存在", fixedLayerObj)
const colorObject = this.getLayerObjectById(SpecialLayerId.COLOR); const colorObject = this.getLayerObjectById(SpecialLayerId.COLOR);
if(colorObject){ if(colorObject){
const ids = this.layerManager.getBlendModeLayerIds(SpecialLayerId.SPECIAL_GROUP); const ids = this.layerManager.getBlendModeLayerIds(SpecialLayerId.SPECIAL_GROUP).filter(id => !fids.includes(id));
if(ids.length === 0){ if(ids.length === 0){
ids.unshift(SpecialLayerId.SPECIAL_GROUP); ids.unshift(SpecialLayerId.SPECIAL_GROUP);
await this.setObjecCliptInfo(colorObject); await this.setObjecCliptInfo(colorObject);
@@ -1866,6 +1884,24 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer')
this.canvas.renderAll(); this.canvas.renderAll();
} }
} }
/** 画布变更之前 */
async beforeChangeCanvas(objects){
if(this.canvasChangeing) return;
const ids = objects.filter(v => {
return v.isPrintTrims && v.globalCompositeOperation && v.globalCompositeOperation !== BlendMode.NORMAL
}).map(v => v.layerId);
if(ids.length > 0){
this.canvasChangeing = true;
this.canvas.getObjects().forEach(v => {
if(ids.includes(v.layerId)){
v.globalCompositeOperation_ = v.globalCompositeOperation;
v.globalCompositeOperation = BlendMode.NORMAL;
}
})
this.canvas.renderAll();
await this.changeCanvas(ids, true);
}
}
/** /**
* 缩放红绿图模式内容以适应当前画布大小 * 缩放红绿图模式内容以适应当前画布大小

View File

@@ -1750,7 +1750,7 @@ export class LayerManager {
layer.serializedObjects = layer.fabricObjects layer.serializedObjects = layer.fabricObjects
.map((obj) => { .map((obj) => {
if (typeof obj.toObject === "function") { if (typeof obj.toObject === "function") {
return obj.toObject(["id", "layerId", "layerName"]); return obj.toObject(["id", "layerId", "layerName", "fill_"]);
} }
return null; return null;
}) })
@@ -1763,7 +1763,7 @@ export class LayerManager {
if (layer.fabricObject) { if (layer.fabricObject) {
layer.serializedBackgroundObject = layer.serializedBackgroundObject =
typeof layer.fabricObject.toObject === "function" typeof layer.fabricObject.toObject === "function"
? layer.fabricObject.toObject(["id", "layerId", "layerName"]) ? layer.fabricObject.toObject(["id", "layerId", "layerName", "fill_"])
: null; : null;
delete layer.fabricObject; delete layer.fabricObject;
@@ -1793,7 +1793,7 @@ export class LayerManager {
return layer.fabricObjects return layer.fabricObjects
.map((obj) => { .map((obj) => {
const { object } = findObjectById(this.canvas, obj.id); const { object } = findObjectById(this.canvas, obj.id);
if (object) return object.toObject(["id", "layerId", "layerName"]); if (object) return object.toObject(["id", "layerId", "layerName", "fill_"]);
return false; return false;
}) })
.filter(Boolean); .filter(Boolean);
@@ -1839,6 +1839,7 @@ export class LayerManager {
// 存储到剪贴板 // 存储到剪贴板
this.clipboardData = layerCopy; this.clipboardData = layerCopy;
console.log("复制图层:", layerCopy);
const input = document.createElement("input"); const input = document.createElement("input");
input.value = "aida_copy_canvas_layer: " + layer.name; input.value = "aida_copy_canvas_layer: " + layer.name;
document.body.appendChild(input); document.body.appendChild(input);
@@ -1884,7 +1885,7 @@ export class LayerManager {
layerCopy.serializedObjects = layer.fabricObjects layerCopy.serializedObjects = layer.fabricObjects
.map((obj) => .map((obj) =>
typeof obj.toObject === "function" typeof obj.toObject === "function"
? obj.toObject(["id", "layerId", "layerName"]) ? obj.toObject(["id", "layerId", "layerName", "fill_"])
: null : null
) )
.filter(Boolean); .filter(Boolean);
@@ -1935,10 +1936,6 @@ export class LayerManager {
return this.clipboardData; return this.clipboardData;
} }
/**
* 粘贴图层
* @returns {string} 新创建的图层ID
*/
/** /**
* 粘贴图层 * 粘贴图层
* @returns {string} 新创建的图层ID * @returns {string} 新创建的图层ID

View File

@@ -1,6 +1,6 @@
import { fabric } from "fabric-with-all"; import { fabric } from "fabric-with-all";
import { traceImageContour, imageToCanvas } from "../utils/helper"; import { traceImageContour, imageToCanvas } from "../utils/helper";
import { OperationType } from "../utils/layerHelper"; import { OperationType, SpecialLayerId } from "../utils/layerHelper";
import { LassoCutoutCommand } from "../commands/LassoCutoutCommand"; import { LassoCutoutCommand } from "../commands/LassoCutoutCommand";
import addIcon from "@/assets/images/canvas/add.png"; import addIcon from "@/assets/images/canvas/add.png";
import removeIcon from "@/assets/images/canvas/remove.png"; import removeIcon from "@/assets/images/canvas/remove.png";
@@ -72,7 +72,7 @@ export class PartManager {
this.activeTool = this.toolManager.activeTool; this.activeTool = this.toolManager.activeTool;
this.rgba = { r: 0, g: 255, b: 0, a: 200 }; this.rgba = { r: 0, g: 255, b: 0, a: 200 };
this.partId = "part_selector"; this.partId = SpecialLayerId.PART_SELECTOR;
this.partGroup = null; // 当前选区对象 this.partGroup = null; // 当前选区对象
this.partCanvas = null;// 选区画布 this.partCanvas = null;// 选区画布
this.rectangleObject = null; // 矩形对象 this.rectangleObject = null; // 矩形对象

View File

@@ -6,6 +6,7 @@ import { OperationType, OperationTypes } from "../../utils/layerHelper";
export class CanvasEventManager { export class CanvasEventManager {
constructor(canvas, options = {}) { constructor(canvas, options = {}) {
this.canvas = canvas; this.canvas = canvas;
this.canvasManager = options.canvasManager;
this.toolManager = options.toolManager || null; this.toolManager = options.toolManager || null;
this.animationManager = options.animationManager; this.animationManager = options.animationManager;
this.thumbnailManager = options.thumbnailManager; this.thumbnailManager = options.thumbnailManager;
@@ -691,7 +692,9 @@ export class CanvasEventManager {
// 清除临时状态记录 // 清除临时状态记录
delete activeObj._initialTransformState; delete activeObj._initialTransformState;
} }
} }else{
this.canvasManager.changeCanvas();
}
if (this.thumbnailManager && e.target) { if (this.thumbnailManager && e.target) {
if (e.target.id) { if (e.target.id) {
@@ -975,6 +978,13 @@ export class CanvasEventManager {
// 添加调试日志(可选) // 添加调试日志(可选)
// console.log(`捕获对象 ${obj.id} (${obj.type}) 的初始变换状态`); // console.log(`捕获对象 ${obj.id} (${obj.type}) 的初始变换状态`);
} }
const arrs = [];
if (e.target._objects) {
e.target._objects.forEach((v) => arrs.push(v));
} else {
arrs.push(e.target);
}
this.canvasManager.beforeChangeCanvas(arrs);
} }
/** /**

View File

@@ -24,6 +24,7 @@ export const LayerType = {
export const SpecialLayerId = { export const SpecialLayerId = {
SPECIAL_GROUP: "group_special", // 特殊组 SPECIAL_GROUP: "group_special", // 特殊组
COLOR: "special_color", // 颜色图层 COLOR: "special_color", // 颜色图层
PART_SELECTOR: "part_selector", // 部件选择器图层
} }

View File

@@ -203,9 +203,9 @@
let scaleY = ((cheight / image.height) * item.scale[1]) / 5; let scaleY = ((cheight / image.height) * item.scale[1]) / 5;
let scale = cwidth > cheight ? scaleX : scaleY; let scale = cwidth > cheight ? scaleX : scaleY;
let offsetX = let offsetX =
(item.location[0] * cwidth) / props.width + (image.width * scale) / 2; (item.location[0] * cwidth) / props.width - (image.width * scale) / 2;
let offsetY = let offsetY =
(item.location[1] * cheight) / props.height + (item.location[1] * cheight) / props.height -
(image.height * scale) / 2; (image.height * scale) / 2;
let angle = item.angle; let angle = item.angle;
let gapX = item.object.gapX; let gapX = item.object.gapX;

View File

@@ -337,28 +337,28 @@
color: { rgba: { r: 255, g: 0, b: 0, a: 1 } }, color: { rgba: { r: 255, g: 0, b: 0, a: 1 } },
printObject: { printObject: {
prints: [ prints: [
{ // {
ifSingle: false, // ifSingle: false,
level2Type: "Pattern", // level2Type: "Pattern",
designType: "Library", // designType: "Library",
path: "/src/assets/images/canvas/yinhua1.jpg", // path: "/src/assets/images/canvas/yinhua1.jpg",
location: [250, 780], // location: [800, 600],
scale: [1.2, 1.6], // scale: [1, 1],
angle: 0, // angle: 0,
object: { // object: {
top: 600, // top: 300,
left: 800, // left: 400,
scaleX: 0.5, // scaleX: 0.5,
scaleY: 0.5, // scaleY: 0.5,
opacity: 1, // opacity: 1,
angle: 45, // angle: 0,
flipX: false, // flipX: false,
flipY: false, // flipY: false,
blendMode: "multiply", // blendMode: "multiply",
gapX: 0, // gapX: 0,
gapY: 0, // gapY: 0,
}, // },
}, // },
// { // {
// ifSingle: true, // ifSingle: true,
// level2Type: "Pattern", // level2Type: "Pattern",
@@ -368,15 +368,15 @@
// scale: [0.15, 0.2], // scale: [0.15, 0.2],
// angle: 0, // angle: 0,
// }, // },
// { {
// ifSingle: true, ifSingle: true,
// level2Type: "Pattern", level2Type: "Pattern",
// designType: "Library", designType: "Library",
// path: "/src/assets/images/canvas/yinhua1.jpg", path: "/src/assets/images/canvas/yinhua1.jpg",
// location: [700, 400], location: [700, 400],
// scale: [0.1, 0.133], scale: [0.1, 0.133],
// angle: 0, angle: 0,
// }, },
], ],
}, },
}); });
@@ -411,6 +411,7 @@
:clothingMinIOPath="clothingMinIOPath" :clothingMinIOPath="clothingMinIOPath"
:clothingImageUrl="clothingImageUrl" :clothingImageUrl="clothingImageUrl"
:clothingImageUrl2="clothingImageUrlInit" :clothingImageUrl2="clothingImageUrlInit"
@canvasLoadJsonSuccess="canvasLoadJsonSuccess"
:config="editorConfig" :config="editorConfig"
:clothing-image-opts="{ :clothing-image-opts="{
imageMode: 'contains', // 设置底图包含在画布内 imageMode: 'contains', // 设置底图包含在画布内

View File

@@ -331,6 +331,7 @@ export default defineComponent({
store.commit('DesignDetail/setCurrentDetailType',str) store.commit('DesignDetail/setCurrentDetailType',str)
} }
const setClothes = async (list:any,str:string)=>{ const setClothes = async (list:any,str:string)=>{
console.log(JSON.parse(JSON.stringify(list)))
let clothesList:any = [] let clothesList:any = []
if(detailData.isEditPattern.value == 'editSketch')await detailDom.canvasBox.submitBase64Data().then((rv)=>{ if(detailData.isEditPattern.value == 'editSketch')await detailDom.canvasBox.submitBase64Data().then((rv)=>{
detailData.selectDetail.sketchString = rv detailData.selectDetail.sketchString = rv
@@ -368,10 +369,17 @@ export default defineComponent({
// }else if(isCurrent){ // }else if(isCurrent){
// } // }
console.log(JSON.parse(JSON.stringify(detailData.selectDetail.color)),'=====')
color = list[i].color?.rgba?.r != null?`${list[i].color.rgba.r} ${list[i].color.rgba.g} ${list[i].color.rgba.b}`:'' color = list[i].color?.rgba?.r != null?`${list[i].color.rgba.r} ${list[i].color.rgba.g} ${list[i].color.rgba.b}`:''
gradient = list[i].gradient gradient = list[i].gradient
if((detailData.currentDetailType == 'sketch' && newData?.sketch) || detailData.isEditPattern.value == 'editSketch'){ if((detailData.currentDetailType == 'sketch' && newData?.sketch) || detailData.isEditPattern.value == 'editSketch'){
color = detailData.designDetail.clothes?.[0]?.color?.rgba?.r?`${detailData.designDetail.clothes?.[0].color.rgba.r} ${detailData.designDetail.clothes[0].color.rgba.g} ${detailData.designDetail.clothes[0].color.rgba.b}`:'' if(detailData.isEditPattern.value == 'editSketch'){
color = detailData.selectDetail?.color?.rgba?.r != null?`${detailData.selectDetail.color.rgba.r} ${detailData.selectDetail.color.rgba.g} ${detailData.selectDetail.color.rgba.b}`:''
gradient = detailData.selectDetail?.gradient || null
}else{
color = detailData.designDetail.clothes?.[0]?.color?.rgba?.r?`${detailData.designDetail.clothes?.[0].color.rgba.r} ${detailData.designDetail.clothes[0].color.rgba.g} ${detailData.designDetail.clothes[0].color.rgba.b}`:''
gradient = detailData.designDetail.clothes?.[0]?.gradient || null
}
detailData.selectDetail.maskUrl = '' detailData.selectDetail.maskUrl = ''
detailData.selectDetail.maskMinioUrl = '' detailData.selectDetail.maskMinioUrl = ''
} }
@@ -547,6 +555,7 @@ export default defineComponent({
if((detailData.currentDetailType == 'models' && !detailData.isEditPattern.value) || (detailData.currentDetailType == 'sketch' && !detailData.isEditPattern.value) || detailData.isEditPattern.value == 'editSketch'){ if((detailData.currentDetailType == 'models' && !detailData.isEditPattern.value) || (detailData.currentDetailType == 'sketch' && !detailData.isEditPattern.value) || detailData.isEditPattern.value == 'editSketch'){
await getSubmitData('preview') await getSubmitData('preview')
if(detailData.currentDetailType == 'models')return detailData.loadingShow = false if(detailData.currentDetailType == 'models')return detailData.loadingShow = false
detailData.imgDomIndex = detailData.frontBack.front.findIndex((item:any)=>item.id == detailData.selectDetail.id)
await getSketchSize() await getSketchSize()
detailDom.canvasBox.changeSketchUpdateFrontBack = async ()=>{ detailDom.canvasBox.changeSketchUpdateFrontBack = async ()=>{
await detailDom.canvasBox.privewDetail() await detailDom.canvasBox.privewDetail()
@@ -581,9 +590,9 @@ export default defineComponent({
let front = detailData.frontBack.front[detailData.imgDomIndex] let front = detailData.frontBack.front[detailData.imgDomIndex]
let back = detailData.frontBack.back[detailData.imgDomIndex] let back = detailData.frontBack.back[detailData.imgDomIndex]
front.oldImageUrl = '' if(front?.oldImageUrl)front.oldImageUrl = ''
front.oldMaskUrl = '' if(front?.oldMaskUrl)front.oldMaskUrl = ''
back.oldImageUrl = '' if(back?.oldImageUrl)back.oldImageUrl = ''
front.imageUrl = rv.targetFrontUrl front.imageUrl = rv.targetFrontUrl
back.imageUrl = rv.targetBackUrl back.imageUrl = rv.targetBackUrl
store.commit('DesignDetail/canvasPreviewUpdata',{type:detailData.isEditPattern.value?'all':detailData.currentDetailType,callBack:setRevocation}) store.commit('DesignDetail/canvasPreviewUpdata',{type:detailData.isEditPattern.value?'all':detailData.currentDetailType,callBack:setRevocation})
@@ -678,7 +687,7 @@ export default defineComponent({
let color = detailData.selectDetail.newDetail?.color let color = detailData.selectDetail.newDetail?.color
// let colorData:any = await getColorName(color?.rgba) // let colorData:any = await getColorName(color?.rgba)
if(detailData.selectDetail.newDetail?.color){ if(detailData.selectDetail.newDetail?.color){
if(color.r){ if(color.r != null){
color.rgba = {r:color.r,g:color.g,b:color.b,a:color.a} color.rgba = {r:color.r,g:color.g,b:color.b,a:color.a}
}else{ }else{
color.rgba = {} color.rgba = {}
@@ -771,7 +780,6 @@ export default defineComponent({
if(canvasColor?.gradient){ if(canvasColor?.gradient){
color.gradient = canvasColor.gradient color.gradient = canvasColor.gradient
} }
console.log(color,'color')
} }
if(detailData.isEditPattern.value == 'canvasEditor'){ if(detailData.isEditPattern.value == 'canvasEditor'){

View File

@@ -11,7 +11,7 @@
@canvasInit="editSketchCanvasInit" @canvasInit="editSketchCanvasInit"
is-edit is-edit
:clothingImageUrl="selectDetail.path" :clothingImageUrl="selectDetail.path"
:clothingImageUrl2="selectDetail.layersObject[0].maskUrl" :clothingImageUrl2="selectDetail.maskUrl || selectDetail.layersObject[0].maskUrl"
:clothingMinIOPath="selectDetail.minIOPath" :clothingMinIOPath="selectDetail.minIOPath"
showFixedLayer showFixedLayer
:canvasJSON="canvasJSON" :canvasJSON="canvasJSON"
@@ -245,8 +245,11 @@ export default defineComponent({
} }
const frontBackChange = (value:any)=>{ const frontBackChange = async (value:any)=>{
let full = detailData.selectDetail.partialDesign.partialDesignBase64 || detailData.selectDetail.path if(!detailData.selectDetail.partialDesign.partialDesignPath && !detailData.selectDetail.partialDesign.partialDesignBase64){
await privewDetail()
}
let full = detailData.selectDetail.partialDesign.partialDesignBase64 || detailData.selectDetail.partialDesign.partialDesignPath || detailData.selectDetail.path
let size = { let size = {
...detailData.canvasConfig, ...detailData.canvasConfig,
} }

View File

@@ -101,7 +101,6 @@ export default defineComponent({
}) })
watch(()=>colorData.selectColor,async (newVal,oldVal)=>{ watch(()=>colorData.selectColor,async (newVal,oldVal)=>{
if((newVal.rgba && newVal.rgba?.r != null) || newVal.gradient != null){ if((newVal.rgba && newVal.rgba?.r != null) || newVal.gradient != null){
console.log('=======',123)
let data :any = {} let data :any = {}
if(newVal.rgba?.r != null){ if(newVal.rgba?.r != null){
data = await getColorName(newVal.rgba) data = await getColorName(newVal.rgba)
@@ -119,7 +118,6 @@ export default defineComponent({
} }
store.commit('DesignDetail/setNewDetail',value) store.commit('DesignDetail/setNewDetail',value)
}else{ }else{
console.log('=======',123)
let value = { let value = {
data:{}, data:{},
str:'color' str:'color'
@@ -144,14 +142,13 @@ export default defineComponent({
let color = colorData.allBoardData.colorBoards?.[index] let color = colorData.allBoardData.colorBoards?.[index]
if(!color?.rgba && color?.rgbValue)color.rgba = color.rgbValue if(!color?.rgba && color?.rgbValue)color.rgba = color.rgbValue
if( if(
(colorData.allBoardData.colorBoards?.[index] && (colorData.allBoardData.colorBoards?.[index] && color?.rgba &&
colorData.selectDetail.color.rgba?.r == color?.rgba?.r && colorData.selectDetail.color.rgba?.r == color?.rgba?.r &&
colorData.selectDetail.color.rgba?.g == color?.rgba?.g && colorData.selectDetail.color.rgba?.g == color?.rgba?.g &&
colorData.selectDetail.color.rgba?.b == color?.rgba?.b) || colorData.selectDetail.color.rgba?.b == color?.rgba?.b) ||
(JSON.stringify(colorData.selectDetail.color.gradient) == JSON.stringify(color?.gradient) && colorData.selectDetail.color.gradient) ((JSON.stringify(colorData.selectDetail.color.gradient) == JSON.stringify(color?.gradient) && colorData.selectDetail.color.gradient))
){ ){
isNoSelect = true isNoSelect = true
console.log('=======',123)
colorData.selectColor = item colorData.selectColor = item
colorData.colorList.index = index colorData.colorList.index = index
}else if(color?.rgba?.r){ }else if(color?.rgba?.r){
@@ -175,7 +172,6 @@ export default defineComponent({
} }
colorData.colorList.list[newVal].push(item) colorData.colorList.list[newVal].push(item)
} }
console.log('=======',isNoSelect)
if(!isNoSelect){ if(!isNoSelect){
let color = colorData.selectDetail.newDetail?.color?.rgba?.r != null?colorData.selectDetail.newDetail?.color:colorData.selectDetail.color let color = colorData.selectDetail.newDetail?.color?.rgba?.r != null?colorData.selectDetail.newDetail?.color:colorData.selectDetail.color
let item:any = {} let item:any = {}

View File

@@ -372,7 +372,8 @@ export default defineComponent({
angle: 0, angle: 0,
flipX: false, flipX: false,
flipY: false, flipY: false,
blendMode: "multiply", // blendMode: "multiply",
blendMode: "source-over",
gapX: 0, gapX: 0,
gapY: 0, gapY: 0,
} }

View File

@@ -189,17 +189,25 @@ export default defineComponent({
left: 0, left: 0,
top: 0, top: 0,
} }
let startSize = {//记录初始缩放比例
width: 0,
height: 0,
}
moveableInstance.value.on('scaleStart', ({ target, direction }) => { moveableInstance.value.on('scaleStart', ({ target, direction }) => {
const frontStyle = detailData.frontBack.front[selectItem.imgDomIndex]; const frontStyle = detailData.frontBack.front[selectItem.imgDomIndex];
if (!frontStyle.mirror){ if (!frontStyle?.mirror){
let scaleX = frontStyle.style.transform.match(/scaleX\(([-\d.]+)\)/); let scaleX = frontStyle.style.transform.match(/scaleX\(([-\d.]+)\)/);
let scaleY = frontStyle.style.transform.match(/scaleY\(([-\d.]+)\)/); let scaleY = frontStyle.style.transform.match(/scaleY\(([-\d.]+)\)/);
frontStyle.mirror = { x: scaleX[1] == '-1' ? true : false, y: scaleY[1] == '-1' ? true : false }; frontStyle.mirror = { x: scaleX[1] == '-1' ? true : false, y: scaleY[1] == '-1' ? true : false };
} }
startSize.width = Number(parseInt(target.style.width))
startSize.height = Number(parseInt(target.style.height))
startPosition.left = Number(parseInt(target.style.left))
startPosition.top = Number(parseInt(target.style.top))
}); });
moveableInstance.value.on('rotateStart', ({ target, direction }) => { moveableInstance.value.on('rotateStart', ({ target, direction }) => {
const frontStyle = detailData.frontBack.front[selectItem.imgDomIndex]; const frontStyle = detailData.frontBack.front[selectItem.imgDomIndex];
if (!frontStyle.mirror){ if (!frontStyle?.mirror){
let scaleX = frontStyle.style.transform.match(/scaleX\(([-\d.]+)\)/); let scaleX = frontStyle.style.transform.match(/scaleX\(([-\d.]+)\)/);
let scaleY = frontStyle.style.transform.match(/scaleY\(([-\d.]+)\)/); let scaleY = frontStyle.style.transform.match(/scaleY\(([-\d.]+)\)/);
frontStyle.mirror = { x: scaleX[1] == '-1' ? true : false, y: scaleY[1] == '-1' ? true : false }; frontStyle.mirror = { x: scaleX[1] == '-1' ? true : false, y: scaleY[1] == '-1' ? true : false };
@@ -211,7 +219,7 @@ export default defineComponent({
top:parseFloat(selectedEl.style.top.replace('px','')) || 0, top:parseFloat(selectedEl.style.top.replace('px','')) || 0,
} }
}); });
// 拖拽 // 拖拽
moveableInstance.value.on('drag', ({ target, beforeTranslate }) => { moveableInstance.value.on('drag', ({ target, beforeTranslate }) => {
let x = startPosition.left + beforeTranslate[0] let x = startPosition.left + beforeTranslate[0]
let y = startPosition.top + beforeTranslate[1] let y = startPosition.top + beforeTranslate[1]
@@ -222,133 +230,179 @@ export default defineComponent({
const currentTransform = element.style?.transform || ''; const currentTransform = element.style?.transform || '';
const currentRotates = (currentTransform.match(/rotate[XYZ]?\([^)]+\)/g) || []); const currentRotates = (currentTransform.match(/rotate[XYZ]?\([^)]+\)/g) || []);
let otherTransforms = currentTransform let otherTransforms = currentTransform
.replace(/scaleX\(-1\)|scaleY\(-1\)/g, '') .replace(/scaleX\([^)]*\)/g, '') // 移除所有 scaleX(...)
.replace(/scaleY\([^)]*\)/g, '') // 移除所有 scaleY(...)
.replace(/rotate[XYZ]?\([^)]+\)/g, '') .replace(/rotate[XYZ]?\([^)]+\)/g, '')
.replace(/\s+/g, ' ') .replace(/\s+/g, ' ')
.trim(); .trim();
const transforms = []; const transforms = [];
if (element.mirror.x) transforms.push('scaleX(-1)'); if (element.mirror && element.mirror.x) transforms.push('scaleX(-1)');
if (element.mirror.y) transforms.push('scaleY(-1)'); if (element.mirror && element.mirror.y) transforms.push('scaleY(-1)');
if (otherTransforms) transforms.push(otherTransforms); if (otherTransforms) transforms.push(otherTransforms);
if (rotateDeg !== null) { if (rotateDeg !== null) {
transforms.push(`rotate(${rotateDeg}deg)`); transforms.push(`rotate(${rotateDeg}deg)`);
} else if (currentRotates.length > 0) { } else if (currentRotates.length > 0) {
transforms.push(...currentRotates); transforms.push(...currentRotates);
} }
element.style.transform = transforms.join(' ').trim(); element.style.transform = transforms.join(' ').trim();
}; };
moveableInstance.value.on('scale', ({ target, delta, direction }) => { moveableInstance.value.on('scale', (e) => {
var { target, delta, direction, dist} = e
// console.log('scaleStart', e);
const frontStyle = detailData.frontBack.front[selectItem.imgDomIndex]; const frontStyle = detailData.frontBack.front[selectItem.imgDomIndex];
if (!frontStyle.mirror) frontStyle.mirror = { x: false, y: false };
// 确保 mirror 对象存在并正确初始化
let width = parseFloat(frontStyle.style.width); if (!frontStyle.mirror) {
let height = parseFloat(frontStyle.style.height); frontStyle.mirror = { x: false, y: false };
let left = parseFloat(frontStyle.style.left) || 0; }
let top = parseFloat(frontStyle.style.top) || 0;
// 清除可能存在的重复镜像变换
updateElementTransform(frontStyle);
// let width = parseFloat(frontStyle.style.width);
// let height = parseFloat(frontStyle.style.height);
// let left = parseFloat(frontStyle.style.left) || 0;
// let top = parseFloat(frontStyle.style.top) || 0;
let width = startSize.width
let height = startSize.height
let left = startPosition.left;
let top = startPosition.top;
let rotation = 0; let rotation = 0;
const originalRatio = width / height; const originalRatio = width / height;
// 提取当前旋转角度
if (frontStyle.style.transform) { if (frontStyle.style.transform) {
const match = frontStyle.style.transform.match(/rotate\(([-\d.]+)deg\)/); const match = frontStyle.style.transform.match(/rotate\(([-\d.]+)deg\)/);
if (match) rotation = parseFloat(match[1]); if (match) rotation = parseFloat(match[1]);
} }
const getAdjustedCorner = (corner, rot) => { const getAdjustedCorner = (corner, rot) => {
const rad = rot * (Math.PI / 180); const rad = rot * (Math.PI / 180);
const x = corner.x * Math.cos(rad) - corner.y * Math.sin(rad); const x = corner.x * Math.cos(rad) - corner.y * Math.sin(rad);
const y = corner.x * Math.sin(rad) + corner.y * Math.cos(rad); const y = corner.x * Math.sin(rad) + corner.y * Math.cos(rad);
const threshold = 0.5; const threshold = 0.5;
return { x: Math.abs(x) > threshold ? (x > 0 ? 1 : -1) : 0, y: Math.abs(y) > threshold ? (y > 0 ? 1 : -1) : 0 }; return {
x: Math.abs(x) > threshold ? (x > 0 ? 1 : -1) : 0,
y: Math.abs(y) > threshold ? (y > 0 ? 1 : -1) : 0
};
}; };
if (rotation !== 0) {
direction = getAdjustedCorner({ x: direction[0], y: direction[1] }, rotation); // 根据旋转角度调整方向
direction = [direction.x, direction.y]; // if (rotation !== 0) {
} // direction = getAdjustedCorner({ x: direction[0], y: direction[1] }, rotation);
// direction = [direction.x, direction.y];
// }
const isDiagonal = Math.abs(direction[0]) === 1 && Math.abs(direction[1]) === 1; const isDiagonal = Math.abs(direction[0]) === 1 && Math.abs(direction[1]) === 1;
const processAxis = (axis, val, deltaVal, dir, pos, keepRatio = false, otherAxisResult = null) => { const processAxis = (axis, val, distVal, dir, pos, keepRatio = false, otherAxisResult = null) => {
const mirrorKey = axis === 'width' ? 'x' : 'y'; const mirrorKey = axis === 'width' ? 'x' : 'y';
const isWidth = axis === 'width'; const isWidth = axis === 'width';
let newVal = val * deltaVal; let newVal = val * distVal;
// 翻转处理 - 只在值真正变为负值时触发镜像
// 翻转处理 // if (newVal < 0) {
if (newVal <= 0) { // frontStyle.mirror[mirrorKey] = !frontStyle.mirror[mirrorKey];
frontStyle.mirror[mirrorKey] = !frontStyle.mirror[mirrorKey]; // newVal = Math.abs(newVal);
newVal = Math.abs(newVal); // } else if (newVal === 0) {
updateElementTransform(frontStyle); // // 防止值变为0
} // newVal = 1;
// }
if(newVal < 10) newVal = 10;
// 位置调整 // 位置调整
const shouldMove = (!frontStyle.mirror[mirrorKey] && dir === -1) || (frontStyle.mirror[mirrorKey] && dir === 1); const shouldMove = (!frontStyle.mirror[mirrorKey] && dir === -1) || (frontStyle.mirror[mirrorKey] && dir === 1);
if (keepRatio && otherAxisResult) { // 保持宽高比
newVal = isWidth ? otherAxisResult.newVal * originalRatio : otherAxisResult.newVal / originalRatio; // if (keepRatio && otherAxisResult) {
} // newVal = isWidth ? otherAxisResult.newVal * originalRatio : otherAxisResult.newVal / originalRatio;
// }
const adjustPos = shouldMove ? pos - (newVal - val) : pos; const adjustPos = shouldMove ? pos - (newVal - val) : pos;
return { newVal, adjustPos, shouldFlip: newVal !== val && newVal <= 0 }; return { newVal, adjustPos };
}; };
// 处理缩放
if (isDiagonal) { if (isDiagonal) {
const mainAxis = Math.abs(delta[0] - 1) > Math.abs(delta[1] - 1) ? 'width' : 'height'; // const mainAxis = Math.abs(dist[0] - 1) > Math.abs(dist[1] - 1) ? 'width' : 'height';
const crossAxis = mainAxis === 'width' ? 'height' : 'width'; // const crossAxis = mainAxis === 'width' ? 'height' : 'width';
// const mainDir = mainAxis === 'width' ? dist[0] : dist[1];
// const crossDir = crossAxis === 'width' ? dist[0] : dist[1];
// const mainDelta = mainAxis === 'width' ? dist[0] : dist[1];
// const mainResult = processAxis(mainAxis, mainAxis === 'width' ? width : height, mainDelta, mainDir, mainAxis === 'width' ? left : top);
// const crossResult = processAxis(crossAxis, crossAxis === 'width' ? width : height, 1, crossDir, crossAxis === 'width' ? left : top, true, mainResult);
// frontStyle.style.width = mainAxis === 'width' ? mainResult.newVal + 'px' : crossResult.newVal + 'px';
// frontStyle.style.height = mainAxis === 'height' ? mainResult.newVal + 'px' : crossResult.newVal + 'px';
// frontStyle.style.left = mainAxis === 'width' ? mainResult.adjustPos + 'px' : crossResult.adjustPos + 'px';
// frontStyle.style.top = mainAxis === 'height' ? mainResult.adjustPos + 'px' : crossResult.adjustPos + 'px';
const scale = (dist[0] < 0 && dist[1] < 0) ? -Math.sqrt(dist[0] * dist[1]) : Math.sqrt(dist[0] * dist[1]);
const widthResult = processAxis('width', width, scale, direction[0], left);
const heightResult = processAxis('height', height, scale, direction[1], top);
frontStyle.style.width = widthResult.newVal + 'px';
frontStyle.style.height = heightResult.newVal + 'px';
frontStyle.style.left = widthResult.adjustPos + 'px';
frontStyle.style.top = heightResult.adjustPos + 'px';
const mainDir = mainAxis === 'width' ? direction[0] : direction[1];
const crossDir = crossAxis === 'width' ? direction[0] : direction[1];
const mainDelta = mainAxis === 'width' ? delta[0] : delta[1];
const mainResult = processAxis(mainAxis, mainAxis === 'width' ? width : height, mainDelta, mainDir, mainAxis === 'width' ? left : top);
const crossResult = processAxis(crossAxis, crossAxis === 'width' ? width : height, 1, crossDir, crossAxis === 'width' ? left : top, true, mainResult);
frontStyle.style.width = mainAxis === 'width' ? mainResult.newVal + 'px' : crossResult.newVal + 'px';
frontStyle.style.height = mainAxis === 'height' ? mainResult.newVal + 'px' : crossResult.newVal + 'px';
frontStyle.style.left = mainAxis === 'width' ? mainResult.adjustPos + 'px' : crossResult.adjustPos + 'px';
frontStyle.style.top = mainAxis === 'height' ? mainResult.adjustPos + 'px' : crossResult.adjustPos + 'px';
} else { } else {
const widthResult = processAxis('width', width, delta[0], direction[0], left); const widthResult = processAxis('width', width, dist[0], direction[0], left);
const heightResult = processAxis('height', height, delta[1], direction[1], top); const heightResult = processAxis('height', height, dist[1], direction[1], top);
frontStyle.style.left = widthResult.adjustPos + 'px'; frontStyle.style.left = widthResult.adjustPos + 'px';
frontStyle.style.top = heightResult.adjustPos + 'px'; frontStyle.style.top = heightResult.adjustPos + 'px';
frontStyle.style.width = widthResult.newVal + 'px'; frontStyle.style.width = widthResult.newVal + 'px';
frontStyle.style.height = heightResult.newVal + 'px'; frontStyle.style.height = heightResult.newVal + 'px';
} }
// 更新变换,确保正确的顺序
updateElementTransform(frontStyle);
}); });
// 旋转
moveableInstance.value.on('rotate', ({ target, beforeRotate }) => { moveableInstance.value.on('rotate', ({ target, beforeRotate }) => {
let frontStyle = detailData.frontBack.front[selectItem.imgDomIndex]; let frontStyle = detailData.frontBack.front[selectItem.imgDomIndex];
// 确保镜像状态存在 if (!frontStyle.mirror) {
if (!frontStyle.mirror) frontStyle.mirror = { x: false, y: false }; frontStyle.mirror = { x: false, y: false };
}
const { x: isMirroredX, y: isMirroredY } = frontStyle.mirror; const { x: isMirroredX, y: isMirroredY } = frontStyle.mirror;
const currentTransform = frontStyle.style?.transform || '';
// 计算实际旋转角度 const rotateMatch = currentTransform.match(/rotate\(([-\d.]+)deg\)/);
let actualRotate = beforeRotate; let currentAngle = 0;
if (rotateMatch && rotateMatch[1]) {
// 关键逻辑当镜像状态不同时一个true一个false旋转方向反转 const parsed = parseFloat(rotateMatch[1]);
if (isMirroredX !== isMirroredY) { if (!isNaN(parsed)) {
actualRotate = -beforeRotate; currentAngle = parsed;
}
} }
const newBeforeRotate = parseFloat(beforeRotate) || 0;
// 确保角度在 0-360 度范围内 if (!window._lastRotateData) {
actualRotate = actualRotate % 360; window._lastRotateData = {
beforeRotate: newBeforeRotate,
// 如果角度为负数,转换为正数 angle: currentAngle
if (actualRotate < 0) { };
actualRotate += 360;
} }
const delta = newBeforeRotate - window._lastRotateData.beforeRotate;
// 确保角度在 [0, 360) 范围内 const shouldReverse = (isMirroredX && !isMirroredY) || (!isMirroredX && isMirroredY);
actualRotate = ((actualRotate % 360) + 360) % 360; let newAngle;
if (shouldReverse) {
updateElementTransform(frontStyle, actualRotate.toFixed(2)); newAngle = window._lastRotateData.angle - delta;
} else {
newAngle = window._lastRotateData.angle + delta;
}
newAngle = ((newAngle % 360) + 360) % 360;
window._lastRotateData.beforeRotate = newBeforeRotate;
window._lastRotateData.angle = newAngle;
updateElementTransform(frontStyle, newAngle);
});
// 可选在rotateStart时重置
moveableInstance.value.on('rotateStart', () => {
window._lastRotateData = null;
}); });
// 调整大小 // 调整大小
moveableInstance.value.on('resize', ({ target, width, height }) => { moveableInstance.value.on('resize', ({ target, width, height }) => {
@@ -370,12 +424,23 @@ export default defineComponent({
upDataDetail() upDataDetail()
}); });
}; };
watch(()=>selectItem.selectDetail,(newValue,oldValue)=>{ // watch(()=>selectItem.selectDetail,(newValue,oldValue)=>{
if(!newValue && newValue?.id == oldValue?.id)return // if(!newValue && newValue?.id == oldValue?.id)return
selectItem.imgDomIndex = detailData.frontBack.front.findIndex((item:any)=>item.id == newValue.id) // },{immediate: true,})
initMoveableForSelected() watch(()=>selectItem.selectDetail?.id,(newValue,oldValue)=>{
if(newValue){
selectItem.imgDomIndex = detailData.frontBack.front.findIndex((item:any)=>item.id == newValue)
setTimeout(()=>{
initMoveableForSelected()
},100)
}
},{immediate: true,}) },{immediate: true,})
watch(()=>detailData.frontBack.front.length,(newValue,oldValue)=>{
if(selectItem.selectDetail?.id)selectItem.imgDomIndex = detailData.frontBack.front.findIndex((item:any)=>item.id == selectItem.selectDetail?.id)
setTimeout(()=>{
initMoveableForSelected()
},100)
})
const setRevocation = async ()=>{ const setRevocation = async ()=>{
let frontBack = JSON.parse(JSON.stringify(detailData.frontBack)) let frontBack = JSON.parse(JSON.stringify(detailData.frontBack))
let revocation:any = JSON.parse((await KeyValueDB.get("revocation") as any) || '[]') let revocation:any = JSON.parse((await KeyValueDB.get("revocation") as any) || '[]')
@@ -536,6 +601,7 @@ export default defineComponent({
getMousePosition, getMousePosition,
updataPosition, updataPosition,
updateRect, updateRect,
initMoveableForSelected,
} }
}, },
@@ -625,6 +691,8 @@ export default defineComponent({
:deep(.moveable-control){ :deep(.moveable-control){
width: 1.4rem; width: 1.4rem;
height: 1.4rem; height: 1.4rem;
margin-top: -.7rem;
margin-left: -.7rem;
border-radius: 0; border-radius: 0;
background-color: #44aaff; background-color: #44aaff;
border: 2px solid #44aaff; border: 2px solid #44aaff;

View File

@@ -790,7 +790,6 @@ export default defineComponent({
.login_form_content { .login_form_content {
margin-top: 4rem; margin-top: 4rem;
position: relative; position: relative;
&[state="2"] { &[state="2"] {
> * { > * {
opacity: 0; opacity: 0;

View File

@@ -826,7 +826,6 @@ export default defineComponent({
.login_form_content { .login_form_content {
margin-top: 4rem; margin-top: 4rem;
position: relative; position: relative;
&[state="2"] { &[state="2"] {
> * { > * {
opacity: 0; opacity: 0;

View File

@@ -56,7 +56,7 @@
@changeCanvas="changeCanvas" @changeCanvas="changeCanvas"
@trigger-library="triggerLibrary" @trigger-library="triggerLibrary"
:canvasJSON="canvasJSON" :canvasJSON="canvasJSON"
:hideCanvas="hideCanvas" :hideCanvas="hideCanvas || !key"
ref="editCanvas"> ref="editCanvas">
<template #existsImageList> <template #existsImageList>
<ExistsImageList :list="canvasSelectList" @select="handleImageSelect" /> <ExistsImageList :list="canvasSelectList" @select="handleImageSelect" />
@@ -135,7 +135,7 @@ export default defineComponent({
unLikeList:[], unLikeList:[],
locale:null as any, locale:null as any,
t:null as any, t:null as any,
key:true as any
}) })
const dataDom = reactive({ const dataDom = reactive({
toProduct:null as any, toProduct:null as any,
@@ -462,9 +462,11 @@ export default defineComponent({
imgUrl:imageDataURL, imgUrl:imageDataURL,
userlikeGroupId:'', userlikeGroupId:'',
} }
data.key = false
dataDom.publish.init(value) dataDom.publish.init(value)
} }
const setPublish = ()=>{ const setPublish = ()=>{
data.key = true
saveCanvas() saveCanvas()
} }
return{ return{

View File

@@ -916,9 +916,13 @@ export default defineComponent({
.login_form_content { .login_form_content {
margin-top: 4rem; margin-top: 4rem;
position: relative; position: relative;
min-height: 34rem;
@media (max-width: 768px) { @media (max-width: 768px) {
margin-top: 2.4rem; margin-top: 2.4rem;
height: 20rem; min-height: auto;
&[state="2"] {
height: 20rem;
}
} }
&[state="2"] { &[state="2"] {
> * { > * {

View File

@@ -272,12 +272,12 @@ const navTypeList = (t)=>{
// }, // },
// { {
// icon:'fi fi-rr-puzzle-alt', icon:'fi fi-rr-puzzle-alt',
// value:'deReconstruction', value:'deReconstruction',
// label:t('Header.toolsDeReconstruction'), label:t('Header.toolsDeReconstruction'),
// router:'tools=deReconstruction' router:'tools=deReconstruction'
// }, },
{ {
icon:'fi fi-ss-box-open', icon:'fi fi-ss-box-open',
value:'toProduct', value:'toProduct',
@@ -294,18 +294,18 @@ const navTypeList = (t)=>{
label:t('Header.toolsToTransferPose'), label:t('Header.toolsToTransferPose'),
router:'tools=poseTransfer' router:'tools=poseTransfer'
}, },
// { {
// icon:'fi fi-rr-cubes', icon:'fi fi-rr-cubes',
// value:'patternMaking3D', value:'patternMaking3D',
// label:t('Header.toolsPatternMaking'), label:t('Header.toolsPatternMaking'),
// router:'tools=patternMaking3D' router:'tools=patternMaking3D'
// }, },
// { {
// icon:'fi fi-rr-pen-swirl', icon:'fi fi-rr-pen-swirl',
// value:'canvasUpload', value:'canvasUpload',
// label:t('Header.toolsCanvas'), label:t('Header.toolsCanvas'),
// router:'tools=canvasUpload' router:'tools=canvasUpload'
// }, },
] ]
}, },
library:{ library:{

View File

@@ -12,7 +12,7 @@
<!-- <div class="upgrade-content-textab">Due to the system server upgrade, we will start the upgrade from 9:30 am Hong Kong time on the weekend of October 20th until October 21st. During this time,<br> the AiDA system will be temporarily inaccessible. We apologize for any inconvenience this may cause and thank you for your understanding.</div> --> <!-- <div class="upgrade-content-textab">Due to the system server upgrade, we will start the upgrade from 9:30 am Hong Kong time on the weekend of October 20th until October 21st. During this time,<br> the AiDA system will be temporarily inaccessible. We apologize for any inconvenience this may cause and thank you for your understanding.</div> -->
<!-- 有截至时间 --> <!-- 有截至时间 -->
<div class="upgrade-content-textab"> <div class="upgrade-content-textab">
Due to system server upgrades, maintenance will be carried out from 21:00 to 22:00 on January 19, 2026 (today). Due to system server upgrades, maintenance will be carried out from 21:00 to 23:00 on January 19, 2026 (today).
<br> <br>
The AiDA system will be temporarily unavailable during this period. We sincerely apologize for any inconvenience caused and thank you for your understanding.</div> The AiDA system will be temporarily unavailable during this period. We sincerely apologize for any inconvenience caused and thank you for your understanding.</div>
<br> <br>
@@ -20,7 +20,7 @@
<br> <br>
<!-- <div class="upgrade-content-textab">由于系统服务器维护AiDA系统暂时无法访问对于由此造成的任何不便我们深表歉意并感谢您的理解</div> --> <!-- <div class="upgrade-content-textab">由于系统服务器维护AiDA系统暂时无法访问对于由此造成的任何不便我们深表歉意并感谢您的理解</div> -->
<div class="upgrade-content-textab"> <div class="upgrade-content-textab">
由于系统服务器升级我们将于1月23日21:00 至1月23日22:00进行升级 由于系统服务器升级我们将于1月23日21:00 至1月23日23:00进行升级
<br> <br>
在此期间AiDA系统将暂时无法访问给您带来的不便我们深表歉意并感谢您的理解</div> 在此期间AiDA系统将暂时无法访问给您带来的不便我们深表歉意并感谢您的理解</div>
</div> </div>