386 lines
12 KiB
JavaScript
386 lines
12 KiB
JavaScript
import { defineStore } from "pinia";
|
||
import { ipcRenderer } from "electron";
|
||
import { useUser } from "@/store/user.js";
|
||
import dayjs from "dayjs";
|
||
import receiptPrint from "@/components/lodop/receiptPrint.js";
|
||
import lodopPrintWork from "@/components/lodop/lodopPrintWork.js";
|
||
import invoicePrint from "@/components/lodop/invoicePrint.js";
|
||
import refundPrint from "@/components/lodop/refundPrint.js";
|
||
import { printerList } from "@/api/account.js";
|
||
import { useSocket } from './socket.js';
|
||
|
||
export const usePrint = defineStore("print", {
|
||
state: () => ({
|
||
isPrintService: false,
|
||
printServiceTimer: null,
|
||
printServiceTimerCount: 0,
|
||
printServiceTimerMaxCount: 10,
|
||
showPrintNotService: false,
|
||
localDevices: [],
|
||
deviceNoteList: [],
|
||
deviceLableList: [],
|
||
labelList: [],
|
||
printTimer: null,
|
||
receiptList: [],
|
||
receiptTimer: null,
|
||
}),
|
||
|
||
actions: {
|
||
async init() {
|
||
ipcRenderer.send("getPrintList");
|
||
ipcRenderer.on("printList", (event, arg) => {
|
||
this.localDevices = arg;
|
||
});
|
||
|
||
try {
|
||
const res = await printerList();
|
||
this.deviceNoteList = res.records.filter(
|
||
(item) => item.status && item.subType == "cash"
|
||
);
|
||
this.deviceLableList = res.records.filter(
|
||
(item) => item.status && item.subType == "label"
|
||
);
|
||
} catch (error) {
|
||
console.error("获取打印机列表失败", error);
|
||
}
|
||
this.checkPrintService();
|
||
},
|
||
|
||
checkPrintService() {
|
||
this.printServiceTimer = setInterval(() => {
|
||
if (
|
||
typeof LODOP !== "undefined" &&
|
||
LODOP.webskt &&
|
||
LODOP.webskt.readyState == 1
|
||
) {
|
||
this.isPrintService = true;
|
||
clearInterval(this.printServiceTimer);
|
||
this.printServiceTimer = null;
|
||
} else {
|
||
this.printServiceTimerCount++;
|
||
if (this.printServiceTimerCount >= this.printServiceTimerMaxCount) {
|
||
this.isPrintService = false;
|
||
this.showPrintNotService = true;
|
||
clearInterval(this.printServiceTimer);
|
||
this.printServiceTimer = null;
|
||
}
|
||
}
|
||
}, 1000);
|
||
},
|
||
|
||
// 检查打印机是否可用
|
||
checkPrinterAvailable(printer) {
|
||
if (printer.connectionType === "局域网") {
|
||
const ipReg = /^(\d{1,3}\.){3}\d{1,3}$/;
|
||
return ipReg.test(printer.address);
|
||
}
|
||
|
||
if (printer.connectionType === "usb") {
|
||
return this.localDevices.some(item => item.name === printer.address);
|
||
}
|
||
return false;
|
||
},
|
||
|
||
// ==============================
|
||
// 最终完美版 → 空数组打印全部
|
||
// ==============================
|
||
pushReceiptData(props, isDevice = true) {
|
||
if (!isDevice) {
|
||
this.receiptList.push(props);
|
||
this.startReceiptPrint();
|
||
return;
|
||
}
|
||
|
||
const validPrinters = this.deviceNoteList.filter(p => {
|
||
return this.checkPrinterAvailable(p) && this.isPrintService;
|
||
});
|
||
|
||
if (validPrinters.length === 0) {
|
||
console.log("无可用小票打印机");
|
||
return;
|
||
}
|
||
|
||
const store = useUser();
|
||
|
||
validPrinters.forEach(printer => {
|
||
let filterCarts = [];
|
||
|
||
// ======================================
|
||
// ✅ 核心:分类为空数组 → 打印全部菜品
|
||
// ======================================
|
||
if (!printer.categoryList || printer.categoryList.length === 0) {
|
||
filterCarts = props.carts || [];
|
||
} else {
|
||
// 有分类 → 只打印对应分类
|
||
filterCarts = (props.carts || []).filter(item => {
|
||
return printer.categoryList.includes(item.categoryId);
|
||
});
|
||
}
|
||
|
||
if (filterCarts.length === 0) return;
|
||
|
||
const printData = {
|
||
...props,
|
||
carts: filterCarts,
|
||
deviceId: printer.id,
|
||
deviceName: printer.address,
|
||
printerName: printer.name,
|
||
connectionType: printer.connectionType,
|
||
shop_name: store.shopInfo.shopName,
|
||
loginAccount: store.userInfo.name,
|
||
createdAt: dayjs(props.createdAt).format("YYYY-MM-DD HH:mm:ss"),
|
||
printTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
||
};
|
||
|
||
if (!printData.orderInfo.masterId) {
|
||
printData.orderInfo.masterId = printData.orderInfo.tableName;
|
||
}
|
||
printData.orderInfo.outNumber = printData.outNumber;
|
||
if (!printData.discountAmount) {
|
||
printData.discountAmount = printData.amount;
|
||
}
|
||
|
||
this.receiptList.push(printData);
|
||
});
|
||
|
||
if (this.receiptList.length > 0) {
|
||
this.startReceiptPrint();
|
||
}
|
||
},
|
||
|
||
// ==============================
|
||
// 打印执行(USB/局域网自动区分)
|
||
// ==============================
|
||
async startReceiptPrint() {
|
||
try {
|
||
const socketStore = useSocket();
|
||
const userStore = useUser();
|
||
if (this.receiptTimer !== null) return;
|
||
|
||
this.receiptTimer = setInterval(() => {
|
||
if (!this.receiptList.length) {
|
||
clearInterval(this.receiptTimer);
|
||
this.receiptTimer = null;
|
||
return;
|
||
}
|
||
|
||
const printData = this.receiptList[0];
|
||
try {
|
||
if (printData.connectionType === "局域网") {
|
||
ipcRenderer.send('networkPrint', JSON.stringify({
|
||
printerIp: printData.deviceName,
|
||
orderData: printData
|
||
}));
|
||
} else {
|
||
receiptPrint(printData);
|
||
}
|
||
|
||
const syncData = {
|
||
type: "cashier",
|
||
operate_type: "order_print_status",
|
||
table_code: printData.orderInfo.tableCode,
|
||
account: userStore.shopInfo.account,
|
||
print_status: "1",
|
||
order_id: printData.orderInfo.id,
|
||
print_id: printData.deviceId,
|
||
shop_id: printData.orderInfo.shopId,
|
||
};
|
||
socketStore.ws.send(JSON.stringify(syncData));
|
||
console.log("✅ 打印成功:", printData.deviceName, "菜品数:", printData.carts.length);
|
||
} catch (error) {
|
||
console.error("❌ 打印失败:", printData.deviceName, error);
|
||
} finally {
|
||
this.receiptList.splice(0, 1);
|
||
}
|
||
}, 2000);
|
||
} catch (error) {
|
||
console.log("打印定时器异常", error);
|
||
}
|
||
},
|
||
|
||
// ————————————————————————————————
|
||
// 以下原有代码完全不动(除了printWork方法)
|
||
// ————————————————————————————————
|
||
checkLocalPrint(address) {
|
||
let print = "";
|
||
for (let item of this.localDevices) {
|
||
if (item.name == address) {
|
||
print = item;
|
||
}
|
||
}
|
||
if (!print.name) {
|
||
return false;
|
||
} else {
|
||
return true;
|
||
}
|
||
},
|
||
|
||
labelPrint(props) {
|
||
const store = useUser();
|
||
if (
|
||
this.deviceLableList.length &&
|
||
this.checkLocalPrint(this.deviceLableList[0].address)
|
||
) {
|
||
let pids = this.deviceLableList[0].categoryList;
|
||
let count = 0;
|
||
let sum = 0;
|
||
props.carts.map((item) => {
|
||
if (pids.some((el) => el == item.categoryId)) {
|
||
for (let i = 0; i < item.number; i++) {
|
||
sum++;
|
||
}
|
||
}
|
||
});
|
||
props.carts.map((item) => {
|
||
if (pids.some((el) => el == item.categoryId)) {
|
||
for (let i = 0; i < item.number; i++) {
|
||
count++;
|
||
this.labelList.push({
|
||
outNumber: props.outNumber,
|
||
name: item.name,
|
||
skuName: item.skuName,
|
||
masterId: props.orderInfo.tableName,
|
||
deviceName: this.deviceLableList[0].address,
|
||
createdAt: dayjs(props.createdAt).format("YYYY-MM-DD HH:mm:ss"),
|
||
isPrint: false,
|
||
count: `${count}/${sum}`,
|
||
ticketLogo: store.shopInfo.ticketLogo,
|
||
});
|
||
}
|
||
}
|
||
});
|
||
this.startLabelPrint();
|
||
} else {
|
||
console.log("标签打印:未在本机查询到打印机");
|
||
}
|
||
},
|
||
|
||
startLabelPrint() {
|
||
if (this.printTimer != null) return;
|
||
this.printTimer = setInterval(() => {
|
||
let item = "";
|
||
if (!this.labelList.length) {
|
||
clearInterval(this.printTimer);
|
||
this.printTimer = null;
|
||
} else {
|
||
item = this.labelList[0];
|
||
if (!item.isPrint) {
|
||
ipcRenderer.send("printerTagSync", JSON.stringify(item));
|
||
this.labelList[0].isPrint = true;
|
||
this.labelList.splice(0, 1);
|
||
}
|
||
}
|
||
}, 2000);
|
||
},
|
||
|
||
// 打印交班小票(优化:1. 新增handoverSwitch=1才打印 2. 兼容局域网打印机)
|
||
printWork(data) {
|
||
// 筛选条件:
|
||
// 1. 状态启用 + 小票类型 + handoverSwitch=1
|
||
// 2. 打印机可用
|
||
// 3. 打印服务正常
|
||
const validPrinters = this.deviceNoteList.filter(p => {
|
||
return p.status
|
||
&& p.subType === "cash"
|
||
&& p.handoverSwitch === 1 // 新增:只有handoverSwitch为1的打印机才打印交班小票
|
||
&& this.checkPrinterAvailable(p)
|
||
&& this.isPrintService;
|
||
});
|
||
|
||
if (validPrinters.length === 0) {
|
||
console.log("交班小票:无符合条件的可用打印机(handoverSwitch≠1 或 打印机不可用)");
|
||
return;
|
||
}
|
||
|
||
// 遍历符合条件的打印机打印
|
||
validPrinters.forEach(printer => {
|
||
const printData = {
|
||
...data,
|
||
deviceId: printer.id,
|
||
deviceName: printer.address,
|
||
connectionType: printer.connectionType,
|
||
printTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
||
};
|
||
|
||
try {
|
||
// 区分局域网和USB打印机
|
||
if (printer.connectionType === "局域网") {
|
||
// 局域网打印机:使用networkPrint指令
|
||
ipcRenderer.send('printHandoverReceipt', JSON.stringify({
|
||
printerIp: printer.address,
|
||
handoverData: printData
|
||
}));
|
||
} else {
|
||
// USB打印机:使用原有LODOP方式
|
||
lodopPrintWork(printData);
|
||
}
|
||
console.log("✅ 交班小票打印成功:", printer.address);
|
||
} catch (error) {
|
||
console.error("❌ 交班小票打印失败:", printer.address, error);
|
||
}
|
||
});
|
||
},
|
||
|
||
printInvoice(data) {
|
||
if (
|
||
this.deviceNoteList.length &&
|
||
this.checkLocalPrint(this.deviceNoteList[0].address)
|
||
) {
|
||
data.deviceName = this.deviceNoteList[0].address;
|
||
invoicePrint(data);
|
||
} else {
|
||
console.log("订单发票:未在本机查询到打印机");
|
||
}
|
||
},
|
||
// 退菜/退款
|
||
printRefund(data) {
|
||
// 筛选条件:
|
||
// 1. 状态启用 + 小票类型
|
||
// 2. 打印机可用
|
||
// 3. 打印服务正常
|
||
const validPrinters = this.deviceNoteList.filter(p => {
|
||
return p.status
|
||
&& p.subType === "cash"
|
||
&& this.checkPrinterAvailable(p)
|
||
&& this.isPrintService;
|
||
});
|
||
|
||
if (validPrinters.length === 0) {
|
||
console.log("退单小票:无符合条件的可用打印机");
|
||
return;
|
||
}
|
||
|
||
const store = useUser();
|
||
// 遍历符合条件的打印机打印
|
||
validPrinters.forEach(printer => {
|
||
const printData = {
|
||
...data,
|
||
deviceId: printer.id,
|
||
deviceName: printer.address,
|
||
printerName: printer.name,
|
||
connectionType: printer.connectionType,
|
||
shop_name: store.shopInfo.shopName,
|
||
loginAccount: store.userInfo.name,
|
||
printTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
||
};
|
||
|
||
try {
|
||
// 区分局域网和USB打印机
|
||
if (printer.connectionType === "局域网") {
|
||
// 局域网打印机:使用networkPrint指令
|
||
ipcRenderer.send('printRefund', JSON.stringify({
|
||
printerIp: printer.address,
|
||
orderData: printData
|
||
}));
|
||
} else {
|
||
// USB打印机:使用原有LODOP方式
|
||
refundPrint(printData);
|
||
}
|
||
console.log("✅ 退单小票打印成功:", printer.address);
|
||
} catch (error) {
|
||
console.error("❌ 退单小票打印失败:", printer.address, error);
|
||
}
|
||
});
|
||
}
|
||
},
|
||
}); |