This commit is contained in:
weipengfei 2024-05-15 18:33:50 +08:00
parent 9054d93b0d
commit 7d82a14b0f
7 changed files with 438 additions and 33 deletions

View File

@ -3,5 +3,5 @@ VITE_NOW_TYPE = 'dist'
VITE_PUSH_URL = 'ws://192.168.1.22:8787' VITE_PUSH_URL = 'ws://192.168.1.22:8787'
VITE_BASE_URL = 'http://192.168.1.22:8546' # VITE_BASE_URL = 'http://192.168.1.22:8546'
# VITE_BASE_URL = 'https://erp.lihaink.cn' VITE_BASE_URL = 'https://erp.lihaink.cn'

View File

@ -39,14 +39,14 @@
/* 大屏幕 */ /* 大屏幕 */
@media screen and (min-width: 993px) and (max-width: 1336px) { @media screen and (min-width: 993px) and (max-width: 1336px) {
html { html {
font-size: 11px; font-size: 14px;
} }
} }
/* 大屏幕 */ /* 大屏幕 */
@media screen and (min-width: 1336px) and (max-width: 1900px) { @media screen and (min-width: 1336px) and (max-width: 1900px) {
html { html {
font-size: 12px; font-size: 15px;
} }
} }
/* 大屏幕 */ /* 大屏幕 */

View File

@ -14,8 +14,8 @@ const connection = new Push({
// user-1 // user-1
const user_channel = connection.subscribe(`user-${userStore.userInfo.id}`); const user_channel = connection.subscribe(`store_merchant_${userStore.userInfo.merchant.mer_id}`);
// const user_channel = connection.subscribe(`user-${1}`); // const user_channel = connection.subscribe(`store_merchant_${1}`);
// user-2message // user-2message
user_channel.on('message', function (data) { user_channel.on('message', function (data) {

View File

@ -12,7 +12,7 @@ const navTo = (name) => {
const list = ref([ const list = ref([
{ name: "saleHome", title: "收银", ico: "Sell", count: 0 }, { name: "saleHome", title: "收银", ico: "Sell", count: 0 },
{ name: "saleOrder", title: "收银订单", ico: "DataLine", count: 0 }, { name: "saleOrder", title: "收银订单", ico: "DataLine", count: 0 },
{ name: "order", title: "待提采购", ico: "DataAnalysis", count: 0 }, { name: "order", title: "摊贩订单", ico: "DataAnalysis", count: 2 },
{ name: "purchaseOrder", title: "采购订单", ico: "Tickets", count: 0 }, { name: "purchaseOrder", title: "采购订单", ico: "Tickets", count: 0 },
// { name: "test", title: "", ico: "Tickets", count: 0 }, // { name: "test", title: "", ico: "Tickets", count: 0 },
]); ]);

View File

@ -5,8 +5,11 @@ import { info, logout } from "@/api/user.js";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import mitt from "@/utils/mitt.js"; import mitt from "@/utils/mitt.js";
import { usePrintStore } from "@/store/print.js";
import * as Esc from "@/utils/EscPostUtils.js";
const userStore = useUserStore(); const userStore = useUserStore();
const printStore = usePrintStore();
const merInfo = ref({}); const merInfo = ref({});
merInfo.value = userStore.userInfo; merInfo.value = userStore.userInfo;
@ -18,24 +21,48 @@ const onLogout = () => {
router.push("/login"); router.push("/login");
}; };
const is_connect = ref(false); // const onRefresh = () => {
window.location.reload();
};
const dialogVisible = ref(false); //
// //
const connect = () => { const connect = () => {
console.log("连接打印机"); console.log("连接打印机");
uni.getEnv((res) => {
if (res.h5) ElMessage.error("请使用APP连接打印机");
else {
printStore.setConnect(false);
dialogVisible.value = false;
uni.postMessage({ uni.postMessage({
data: { data: {
type: "connect", type: "connect",
}, },
}); });
}
});
}; };
let isPrint = false; //
// //
const printReceipt = (content = "") => { const printReceipt = (content = "") => {
console.log("预打印"); console.log("预打印");
// console.log(Esc.inline3(" ", "", "", " ", 1) + "\n");
// console.log(Esc.inline3("2.36 ", "10", "30.00", " ", 1) + "\n");
// return ;
if (isPrint) return;
isPrint = true;
uni.getEnv((res) => { uni.getEnv((res) => {
if (res.h5) ElMessage.error("请使用APP打印小票"); if (res.h5) {
else APPprint(content); ElMessage.error("请使用APP打印小票");
isPrint = false;
} else {
APPprint(content);
setTimeout(() => {
isPrint = false;
}, 4000);
}
}); });
}; };
@ -43,15 +70,47 @@ const printReceipt = (content = "") => {
const APPprint = (content = "") => { const APPprint = (content = "") => {
let str = ""; let str = "";
if (content === "") { if (content === "") {
str += "********************************\n"; // str += "********************************\n";
str += "泸优采-小票\n"; // str += "\n";
str += "单号: CG171565043141139102\n"; // str += ": PF171568087790938356\n";
str += "测试商品1 * 1 \t 1.00元 \n"; // str += " 0.01/kg\n";
str += "测试商品2 * 1 \t 1.00元 \n"; // str += "x 3 \t\t 0.10 \n";
str += "测试商品小黄鸭3 * 1 \t 1.00元 \n"; // str += " 1.33/kg\n";
str += "\n"; // str += "x 10 \t\t 13.30\n";
str += "--------------------------------\n"; // str += " 36.59/\n";
str += "\n"; // str += "x 3 \t\t 106.97\n";
// str += " \t : ¥235.36\n";
// str += "\n";
// str += "--------------------------------\n";
// str += "\n";
str += Esc.Size2(0) + Esc.Center() + Esc.boldFontOn() + "莲花农贸市场" + "\n";
str += Esc.fillLine(" ") + Esc.boldFontOff() + "\n";
str += Esc.Left() + "单号: PF171568087790938356" + "\n";
str += Esc.Left() + "下单时间: 2024-5-15 18:00:32" + "\n";
//
str += Esc.fillLine("=") + "\n";
str += Esc.inline3("单价 ", "数量", "小计", " ", 1) + "\n";
str += Esc.Left() + "白菜 大白菜" + "\n";
str += Esc.inline3("206.36元 ", "10包", "3600.00元", " ", 1) + "\n";
str += Esc.Left() + "白菜 大白菜" + "\n";
str += Esc.inline3("206.36元 ", "10包", "3600.00元", " ", 1) + "\n";
str += Esc.Left() + "白菜 大白菜" + "\n";
str += Esc.inline3("206.36元 ", "10包", "3600.00元", " ", 1) + "\n";
str += Esc.fillLine("=") + "\n";
str += Esc.Left() + "应付款: " + "29.96元" + "\n";
str += Esc.Left() + "实付款: " + "29.96元" + "\n";
str += Esc.Left() + "支付方式: " + "微信支付" + "\n";
str += Esc.Left() + "支付单号: " + "4200002159202405159003084211" + "\n";
str += Esc.fillLine("=") + "\n";
//
str += Esc.fillLine(" ") + "\n";
str += Esc.Center() + "欢迎下次光临!" + "\n";
str += Esc.feedLines(" ") + "\n";
//
str += Esc.cutPaper();
console.log(str);
} else str = content; } else str = content;
uni.postMessage({ uni.postMessage({
data: { data: {
@ -68,8 +127,8 @@ onMounted(() => {
"message", "message",
function (event) { function (event) {
// alert(JSON.stringify(event.data)); // alert(JSON.stringify(event.data));
if(event.data.type === "connect"){ if (event.data.type === "connect") {
is_connect.value = true; printStore.setConnect(true);
ElMessage.success("已连接打印机T58"); ElMessage.success("已连接打印机T58");
} }
}, },
@ -92,27 +151,49 @@ onUnmounted(() => {
></el-image> ></el-image>
</div> </div>
<div class="card-title">里海收银系统</div> <div class="card-title">里海收银系统</div>
<div
style="
margin-left: 1rem;
display: flex;
flex-direction: column;
justify-content: center;
cursor: pointer;
"
>
<el-icon color="#fff" size="18" @click="onRefresh"><Refresh /></el-icon>
</div>
</div> </div>
<div class="card-body"> <div class="card-body">
<div style="margin-right: 1rem"> <div style="margin-right: 1rem">
<el-button @click="mitt.emit('printReceipt')" link type="warning"> <el-button @click="mitt.emit('printReceipt')" type="primary">
打印测试 <span>打印自检</span>
</el-button> </el-button>
</div> </div>
<div style="margin-right: 1rem" v-if="!is_connect"> <div style="margin-right: 1rem" v-if="!printStore.is_connect">
<el-button @click="connect" link type="warning"> <el-button @click="connect" type="warning">
点击自动连接打印机 <span>点击自动连接打印机</span>
</el-button> </el-button>
</div> </div>
<div style="margin-right: 1rem;" v-else @click="ElMessage.success('打印机已经连接啦')">已连接打印机T58</div> <div style="margin-right: 1rem" v-else @click="dialogVisible = true">
已连接打印机T58
</div>
<el-dialog v-model="dialogVisible" title="提示" width="500">
<span>打印机已连接是否重新连接</span>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="connect"> 重新连接 </el-button>
</div>
</template>
</el-dialog>
<el-dropdown trigger="hover"> <el-dropdown trigger="hover">
<div class="el-dropdown-link"> <div class="el-dropdown-link">
<el-avatar :src="merInfo.avatar" icon="user-filled" /> <el-avatar :src="merInfo.avatar" icon="user-filled" />
<div class="info"> <div class="info">
<div> <div>
{{ merInfo.nickname }} {{ merInfo.merchant.mer_name }}
</div> </div>
<div>{{ merInfo.account }}</div> <div>{{ merInfo.merchant.service_phone }}</div>
</div> </div>
<el-icon class="el-icon--right"> <el-icon class="el-icon--right">
<arrow-down /> <arrow-down />

18
src/store/print.js Normal file
View File

@ -0,0 +1,18 @@
import { defineStore } from "pinia"
import { ref } from "vue"
export const usePrintStore = defineStore('print', () => {
const is_connect = ref(localStorage.getItem('is_connect'));
const setConnect = (e)=>{
is_connect.value = e;
localStorage.setItem('is_connect',e);
}
return {
is_connect,
setConnect
}
})

306
src/utils/EscPostUtils.js Normal file
View File

@ -0,0 +1,306 @@
// 打印机纸宽58mm页的宽度384字符宽度为1每行最多盛放32个字符
// 打印机纸宽80mm页的宽度576字符宽度为1每行最多盛放48个字符
const PAGE_WIDTH = 384;
const MAX_CHAR_COUNT_EACH_LINE = 32;
//字符串转字节序列
export function stringToByte(str) {
var bytes = new Array();
var len, c;
len = str.length;
for (var i = 0; i < len; i++) {
c = str.charCodeAt(i);
if (c >= 0x010000 && c <= 0x10FFFF) {
bytes.push(((c >> 18) & 0x07) | 0xF0);
bytes.push(((c >> 12) & 0x3F) | 0x80);
bytes.push(((c >> 6) & 0x3F) | 0x80);
bytes.push((c & 0x3F) | 0x80);
} else if (c >= 0x000800 && c <= 0x00FFFF) {
bytes.push(((c >> 12) & 0x0F) | 0xE0);
bytes.push(((c >> 6) & 0x3F) | 0x80);
bytes.push((c & 0x3F) | 0x80);
} else if (c >= 0x000080 && c <= 0x0007FF) {
bytes.push(((c >> 6) & 0x1F) | 0xC0);
bytes.push((c & 0x3F) | 0x80);
} else {
bytes.push(c & 0xFF);
}
}
return bytes;
}
//字节序列转ASCII码
//[0x24, 0x26, 0x28, 0x2A] ==> "$&C*"
export function byteToString(arr) {
if (typeof arr === 'string') {
return arr;
}
var str = '',
_arr = arr;
for (var i = 0; i < _arr.length; i++) {
var one = _arr[i].toString(2),
v = one.match(/^1+?(?=0)/);
if (v && one.length == 8) {
var bytesLength = v[0].length;
var store = _arr[i].toString(2).slice(7 - bytesLength);
for (var st = 1; st < bytesLength; st++) {
store += _arr[st + i].toString(2).slice(2);
}
str += String.fromCharCode(parseInt(store, 2));
i += bytesLength - 1;
} else {
str += String.fromCharCode(_arr[i]);
}
}
return str;
}
//居中
export function Center() {
var Center = [];
Center.push(27);
Center.push(97);
Center.push(1);
var strCenter = byteToString(Center);
return strCenter;
}
//居左
export function Left() {
var Left = [];
Left.push(27);
Left.push(97);
Left.push(0);
var strLeft = byteToString(Left);
return strLeft;
}
//居右
export function Right() {
var right = [];
Left.push(27);
Left.push(97);
Left.push(2);
var strRight = byteToString(right);
return strRight;
}
//标准字体
export function Size1() {
var Size1 = [];
Size1.push(29);
Size1.push(33);
Size1.push(0);
var strSize1 = byteToString(Size1);
return strSize1;
}
//大号字体
/* 1 n = 0
* 长宽各放大2倍 n = 17 */
export function Size2(n) {
var Size2 = [];
Size2.push(29);
Size2.push(33);
Size2.push(n);
var strSize2 = byteToString(Size2);
return strSize2;
}
// 字体加粗
export function boldFontOn() {
var arr = []
arr.push(27)
arr.push(69)
arr.push(1)
var cmd = byteToString(arr);
return cmd
}
// 取消字体加粗
export function boldFontOff() {
var arr = []
arr.push(27)
arr.push(69)
arr.push(0)
var cmd = byteToString(arr);
return cmd
}
// 打印并走纸n行
export function feedLines(n = 1) {
var feeds = []
feeds.push(27)
feeds.push(100)
feeds.push(n)
var printFeedsLines = byteToString(feeds);
return printFeedsLines
}
// 切纸
export function cutPaper() {
var cut = []
cut.push(29)
cut.push(86)
cut.push(49)
var cutType = byteToString(cut);
return cutType
}
// 开钱箱
export function open_money_box() {
var open = []
open.push(27)
open.push(112)
open.push(0)
open.push(60)
open.push(255)
var openType = byteToString(open)
return openType
}
// 初始化打印机
export function init() {
var arr = []
arr.push(27)
arr.push(68)
arr.push(0)
var str = byteToString(arr)
return str
}
/*
设置左边距
len:
*/
export function setLeftMargin(len = 1) {
var arr = []
arr.push(29)
arr.push(76)
arr.push(len)
var str = byteToString(arr)
return str
}
// 设置打印区域宽度
export function setPrintAreaWidth(width) {
var arr = []
arr.push(29)
arr.push(87)
arr.push(width)
var str = byteToString(arr)
return str
}
/**
* @param str
* @returns {boolean} str是否全是中文
*/
export function isChinese(str) {
return /^[\u4e00-\u9fa5]$/.test(str);
}
// str是否全含中文或者中文标点
export function isHaveChina(str) {
if (escape(str).indexOf("%u") < 0) {
return 0
} else {
return 1
}
}
/**
* 返回字符串宽度(1个中文=2个英文字符)
* @param str
* @returns {number}
*/
export function getStringWidth(str) {
let width = 0;
for (let i = 0, len = str.length; i < len; i++) {
width += isHaveChina(str.charAt(i)) ? 2 : 1;
}
return width;
}
/**
* 同一行输出str1, str2str1居左, str2居右
* @param {string} str1 内容1
* @param {string} str2 内容2
* @param {string} fillWith str1 str2之间的填充字符
* @param {number} fontWidth 字符宽度 1/2
*
*/
export function inline(str1, str2, fillWith = ' ', fontWidth = 1) {
const lineWidth = MAX_CHAR_COUNT_EACH_LINE / fontWidth;
// 需要填充的字符数量
let fillCount = lineWidth - (getStringWidth(str1) + getStringWidth(str2)) % lineWidth;
let fillStr = new Array(fillCount).fill(fillWith.charAt(0)).join('');
return str1 + fillStr + str2;
}
/**
* 同一行输出三列第一列居左第二列居中第三列居右
* @param {string} str1 内容1左列
* @param {string} str2 内容2中列
* @param {string} str3 内容3右列
* @param {string} fillWith 列之间的填充字符
* @param {number} fontWidth 字符宽度默认为1
*/
export function inlineThreeColumns(str1, str2, str3, fillWith = ' ', fontWidth = 1) {
const lineWidth = MAX_CHAR_COUNT_EACH_LINE / fontWidth;
// 计算每列的宽度(假设三列等宽)
const columnWidth = Math.floor(lineWidth / 3);
// 计算每列的实际宽度
const width1 = getStringWidth(str1);
const width2 = getStringWidth(str2);
const width3 = getStringWidth(str3);
// 计算每列需要的填充数量
let fillCount1 = columnWidth - width1;
let fillCount2 = columnWidth - width2;
let fillCount3 = lineWidth - columnWidth - (width1 + fillCount1 * fontWidth + width2 + fillCount2 * fontWidth + width3);
// 创建填充字符串
let fillStr1 = new Array(fillCount1).fill(fillWith.charAt(0)).join('');
let fillStr2 = new Array(fillCount2).fill(fillWith.charAt(0)).join('');
let fillStr3 = new Array(fillCount3).fill(fillWith.charAt(0)).join('');
// 拼接字符串
return str1 + fillStr1 + str2 + fillStr2 + str3 + fillStr3;
}
export function inline3(str1, str2, str3, fillWith = ' ', fontWidth = 1) {
const lineWidth = MAX_CHAR_COUNT_EACH_LINE / fontWidth;
// 需要填充的字符数量
let fillCount = lineWidth - (getStringWidth(str1) + getStringWidth(str2) + getStringWidth(str3)) % lineWidth;
console.log("=",lineWidth, getStringWidth(str1) + getStringWidth(str2) + getStringWidth(str3), fillCount);
fillCount = Math.floor(fillCount / 2);
let fillStr = new Array(fillCount).fill(fillWith.charAt(0)).join('');
return str1 + fillStr + str2 + fillStr + str3;
}
/**
* 用字符填充一整行
* @param {string} fillWith 填充字符
* @param {number} fontWidth 字符宽度 1/2
*/
export function fillLine(fillWith = '-', fontWidth = 1) {
const lineWidth = MAX_CHAR_COUNT_EACH_LINE / fontWidth;
return new Array(lineWidth).fill(fillWith.charAt(0)).join('');
}
/**
* 文字内容居中左右用字符填充
* @param {string} str 文字内容
* @param {number} fontWidth 字符宽度 1/2
* @param {string} fillWith str1 str2之间的填充字符
*/
export function fillAround(str, fillWith = '-', fontWidth = 1) {
const lineWidth = MAX_CHAR_COUNT_EACH_LINE / fontWidth;
let strWidth = getStringWidth(str);
// 内容已经超过一行了,没必要填充
if (strWidth >= lineWidth) {
return str;
}
// 需要填充的字符数量
let fillCount = lineWidth - strWidth;
// 左侧填充的字符数量
let leftCount = Math.round(fillCount / 2);
// 两侧的填充字符,需要考虑左边需要填充,右边不需要填充的情况
let fillStr = new Array(leftCount).fill(fillWith.charAt(0)).join('');
return fillStr + str + fillStr.substr(0, fillCount - leftCount);
}