Commit fe1e5ff2 by linjinhong

fix:添加备注方法注释

parent e34286ca
......@@ -583,6 +583,7 @@ export default {
res.json({ code: 500, msg: error });
}
},
processTransparentBackground: async (req, res) => {
env = getHostApi().apiApiHost;
const token = req.headers["jwt-token"];
......
......@@ -417,9 +417,19 @@ function applyPadding(bounds, padding, imgWidth, imgHeight) {
}
}
/**
* @async
* @function checkImageOutsideGrid
* @description 【核心业务方法】检测图片是否超出打印网格边界,并判断超出部分是否存在有效像素(非透明)
* 应用场景:印刷/打印场景,校验图片是否超出安全网格,避免裁切丢失内容
* @returns {Object} 检测结果
* @property {boolean} isImageBiggerThanGrid - 图片显示尺寸是否大于网格尺寸
* @property {boolean} hasOutsideValidPixel - 超出网格部分是否存在有效像素(非透明)
*/
async function checkImageOutsideGrid() {
try {
// ===================== 第一步:获取 DOM 几何信息(核心!)=====================
// ===================== 第一步:获取DOM元素与页面几何尺寸 =====================
// 获取打印安全网格容器(id=line)
const lineDom = document.getElementById("line");
if (!lineDom) {
console.log("未找到网格元素(id=line)");
......@@ -429,7 +439,9 @@ async function checkImageOutsideGrid() {
};
}
// 获取网格元素的页面绝对坐标和尺寸
const lineRect = lineDom.getBoundingClientRect();
// 格式化网格边界信息:左、上、右、下、宽、高
const grid = {
left: lineRect.left,
top: lineRect.top,
......@@ -439,6 +451,7 @@ async function checkImageOutsideGrid() {
height: lineRect.height,
};
// 网格无尺寸,直接返回默认结果
if (grid.width === 0 || grid.height === 0) {
return {
isImageBiggerThanGrid: false,
......@@ -446,6 +459,7 @@ async function checkImageOutsideGrid() {
};
}
// 获取图片展示容器(id=imgBox)
const imgDom = document.getElementById("imgBox");
if (!imgDom) {
console.log("图片未加载完成或未找到imgBox元素");
......@@ -455,16 +469,19 @@ async function checkImageOutsideGrid() {
};
}
// 确保图片加载完成
// 等待图片完全加载完成,保证尺寸获取准确
await new Promise((resolve) => {
if (imgDom.complete) resolve();
else imgDom.onload = resolve;
});
// 获取图片在页面上的显示坐标、尺寸
const imgRect = imgDom.getBoundingClientRect();
// 获取图片原始分辨率(真实像素尺寸)
const naturalWidth = imgDom.naturalWidth;
const naturalHeight = imgDom.naturalHeight;
// 图片无原始尺寸,直接返回默认结果
if (naturalWidth === 0 || naturalHeight === 0) {
console.log("图片原始尺寸为0");
return {
......@@ -473,6 +490,7 @@ async function checkImageOutsideGrid() {
};
}
// 格式化图片完整信息:显示位置、显示尺寸、原始尺寸
const imgDisplayInfo = {
left: imgRect.left,
top: imgRect.top,
......@@ -482,12 +500,11 @@ async function checkImageOutsideGrid() {
naturalHeight,
};
// ===================== 【判断1】图片是否大于台版 =====================
// ===================== 【判断1】图片显示尺寸是否大于打印网格 =====================
const isImageBiggerThanGrid =
imgDisplayInfo.width > grid.width || imgDisplayInfo.height > grid.height;
// 如果图片不大于网格,直接返回
// 图片尺寸≤网格,无需进行像素越界检测,直接返回
if (!isImageBiggerThanGrid) {
console.log("图片尺寸小于/等于网格,无需检测越界");
return {
......@@ -496,38 +513,52 @@ async function checkImageOutsideGrid() {
};
}
// ===================== 第二步:Sharp 读取图片原始像素 =====================
// ===================== 第二步:处理图片路径,使用Sharp读取原始像素数据 =====================
let imgSource = imgDom.src;
// 兼容处理本地file://协议的图片路径(Electron环境专用)
if (imgSource.startsWith("file://")) {
console.log(111);
// 解析本地文件路径
imgSource = new URL(imgSource).pathname;
// Windows系统路径修正(去除开头多余的斜杠)
if (process.platform === "win32") {
imgSource = imgSource.slice(1);
}
// 解码URI编码字符
imgSource = decodeURIComponent(imgSource);
}
console.log("imgSource", imgSource);
// 使用Sharp库加载图片
const sharpImg = sharp(imgSource);
// 获取图片元信息(宽高、通道数、格式等)
const imgMetadata = await sharpImg.metadata();
// 将图片转为原始像素数据(Buffer),方便逐像素检测
const { data: pixels } = await sharpImg
.raw()
.toBuffer({ resolveWithObject: true });
// ===================== 第三步:坐标映射 + 像素检测 =====================
// ===================== 第三步:坐标映射 + 逐像素检测越界有效像素 =====================
// 计算缩放比例:图片显示尺寸 / 原始尺寸(页面像素 → 原始像素映射)
const scaleX = imgDisplayInfo.width / naturalWidth;
const scaleY = imgDisplayInfo.height / naturalHeight;
// 标记:是否检测到超出网格的有效像素
let hasOutsideValidPixel = false;
// 透明度阈值:Alpha值>1 视为有效像素(非透明)
const alphaThreshold = 1;
// 图片原始宽高
const imgNaturalWidth = imgMetadata.width;
const imgNaturalHeight = imgMetadata.height;
// 判断图片是否包含透明通道(PNG为4通道,JPG为3通道)
const hasAlpha = imgMetadata.channels === 4;
// 双层循环:遍历图片所有原始像素
for (let y = 0; y < imgNaturalHeight; y++) {
// 已检测到有效像素,直接终止循环,提升性能
if (hasOutsideValidPixel) break;
for (let x = 0; x < imgNaturalWidth; x++) {
// 计算当前原始像素 → 页面上的显示坐标
const imgDisplayX = parseFloat(
(imgDisplayInfo.left + x * scaleX).toFixed(2),
);
......@@ -535,28 +566,33 @@ async function checkImageOutsideGrid() {
(imgDisplayInfo.top + y * scaleY).toFixed(2),
);
// 坐标异常,跳过当前像素
if (isNaN(imgDisplayX) || isNaN(imgDisplayY)) continue;
// 判断当前像素是否【超出打印网格边界】
const isOutside =
imgDisplayX < grid.left ||
imgDisplayX > grid.right ||
imgDisplayY < grid.top ||
imgDisplayY > grid.bottom;
// 仅处理【超出网格】的像素
if (isOutside) {
// 计算当前像素在原始Buffer数据中的索引位置
const pixelIndex = (y * imgNaturalWidth + x) * imgMetadata.channels;
// 🔥 终极兼容逻辑
// 🔥 核心:判断超出部分是否为【有效像素】(非透明)
let isValidPixel = false;
if (hasAlpha) {
// PNG 有透明通道:判断透明度
// 图片有透明通道(PNG):读取Alpha值,判断是否为非透明
const alpha = pixels[pixelIndex + 3];
isValidPixel = alpha > alphaThreshold;
} else {
// JPG / 无透明通道:只要超出,一律视为有实色像素(纯白/彩色都算)
// 图片无透明通道(JPG):所有超出像素都视为有效像素
isValidPixel = true;
}
// 检测到有效越界像素,标记并终止循环
if (isValidPixel) {
hasOutsideValidPixel = true;
console.log(`✅ 检测到超出有效像素(坐标${x},${y})`);
......@@ -568,14 +604,14 @@ async function checkImageOutsideGrid() {
console.log("检测结果:", hasOutsideValidPixel ? "超出网格" : "正常");
// ===================== ✅ 返回你要的两个参数 =====================
// ===================== 第四步:返回最终检测结果 =====================
return {
isImageBiggerThanGrid, // 图片是否大于台版
hasOutsideValidPixel, // 超出部分是否有真实像素(非透明)
isImageBiggerThanGrid, // 图片是否大于网格
hasOutsideValidPixel, // 超出部分是否有真实有效像素
};
} catch (error) {
// 异常捕获:检测失败时,打印错误并返回默认结果,保证程序不崩溃
console.error("检测失败:", error);
// 出错也返回固定结构
return {
isImageBiggerThanGrid: false,
hasOutsideValidPixel: false,
......
......@@ -275,11 +275,13 @@ export function getImgTitle(imageResList) {
});
}
/**
* 毫米(mm) 转换为 像素(px) 工具函数
* 换算标准:遵循打印/设计行业标准 1英寸 = 25.4mm,固定使用每一个网格42px的进行计算
* @param {number|string} mm - 待转换的毫米数值
* @returns {number} 转换后的像素值,保留1位小数
*/
export function newMmToPxFn(mm) {
const px = (Number(mm) / 25.4) * 42;
return Number(px.toFixed(1));
}
export function HLCMmToPxFn(mm) {
const px = (Number(mm) / 10) * 18;
return Number(px.toFixed(1));
}
<script>
import bus from "@/bus";
// import PrintDialog from "./printDialog.vue";
// import { getProductCnByFactorySubOrderNumberApi } from "../../../api/index.js";
import { ipcRenderer } from "electron";
import { copySingleImage } from "@/server/utils/index.js";
const moment = require("moment");
......@@ -143,7 +141,6 @@ export default {
} else {
this.$dataStore.set("setting", this.setting);
}
// console.log(this.getDomainFromUrl(getHostApi().apiApiHost));
},
watch: {
setting: {
......@@ -161,9 +158,7 @@ export default {
immediate: true,
deep: true,
},
desktopDevice(val) {
console.log("desktopDevice", val);
desktopDevice() {
this.checked = false;
},
imgList: {
......@@ -247,12 +242,6 @@ export default {
const canCallApi =
this.desktopDevice != 3 ||
(data.saveImgList?.every((el) => el.power) ?? false);
console.log(
"data",
data.saveImgList?.every((el) => el.power),
);
console.log("canCallApi", canCallApi);
console.log("desktopDevice", this.desktopDevice);
if (canCallApi) {
console.log("生产完成");
......@@ -263,9 +252,6 @@ export default {
}
console.log("本地数据removeFromOrderInfo:", getOrderInfoMap());
//生产完成后在本地删除
// return;
// await completeDeliveryApi(params);
// await this.$api.post("/completeDelivery", params);
await this.$api.post(
pathMap["completeDelivery"][this.orderType],
params,
......@@ -324,9 +310,6 @@ export default {
responseType: "blob",
})
.then((res) => {
// console.log("item", item);
const canvasWidth = 524.0493037260068;
const canvasHeight = 589.5;
var url = URL.createObjectURL(res.data);
let img = new Image();
img.crossorigin = "";
......@@ -343,27 +326,8 @@ export default {
ctx.imageSmoothingQuality = "high";
ctx.drawImage(img, ...item.drawImage);
URL.revokeObjectURL(url);
const originWidth = img.width;
const originHeight = img.height;
const [dx, dy, drawW] = item.drawImage;
const scale = drawW / originWidth;
// 2. 黄点在【原始高清图】上的裁切坐标
const cropArea = {
left: Math.round(-dx / scale),
top: Math.round(-dy / scale),
width: Math.round(canvasWidth / scale),
height: Math.round(canvasHeight / scale),
};
// 3. 黄点相对【整个原始素材】的比例(0~1,你要的最终结果)
const maskRatio = {
left: Number((cropArea.left / originWidth).toFixed(4)),
top: Number((cropArea.top / originHeight).toFixed(4)),
width: Number((cropArea.width / originWidth).toFixed(4)),
height: Number((cropArea.height / originHeight).toFixed(4)),
};
console.log(392, maskRatio);
resolve(maskRatio);
resolve();
};
})
.catch((e) => {
......@@ -391,12 +355,7 @@ export default {
// 遍历每个canvas配置项,串行处理(保持原逻辑,若想并行可改成Promise.all(canvasList.map(...)))
for (const canvasConfig of canvasList) {
// 解构赋值,简化后续取值,同时校验核心属性
const {
canvasWidth,
canvasHeight,
rect_info,
list: drawItems,
} = canvasConfig;
const { canvasWidth, canvasHeight, list: drawItems } = canvasConfig;
if (!canvasWidth || !canvasHeight || !Array.isArray(drawItems)) {
throw new Error(
"canvas配置项必须包含canvasWidth/canvasHeight/list(数组)属性",
......@@ -411,7 +370,7 @@ export default {
// 批量执行绘制方法,收集异步绘制Promise(语义化变量名,替代原模糊的list)
const drawPromises = drawItems.map((drawItem) =>
this.drawImage(canvas, drawItem, { rect_info }),
this.drawImage(canvas, drawItem),
);
// 等待当前canvas的所有绘制操作完成
await Promise.all(drawPromises);
......@@ -494,8 +453,7 @@ export default {
}
if (this.desktopDevice == 3) {
designImagesCanvasJsonList = JSON.parse(designImagesCanvasJsonList);
console.log("designImagesCanvasJsonList", designImagesCanvasJsonList);
// 惠立彩 带黄点摸的订单直接展示错误弹窗
if (!designImagesCanvasJsonList[0].images) {
this.dialogVisible = true;
return;
......@@ -528,7 +486,6 @@ export default {
} else if (bool) {
//如果有本地数据 则直接获取本地数据同图片
imageResList = this.detail?.saveImgList || [];
console.log("imageResList", imageResList);
}
if (this.checked) {
......@@ -605,6 +562,7 @@ export default {
}
if (this.detail && !this.isAutoFinish && this.desktopDevice == 3) {
//惠立彩判断是否全部图片都已经打印完成
const canCallApi =
this.detail.saveImgList?.every((el) => el.power) ?? false;
if (canCallApi) {
......@@ -615,16 +573,13 @@ export default {
}
}
// if (this.desktopDevice == 3 && !this.isForcedProduction) {
// }
//判断生产单号是否为空
if (this.productionNo === "")
return this.$message.warning("请录入生产单号");
const today = moment(new Date()).format("YYYY-MM-DD");
//判断上一单未勾选是否跳过
//判断上一单未勾选添加当天日期是否跳过
if (!this.isAutoFinish && today != getNowDate()) {
this.$confirm("请注意自动完成上一单未勾选", "提示", {
confirmButtonText: "跳过提示",
......@@ -686,8 +641,6 @@ export default {
apiRequestParams,
));
} else {
console.log("path", pathMap["findByPodProductionNo"]);
findByPodProductionNo = await this.$api.post(
pathMap["findByPodProductionNo"][this.orderType],
apiRequestParams,
......@@ -730,12 +683,10 @@ export default {
if (field.includes("CN")) {
return "CN";
}
// 第二类:以"AAAF-USPSC"开头
if (field.includes("US")) {
return "US";
}
// 第三类:所有其他情况
return "GC";
},
......@@ -834,7 +785,6 @@ export default {
},
async cutImgFn(arr) {
if (!arr.length) return arr;
console.log(arr);
try {
const processQueue = await Promise.all(
......@@ -864,15 +814,13 @@ export default {
// 等待所有异步操作完成
await new Promise((resolve) => setTimeout(resolve, 100));
const newMap = new Map(processQueue.map((el) => [el.designId, el]));
// console.log("newMap", newMap);
processQueue.forEach((el) => {
if (newMap.has(el.designId)) {
el.fileName = newMap.get(el.designId).fileName;
el.productionFile = newMap.get(el.designId).productionFile;
}
});
// console.log("processQueue", processQueue);
return processQueue;
} catch (error) {
console.error("错误", error);
......
......@@ -767,6 +767,7 @@ export default {
let data = await that.getImageSize(files[i].url);
const isCut = files[i].isCut;
if (size && !isCut) {
//带黄点模判断是否是cp类,cp类按照newMmToPxFn方法重新计算宽高
if (isCp) {
width_px = newMmToPxFn(size.width);
height_px = newMmToPxFn(size.height);
......@@ -774,13 +775,11 @@ export default {
width_px = mmToPx(size.width);
height_px = mmToPx(size.height);
}
x = w;
y = height_px / 2;
rate = height_px / width_px;
// }
if (this.newDesktopDevice == 3) {
//惠立彩 直接获取图片原始像素进行技术
const scale = bh / data.height;
width_px = data.width * scale;
height_px = data.height * scale;
......@@ -822,16 +821,20 @@ export default {
isCp ? that.ev("x_center") : that.ev("cover");
if (isCut) that.ev("cover");
this.$nextTick(async () => {
//等图片铺上网格后判断是否超过网格
const {
isImageBiggerThanGrid,
hasOutsideValidPixel,
} = await checkImageOutsideGrid();
if (isImageBiggerThanGrid && hasOutsideValidPixel) {
//图大于台版且超过台版有素材
this.isOver = hasOutsideValidPixel;
} else if (!isImageBiggerThanGrid) {
//图小于台版
this.isOver = isImageBiggerThanGrid;
} else if (isImageBiggerThanGrid && !hasOutsideValidPixel) {
//图大于台版且超过台版没有有素材
this.isOver = hasOutsideValidPixel;
}
});
......@@ -845,9 +848,6 @@ export default {
addFile(file, callback) {
let that = this;
let bw = document.getElementById("line").clientWidth;
console.log("addFile");
// let bh = document.getElementById("line").clientHeight;
that.$nextTick(() => {
that.getImageSize(file.url).then((data) => {
let w = document.getElementById("line").clientWidth / 2;
......@@ -864,7 +864,6 @@ export default {
h: bw * (2 / 3) * rate,
r: 0,
});
// console.log(570, that.imgList);
that.selectIndex = that.imgList.length - 1;
that.showImgSetting = true;
callback && callback(file);
......@@ -984,12 +983,10 @@ export default {
}
}),
);
// console.log("processQueue", processQueue);
// 等待所有异步操作完成
await new Promise((resolve) => setTimeout(resolve, 100));
const newMap = new Map(processQueue.map((el) => [el.designId, el]));
console.log("newMap", newMap);
this.selectImgList.forEach((el) => {
if (newMap.has(el.designId)) {
......@@ -1009,16 +1006,12 @@ export default {
this.selectIndex = -1;
}
}
console.log("this.selectImgList", this.selectImgList);
this.checkList = [];
this.getBackFile({ files: [this.selectImgList[0]] });
} catch (error) {
console.error("错误", error);
}
},
// startLoading,
// endLoading,
handleClick(event) {
// 获取点击的元素
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment