Merge branch 'dev_vite' of http://18.167.251.121:10003/aidlab/aida_front into dev_vite

This commit is contained in:
zhangyh
2025-11-11 10:35:06 +08:00
8 changed files with 119 additions and 55 deletions

View File

@@ -2595,7 +2595,7 @@ export class CreateImageLayerCommand extends Command {
// 生成图层名称 // 生成图层名称
const fileName = const fileName =
this.layerName || `图片 ${new Date().toLocaleTimeString()}`; this.layerName || `${new Date().toLocaleString()}`;
this.fabricImage.set({ this.fabricImage.set({
id: this.imageId, id: this.imageId,

View File

@@ -22,7 +22,7 @@
v-for="v in activeObjects" v-for="v in activeObjects"
:key="v.id" :key="v.id"
> >
<div class="title">图层1</div> <div class="title">{{ v.layer?.name }}</div>
<div class="list"> <div class="list">
<div> <div>
<span class="label">W</span> <span class="label">W</span>
@@ -53,16 +53,20 @@
<input <input
type="number" type="number"
:value="v.angle" :value="v.angle"
disabled @change="(e) => changeAngle(e, v)"
/> />
</div> </div>
<div class="btn" @click="clickflipHorizontal(v)"> <div class="btn" @click="clickflipHorizontal(v)">
<i class="iconfont icon-flip-horizontal"></i> <i class="iconfont icon-flip-horizontal"></i>
<p class="tip">水平翻转</p> <p class="tip">
{{ t("Canvas.flipHorizontal") }}
</p>
</div> </div>
<div class="btn" @click="clickflipVertical(v)"> <div class="btn" @click="clickflipVertical(v)">
<i class="iconfont icon-flip-vertical"></i> <i class="iconfont icon-flip-vertical"></i>
<p class="tip">垂直翻转</p> <p class="tip">
{{ t("Canvas.flipVertical") }}
</p>
</div> </div>
</div> </div>
</div> </div>
@@ -158,6 +162,9 @@
const getActiveObject = (e) => { const getActiveObject = (e) => {
console.log("==========切换激活对象", e); console.log("==========切换激活对象", e);
activeObjects.value = e.selected.map((v) => v); activeObjects.value = e.selected.map((v) => v);
activeObjects.value.forEach((v) => {
v.layer = props.layerManager.getLayerById(v.layerId);
});
if (activeObjects.value.length === 0) { if (activeObjects.value.length === 0) {
close(); close();
} else { } else {
@@ -166,46 +173,11 @@
}; };
const lastSelectLayerId = inject("lastSelectLayerId"); const lastSelectLayerId = inject("lastSelectLayerId");
const layers = inject("layers"); const layers = inject("layers");
const changeAngle = (activeObj) => { const transformObject = (activeObj, initialState, finalState) => {
// console.log("=====================", e.target.value);
// const finalState = TransformCommand.captureTransformState(activeObj);
// const { xPrime, yPrime } = compute(
// activeObj.left,
// activeObj.top,
// activeObj.width,
// activeObj.height,
// activeObj.angle
// );
// finalState.left = xPrime;
// finalState.top = yPrime;
// const transformCmd = new TransformCommand({
// canvas: props.canvas,
// objectId: activeObj.id,
// initialState: null,
// finalState,
// objectType: activeObj.type,
// name: `变换 ${activeObj.type || "对象"}`,
// layerManager: props.layerManager,
// layers: layers,
// lastSelectLayerId: lastSelectLayerId,
// });
// props.layerManager.commandManager.execute(transformCmd, {
// name: "对象修改",
// });
};
const flipObject = (activeObj, type) => {
const initialState = TransformCommand.captureTransformState(activeObj);
const finalState = { ...initialState };
if (type === "h") {
finalState.flipX = !finalState.flipX;
} else if (type === "v") {
finalState.flipY = !finalState.flipY;
}
const transformCmd = new TransformCommand({ const transformCmd = new TransformCommand({
canvas: props.canvas, canvas: props.canvas,
objectId: activeObj.id, objectId: activeObj.id,
initialState: initialState, initialState,
finalState, finalState,
objectType: activeObj.type, objectType: activeObj.type,
name: `变换 ${activeObj.type || "对象"}`, name: `变换 ${activeObj.type || "对象"}`,
@@ -217,20 +189,90 @@
name: "对象修改", name: "对象修改",
}); });
}; };
const clickflipHorizontal = (obj) => {
console.log("水平翻转"); /**
flipObject(obj, "h"); * 根据左上角坐标计算旋转后的新坐标
* @param {number} W - 宽度
* @param {number} H - 高度
* @param {number} currentX - 当前左上角x坐标
* @param {number} currentY - 当前左上角y坐标
* @param {number} currentAngleDeg - 当前角度(度)
* @param {number} newAngleDeg - 新角度(度)
* @returns {Object} 旋转后的左上角坐标 {x, y}
*/
function calculateRotatedTopLeftDeg(
W,
H,
currentX,
currentY,
currentAngleDeg,
newAngleDeg
) {
const currentAngle = (currentAngleDeg * Math.PI) / 180;
const newAngle = (newAngleDeg * Math.PI) / 180;
// 1. 用当前角度计算中心点位置
const cosCurrent = Math.cos(currentAngle);
const sinCurrent = Math.sin(currentAngle);
const Cx = currentX + (W / 2) * cosCurrent - (H / 2) * sinCurrent;
const Cy = currentY + (W / 2) * sinCurrent + (H / 2) * cosCurrent;
// 2. 用新角度计算旋转后的左上角位置
const cosNew = Math.cos(newAngle);
const sinNew = Math.sin(newAngle);
const newX = Cx + (-W / 2) * cosNew - (-H / 2) * sinNew;
const newY = Cy + (-W / 2) * sinNew + (-H / 2) * cosNew;
return { x: newX, y: newY };
}
// 改变角度
const changeAngle = (e, obj) => {
const initialState = TransformCommand.captureTransformState(obj);
const finalState = { ...initialState };
const angle = e.target.value;
if (obj.originX === "left" && obj.originY === "top") {
const width = obj.width * obj.scaleX;
const height = obj.height * obj.scaleY;
const left = obj.left;
const top = obj.top;
const { x, y } = calculateRotatedTopLeftDeg(
width,
height,
left,
top,
obj.angle,
angle
);
finalState.left = x;
finalState.top = y;
}
finalState.angle = angle;
transformObject(obj, initialState, finalState);
}; };
// 水平翻转
const clickflipHorizontal = (obj) => {
const initialState = TransformCommand.captureTransformState(obj);
const finalState = { ...initialState };
finalState.flipX = !finalState.flipX;
transformObject(obj, initialState, finalState);
};
// 垂直翻转
const clickflipVertical = (obj) => { const clickflipVertical = (obj) => {
console.log("垂直翻转"); const initialState = TransformCommand.captureTransformState(obj);
flipObject(obj, "v"); const finalState = { ...initialState };
finalState.flipY = !finalState.flipY;
transformObject(obj, initialState, finalState);
}; };
const updateActiveObjects = (arrs, keys) => { const updateActiveObjects = (arrs, keys) => {
arrs.forEach((v) => { arrs.forEach((v) => {
activeObjects.value.forEach((item) => { activeObjects.value.forEach((item) => {
if (item.id === v.id) { if (item.id === v.id) {
keys.forEach((key) => (item[key] = v[key])); keys.forEach((k) => {
item[k] =
typeof v[k] === "number"
? Number(v[k].toFixed(3))
: v[k];
});
} }
}); });
activeObjects.value = [...activeObjects.value]; activeObjects.value = [...activeObjects.value];

View File

@@ -1219,6 +1219,10 @@ export class LayerManager {
} }
// 切换到选择模式 // 切换到选择模式
this?.toolManager?.setTool(OperationType.SELECT); this?.toolManager?.setTool(OperationType.SELECT);
if(objects.length === 1) {
this.canvas.setActiveObject(objects[0]);
return objects[0];
}
// 创建一个新的活动选择组 // 创建一个新的活动选择组
const activeSelection = new fabric.ActiveSelection(objects, { const activeSelection = new fabric.ActiveSelection(objects, {
canvas: this.canvas, canvas: this.canvas,

View File

@@ -44,16 +44,17 @@
:key="index" :key="index"
class="image-item" class="image-item"
@click="handleImageClick(item)" @click="handleImageClick(item)"
@dblclick="handleImageDoubleClick(item)"
> >
<div class="image-wrapper"> <div class="image-wrapper">
<img <img
:src="item.url" :src="item.url"
:alt="item.name || '图片'" :alt="item.name"
@error="handleImageError" @error="handleImageError"
loading="lazy" loading="lazy"
/> />
<div class="image-overlay"> <div class="image-overlay">
<span class="image-name">{{ item.name || "未命名" }}</span> <span class="image-name">{{ item.name }}</span>
</div> </div>
</div> </div>
<!-- <div class="image-select" v-show="selectList.includes(item.url)"> <!-- <div class="image-select" v-show="selectList.includes(item.url)">
@@ -169,7 +170,11 @@ const handleImageClick = (item) => {
selectList.value.push(item.url) selectList.value.push(item.url)
} }
}; };
// 处理图片双击
const handleImageDoubleClick = (item) => {
selectList.value = [item.url];
confirm();
}
// 处理图片加载错误 // 处理图片加载错误
const handleImageError = (event) => { const handleImageError = (event) => {
event.target.src = event.target.src =

View File

@@ -26,16 +26,17 @@
:key="index" :key="index"
class="image-item" class="image-item"
@click="handleImageClick(item)" @click="handleImageClick(item)"
@dblclick="handleImageDoubleClick(item)"
> >
<div class="image-wrapper"> <div class="image-wrapper">
<img <img
v-lazy="item.url" v-lazy="item.url"
:alt="item.name || '图片'" :alt="item.name"
@error="handleImageError" @error="handleImageError"
loading="lazy" loading="lazy"
/> />
<div class="image-overlay"> <div class="image-overlay">
<span class="image-name">{{ item.name || '未命名' }}</span> <span class="image-name">{{ item.name }}</span>
</div> </div>
</div> </div>
<img class="selected-icon image-select" src="@/assets/images/icon/selected.png" v-show="selectList.includes(item.url)"> <img class="selected-icon image-select" src="@/assets/images/icon/selected.png" v-show="selectList.includes(item.url)">
@@ -48,7 +49,6 @@
<!-- 加载状态 --> <!-- 加载状态 -->
<div v-if="loading && list.length > 0" class="loading-state"> <div v-if="loading && list.length > 0" class="loading-state">
<div class="loading-spinner"></div> <div class="loading-spinner"></div>
<p>加载中...</p>
</div> </div>
<!-- 空状态 --> <!-- 空状态 -->
@@ -279,6 +279,14 @@ const handleImageClick = item => {
} }
} }
// 处理图片双击
const handleImageDoubleClick = item => {
selectList.value = [item.url]
confirm()
}
// 处理分类切换 // 处理分类切换
const handleChangeCategory = category => { const handleChangeCategory = category => {
// console.log('handleChangeCategory',category) // console.log('handleChangeCategory',category)
@@ -307,6 +315,7 @@ const confirm = () => {
emitData = selectList.value emitData = selectList.value
} }
emits('select', emitData) emits('select', emitData)
selectList.value = []
showPanel.value = false showPanel.value = false
} }

View File

@@ -1217,6 +1217,8 @@ export default {
Rough: '粗糙', Rough: '粗糙',
Smooth: '平滑', Smooth: '平滑',
basic: '基础', basic: '基础',
flipHorizontal: '水平翻转',
flipVertical: '垂直翻转',
//长毛笔 //长毛笔
FurSettings: '长毛笔设置', FurSettings: '长毛笔设置',
FurLength: '毛发长度', FurLength: '毛发长度',

View File

@@ -1252,6 +1252,8 @@ export default {
Rough: 'Rough', Rough: 'Rough',
Smooth: 'Smooth', Smooth: 'Smooth',
basic: 'Basic', basic: 'Basic',
flipHorizontal: 'Horizontal Flip',
flipVertical: 'Vertical Flip',
//长毛笔 //长毛笔
FurSettings: 'FurSettings', FurSettings: 'FurSettings',
FurLength: 'Fur Length', FurLength: 'Fur Length',

View File

@@ -771,7 +771,7 @@ export default defineComponent({
padding: 0 1rem; padding: 0 1rem;
.operate_item { .operate_item {
font-size: 1.4rem; // font-size: 1.4rem;
font-family: Roboto; font-family: Roboto;
font-weight: 400; font-weight: 400;
color: #007ee5; color: #007ee5;