优化小票打印

This commit is contained in:
gyq 2024-07-31 18:14:23 +08:00
parent 49cabfed21
commit f393299f0f
11 changed files with 88 additions and 161 deletions

View File

@ -2,10 +2,10 @@
ENV = test
#测试ws
VITE_API_WSS = 'wss://wxcashiertest.sxczgkj.cn/client'
# VITE_API_WSS = 'wss://wxcashiertest.sxczgkj.cn/client'
# 正式ws
# VITE_API_WSS = 'wss://cashier.sxczgkj.cn/client'
VITE_API_WSS = 'wss://cashier.sxczgkj.cn/client'
# 正式 php
VITE_API_PHP_URL = 'http://czgdoumei.sxczgkj.com/index.php/api'
@ -17,7 +17,7 @@ VITE_API_PHP_URL = 'http://czgdoumei.sxczgkj.com/index.php/api'
VITE_API_KP_URL = 'https://invoice.sxczgkj.cn/api'
# 测试
VITE_API_URL = 'https://cashier-client.sxczgkj.cn/cashier-client'
# VITE_API_URL = 'https://cashier-client.sxczgkj.cn/cashier-client'
# 正式
# VITE_API_URL = 'https://cashierclient.sxczgkj.cn/cashier-client'
VITE_API_URL = 'https://cashierclient.sxczgkj.cn/cashier-client'

View File

@ -1,115 +1 @@
"use strict";
const path = require("path");
const electron = require("electron");
const os = require("os");
let win;
electron.app.whenReady().then(() => {
win = new electron.BrowserWindow({
title: "银收客",
width: 1024,
height: 768,
fullscreenable: true,
fullscreen: process.env.VITE_DEV_SERVER_URL ? false : true,
simpleFullscreen: true,
frame: process.env.VITE_DEV_SERVER_URL ? true : false,
webPreferences: {
// 集成网页和 Node.js也就是在渲染进程中可以调用 Node.js 方法
nodeIntegration: true,
contextIsolation: false
}
});
if (process.env.VITE_DEV_SERVER_URL) {
win.loadURL(process.env.VITE_DEV_SERVER_URL);
} else {
win.loadFile(path.resolve(__dirname, "../dist/index.html"));
}
electron.app.on("activate", () => {
if (electron.BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
electron.ipcMain.on("quitHandler", (_, msg) => {
win = null;
electron.app.exit();
});
electron.ipcMain.on("getPrintList", () => {
win.webContents.getPrintersAsync().then((res) => {
win.webContents.send("printList", res);
});
});
electron.ipcMain.on("getOSmacSync", () => {
let mac = "";
if (os.networkInterfaces().WLAN) {
mac = os.networkInterfaces().WLAN[0].mac;
console.log("wlan.mac===", mac);
} else {
mac = os.networkInterfaces()["以太网"][0].mac;
console.log("以太网.mac===", mac);
}
win.webContents.send("getOSmacRes", mac);
});
const tagPrintWin = new electron.BrowserWindow({
show: false,
width: 360,
height: 240,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
if (process.env.VITE_DEV_SERVER_URL) {
tagPrintWin.loadFile(path.join(__dirname, "../public/tag_print.html"));
} else {
tagPrintWin.loadFile(path.resolve(__dirname, "../dist/tag_print.html"));
}
electron.ipcMain.on("printerTagSync", (event, arg) => {
console.log(arg);
tagPrintWin.webContents.send("getParams", arg);
});
electron.ipcMain.on("printTagStart", (event, arg) => {
const _parmas = JSON.parse(arg);
let name = _parmas.deviceName;
tagPrintWin.webContents.print({
silent: true,
deviceName: name,
pageSize: {
width: 45e3,
height: 3e4
},
scaleFactor: 80,
landscape: false,
margins: {
marginType: "none",
top: 0,
bottom: 0,
left: 0,
right: 0
},
dpi: {
horizontal: 203,
vertical: 203
}
});
});
const gotTheLock = electron.app.requestSingleInstanceLock();
if (!gotTheLock) {
electron.app.quit();
} else {
electron.app.on("second-instance", (event, commandLine, workingDirectory) => {
if (win) {
if (win.isMinimized())
win.restore();
win.focus();
win.show();
}
});
}
win.on("close", (e) => {
e.preventDefault();
win.webContents.send("showCloseDialog");
});
});
electron.app.on("window-all-closed", () => {
if (process.platform !== "darwin")
electron.app.quit();
});
"use strict";const s=require("path"),e=require("electron"),a=require("os");let n;e.app.whenReady().then(()=>{n=new e.BrowserWindow({title:"银收客",width:1024,height:768,fullscreenable:!0,fullscreen:!process.env.VITE_DEV_SERVER_URL,simpleFullscreen:!0,frame:!!process.env.VITE_DEV_SERVER_URL,webPreferences:{nodeIntegration:!0,contextIsolation:!1}}),process.env.VITE_DEV_SERVER_URL?n.loadURL(process.env.VITE_DEV_SERVER_URL):n.loadFile(s.resolve(__dirname,"../dist/index.html")),e.app.on("activate",()=>{e.BrowserWindow.getAllWindows().length===0&&createWindow()}),e.ipcMain.on("quitHandler",(t,o)=>{n=null,e.app.exit()}),e.ipcMain.on("getPrintList",()=>{n.webContents.getPrintersAsync().then(t=>{n.webContents.send("printList",t)})}),e.ipcMain.on("getOSmacSync",()=>{let t="";a.networkInterfaces().WLAN?(t=a.networkInterfaces().WLAN[0].mac,console.log("wlan.mac===",t)):(t=a.networkInterfaces().以太网[0].mac,console.log("以太网.mac===",t)),n.webContents.send("getOSmacRes",t)});const i=new e.BrowserWindow({show:!1,width:360,height:240,webPreferences:{nodeIntegration:!0,contextIsolation:!1}});process.env.VITE_DEV_SERVER_URL?i.loadFile(s.join(__dirname,"../public/tag_print.html")):i.loadFile(s.resolve(__dirname,"../dist/tag_print.html")),e.ipcMain.on("printerTagSync",(t,o)=>{console.log(o),i.webContents.send("getParams",o)}),e.ipcMain.on("printTagStart",(t,o)=>{let l=JSON.parse(o).deviceName;i.webContents.print({silent:!0,deviceName:l,pageSize:{width:45e3,height:3e4},scaleFactor:80,landscape:!1,margins:{marginType:"none",top:0,bottom:0,left:0,right:0},dpi:{horizontal:203,vertical:203}})}),e.app.requestSingleInstanceLock()?e.app.on("second-instance",(t,o,r)=>{n&&(n.isMinimized()&&n.restore(),n.focus(),n.show())}):e.app.quit(),n.on("close",t=>{t.preventDefault(),n.webContents.send("showCloseDialog")})});e.app.on("window-all-closed",()=>{process.platform!=="darwin"&&e.app.quit()});

View File

@ -49,8 +49,6 @@ import more from '@/components/more.vue'
import callNumber from './callNumber.vue'
import work from '@/views/work/index.vue'
const emits = defineEmits(['connectWsHandle'])
const socketStore = useSocket()
const route = useRoute()
@ -108,7 +106,7 @@ function openCall() {
// ws
function connectWsHandle() {
if (socketStore.online) return
emits('connectWsHandle')
window.onload()
}
defineExpose({

View File

@ -3,6 +3,7 @@ import getLodop from "./LodopFuncs.js";
* 打印订单发票
*/
export default (data) => {
console.log("data.deviceName===", data.deviceName);
let LODOP = getLodop();
LODOP.PRINT_INIT("打印小票");
// 设置打印纸大小D
@ -13,13 +14,14 @@ export default (data) => {
LODOP.SET_PRINTER_INDEX(data.deviceName);
// 文字内容
let html = `
<div style="padding-left: 20px;">
<div style="height: 100px;"></div>
<div style="width: 100%;font-size: 16px;display:flex;justify-content:center;">
请使用微信扫码下载发票二维码有效期30天超过自动失效
</div>
<div style="height: 50px;"></div>
</div>
<div>.</div>
<div>.</div>
<div>.</div>
<div>.</div>
`;
setTimeout(() => {

View File

@ -3,6 +3,7 @@ import getLodop from "./LodopFuncs.js";
* 打印交班小票
*/
export default (data) => {
console.log("data.deviceName===", data.deviceName);
let LODOP = getLodop();
LODOP.PRINT_INIT("打印小票");
// 设置打印纸大小D
@ -17,7 +18,7 @@ export default (data) => {
<div style="font-size: 16px;display: flex; justify-content:center;margin-top:6px;">
交班小票
</div>
<div style="margin-top: 30px;font-size: 12px;">
<div style="font-size: 12px;margin-top:50px;">
当班时间${data.startTime}
</div>
<div style="font-size: 12px;">
@ -91,9 +92,8 @@ export default (data) => {
<div style="font-size: 12px;margin-top: 4px;">商品数据</div>
<table class="table" style="width: 100%;">
<tr>
<td style="font-size: 12px;width:50%;">商品</td>
<td style="font-size: 12px;width:75%;">商品</td>
<td style="font-size: 12px;width:25%;">数量</td>
<td style="font-size: 12px;width:25%;">总计</td>
</tr>
`;
@ -102,13 +102,10 @@ export default (data) => {
for (let item of data.productInfos) {
tableBody += `
<tr>
<td style="font-size: 12px;width:50%;">
<td style="font-size: 12px;width:75%;">
<div>${item.productName}</div>
</td>
<td style="font-size: 12px;width:25%;">${item.num}</td>
<td style="font-size: 12px;width:25%;">
${item.amount}
</td>
</tr>
`;
}
@ -141,18 +138,17 @@ export default (data) => {
<span>应交金额</span>
<span>${data.payable}</span>
</div>
<div style="font-size: 12px;">
<span>上交金额</span>
<span>${data.handIn}</span>
</div>
<div style="margin-top: 20px; font-size: 12px;">
<span>总订单数</span>
<span>${data.orderNum}</span>
</div>
<div style="padding-bottom: 50px;font-size: 12px;">
<div style="font-size: 12px;">
打印时间${data.printTime}
</div>
<div style="height: 50px;"></div>
<div>.</div>
<div>.</div>
<div>.</div>
<div>.</div>
`;
let lastHtml = `${html}${payInfos}${memberTitle}${memberData}${productCategoriesTabHead}${productCategoriesTableBody}${tabHead}${tableBody}${str}`;

View File

@ -3,6 +3,8 @@ import getLodop from "./LodopFuncs.js";
* 打印订单小票
*/
export default (data) => {
console.log(data);
console.log("data.deviceName===", data.deviceName);
let LODOP = getLodop();
LODOP.PRINT_INIT("打印小票");
// 设置打印纸大小D
@ -14,12 +16,14 @@ export default (data) => {
let t2 = (100 - t1) / 3;
let html = `
<div style="font-size: 30px;display:flex;justify-content:center;">
${data.shop_name}
${data.shop_name}
</div>
<div style="font-size: 16px;display: flex; justify-content:center;margin-top:6px;">
结算单${data.orderInfo.masterId ? data.orderInfo.masterId : ""}
${data.isBefore ? "预" : ""}结算单${
data.orderInfo.masterId ? data.orderInfo.masterId : ""
}
</div>
<div style="font-size: 16px;display: flex; justify-content:center;margin-top:6px;">
<div style="font-size: 16px;display: flex; justify-content:center;margin-top:20px;">
${data.orderInfo.outNumber ? data.orderInfo.outNumber : ""}
</div>
<div style="margin-top: 30px;font-size: 12px;">
@ -31,7 +35,9 @@ export default (data) => {
<div style="margin-top: 4px;font-size: 12px;">
收银员${data.loginAccount}
</div>
<div style="margin-top: 6px;margin-bottom: 6px;border-bottom:1px dashed #000;"></div>
<div style="margin-top: 6px;margin-bottom: 6px;width: 100%">
<hr/>
</div>
<table class="table" style="width: 100%;">
<tr>
<td style="font-size: 12px;width:${t1}%;">品名</td>
@ -47,7 +53,11 @@ export default (data) => {
<tr>
<td style="font-size: 12px;width:${t1}%;">
<div>${item.name}</div>
<div class="sku">规格${item.skuName || ""}</div>
${
item.skuName
? `<div class="sku">规格:${item.skuName}</div>`
: ""
}
</td>
<td style="font-size: 12px;width:${t2}%;">${item.salePrice}</td>
<td style="font-size: 12px;width:${t2}%;">${item.number}</td>
@ -60,7 +70,9 @@ export default (data) => {
let str = `
</table>
<div style="margin-top: 6px; border-bottom:1px dashed #000;"></div>
<div style="margin-top: 6px;margin-bottom: 6px;width: 100%">
<hr/>
</div>
<div style="margin-top: 6px; font-size: 22px;display:flex;justify-content: space-between;">
<span>应收</span>
<span>${data.amount}</span>
@ -69,12 +81,17 @@ export default (data) => {
<span>余额</span>
<span>0.00</span>
</div>
<div style="margin-top: 6px; border-bottom:1px dashed #000;"></div>
<div style="margin-top: 4px; font-size: 12px;">备注${data.remark}</div>
<div style="margin-top: 4px; padding-bottom: 50px;font-size: 12px;">
<div style="margin-top: 6px;margin-bottom: 6px;width: 100%">
<hr/>
</div>
<div style="margin-top: 4px; font-size: 16px;font-weight: bold;">备注${data.remark}</div>
<div style="margin-top: 4px; font-size: 12px;">
打印时间${data.printTime}
</div>
<div style="height: 50px;"></div>
<div>.</div>
<div>.</div>
<div>.</div>
<div>.</div>
`;
let lastHtml = `${html}${table}${str}`;

View File

@ -125,15 +125,11 @@ export const usePrint = defineStore({
}, 800);
},
// 添加小票打印对列表数据
pushReceiptData(props) {
if (
this.deviceNoteList.length &&
this.checkLocalPrint(this.deviceNoteList[0].config.deviceName)
) {
console.log(props);
pushReceiptData(props, isDevice = true) {
console.log("pushReceiptData===", props);
if (!isDevice) {
// 测试打印,无需校验本地打印机
const store = useUser();
props.deviceName = this.deviceNoteList[0].config.deviceName;
props.shop_name = store.userInfo.shopName;
props.loginAccount = store.userInfo.loginAccount;
props.createdAt = dayjs(props.createdAt).format("YYYY-MM-DD HH:mm:ss");
@ -146,7 +142,28 @@ export const usePrint = defineStore({
this.receiptList.push(props);
this.startReceiptPrint();
} else {
console.log("订单小票:没有小票打印机");
if (
this.deviceNoteList.length &&
this.checkLocalPrint(this.deviceNoteList[0].config.deviceName)
) {
const store = useUser();
props.deviceName = this.deviceNoteList[0].config.deviceName;
props.shop_name = store.userInfo.shopName;
props.loginAccount = store.userInfo.loginAccount;
props.createdAt = dayjs(props.createdAt).format(
"YYYY-MM-DD HH:mm:ss"
);
props.printTime = dayjs().format("YYYY-MM-DD HH:mm:ss");
if (!props.orderInfo.masterId) {
props.orderInfo.masterId = props.orderInfo.tableName;
}
props.orderInfo.outNumber = props.outNumber;
this.receiptList.push(props);
this.startReceiptPrint();
} else {
console.log("订单小票:没有小票打印机");
}
}
},
// 开始打印小票

View File

@ -57,7 +57,14 @@ export const useSocket = defineStore({
if (this.ws == null) {
console.log("创建新的ws连接");
this.ws = new ReconnectingWebSocket(wsUrl);
const protocols = []; // 可选的子协议数组
const options = {
// 自动重新连接的选项(可选)
connectionTimeout: 1000,
maxRetries: 100,
};
this.ws = new ReconnectingWebSocket(wsUrl, protocols, options);
} else {
console.log("重新连接ws");
this.wsReconnect();

View File

@ -178,12 +178,12 @@ const printData = reactive({
}
],
amount: '30.00',
remark: '',
remark: '给我多放点辣椒,谢谢老板',
orderInfo: {
masterId: '#002',
orderNo: '202404021023542223445'
},
deviceName: form.value.config.deviceName,
deviceName: '',
createdAt: '2024-04-02 10:15',
printTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
});
@ -203,8 +203,9 @@ function printHandle() {
return;
}
printDataLoading.value = true
printData.deviceName = form.value.config.deviceName
printData.printTime = dayjs().format('YYYY-MM-DD HH:mm:ss')
printStore.pushReceiptData(printData)
printStore.pushReceiptData(printData, false)
setTimeout(() => {
printDataLoading.value = false
}, 1500)

View File

@ -125,6 +125,7 @@ const printHandle = _.throttle(async function () {
const data = {
shop_name: store.userInfo.shopName,
loginAccount: store.userInfo.loginAccount,
isBefore: true,
carts: props.cart,
amount: props.amount,
remark: props.remark,

View File

@ -212,10 +212,12 @@ const exit = async () => {
data = await handoverData({
id: infoData.value.id
})
data.printTime = dayjs().format('YYYY-MM-DD HH:mm:ss')
data.printShop = isPrint.value
printStore.printWork(data)
// return
await loginlogout({
status: 1
})