22 Commits
1.4.3 ... dev

Author SHA1 Message Date
gyq
0f522fa9d2 版本更新 2024-08-06 15:26:22 +08:00
gyq
efb7dd3e57 优化 2024-08-06 09:16:06 +08:00
gyq
ac469cbc32 更新没有usb打印机时调用云打印机 2024-08-02 17:54:52 +08:00
gyq
f8c5c9bf59 版本更新 2024-08-02 14:56:30 +08:00
gyq
6e2e7f9719 优化标签测试打印 2024-08-02 11:22:17 +08:00
gyq
b4872fec16 打包更新 2024-08-02 10:49:46 +08:00
gyq
804b677174 更改php https 2024-08-01 15:53:19 +08:00
gyq
367b49c68a 优化 2024-08-01 14:09:19 +08:00
gyq
f393299f0f 优化小票打印 2024-07-31 18:14:23 +08:00
gyq
49cabfed21 小票全部采用本地usb打印 2024-07-30 18:04:53 +08:00
gyq
b2e450fd52 新增本地USB打印 2024-07-29 18:10:01 +08:00
魏啾
4fb34a4235 wwz 2024-07-26 10:47:50 +08:00
魏啾
fdacaab44a Merge branch 'gyq' of https://e.coding.net/g-cphe0354/pczhuomianduan/cashierdesktop into wwz 2024-07-26 10:47:24 +08:00
gyq
b33086ba04 优化更多 2024-07-26 10:17:26 +08:00
魏啾
fd6410f742 打印 2024-07-26 10:16:57 +08:00
gyq
ea0c01bb2b 更新 2024-07-25 14:13:32 +08:00
gyq
4eb5df7668 优化 2024-07-25 10:50:24 +08:00
gyq
2c58c99d1e 1.优化订单开票按钮显示 2.退出登录新增退出团购 2024-07-24 14:22:14 +08:00
gyq
9e57753323 新增订单开票 2024-07-23 18:30:16 +08:00
gyq
d2183eec37 1.交班新增选择是否打印商品销售数据 2024-07-23 10:25:20 +08:00
gyq
a282636266 1.新增订单手动退款 2.团购新增抖音团购核销 2024-07-19 16:31:40 +08:00
gyq
c155e8a805 新增抖音团购券核销 2024-07-17 18:02:01 +08:00
40 changed files with 2250 additions and 607 deletions

View File

@@ -11,18 +11,20 @@ VITE_API_WSS = 'wss://cashier.sxczgkj.cn/client'
# 阿伟本地ws # 阿伟本地ws
# VITE_API_WSS = 'ws://192.168.2.17:9998/client' # VITE_API_WSS = 'ws://192.168.2.17:9998/client'
# 测试 php
# VITE_API_PHP_URL = 'http://192.168.2.33:1666/index.php/api'
# 正式 php # 正式 php
VITE_API_PHP_URL = 'http://czgdoumei.sxczgkj.com/index.php/api' VITE_API_PHP_URL = 'https://czgdoumei.sxczgkj.com/index.php/api'
# 测试 php 开票
# VITE_API_KP_URL = 'http://192.168.1.13:8888/api'
# 正式 php 开票
VITE_API_KP_URL = 'https://invoice.sxczgkj.cn/api'
# 阿伟 # 阿伟
# VITE_API_URL = 'http://192.168.2.96:10587/cashier-client' # VITE_API_URL = 'http://192.168.2.96:10587/cashier-client'
# 鹏辉 # 鹏辉
# VITE_API_URL = 'http://192.168.2.41:10589/cashier-client' # VITE_API_URL = 'http://192.168.1.106:10589/cashier-client'
# 测试 # 测试
# VITE_API_URL = 'https://cashier-client.sxczgkj.cn/cashier-client' # VITE_API_URL = 'https://cashier-client.sxczgkj.cn/cashier-client'

View File

@@ -4,17 +4,11 @@ ENV = production
# 正式ws # 正式ws
VITE_API_WSS = 'wss://cashier.sxczgkj.cn/client' VITE_API_WSS = 'wss://cashier.sxczgkj.cn/client'
#测试ws
# VITE_API_WSS = 'wss://wxcashiertest.sxczgkj.cn/client'
# 测试 php
# VITE_API_PHP_URL = 'http://192.168.2.33:1666/index.php/api'
# 正式 php # 正式 php
VITE_API_PHP_URL = 'http://czgdoumei.sxczgkj.com/index.php/api' VITE_API_PHP_URL = 'https://czgdoumei.sxczgkj.com/index.php/api'
# 测试 # 正式 php 开票
# VITE_API_URL = 'https://cashier-client.sxczgkj.cn/cashier-client' VITE_API_KP_URL = 'https://invoice.sxczgkj.cn/api'
# 线上环境接口地址 # 线上环境接口地址
VITE_API_URL = 'https://cashierclient.sxczgkj.cn/cashier-client/' VITE_API_URL = 'https://cashierclient.sxczgkj.cn/cashier-client/'

23
.env.test Normal file
View File

@@ -0,0 +1,23 @@
# 线上环境
ENV = test
#测试ws
VITE_API_WSS = 'wss://wxcashiertest.sxczgkj.cn/client'
# 正式ws
# VITE_API_WSS = 'wss://cashier.sxczgkj.cn/client'
# 正式 php
VITE_API_PHP_URL = 'https://czgdoumei.sxczgkj.com/index.php/api'
# 测试 php 开票
# VITE_API_KP_URL = 'http://192.168.1.13:8888/api'
# 正式 php 开票
VITE_API_KP_URL = 'https://invoice.sxczgkj.cn/api'
# 测试
VITE_API_URL = 'https://cashier-client.sxczgkj.cn/cashier-client'
# 正式
# VITE_API_URL = 'https://cashierclient.sxczgkj.cn/cashier-client'

View File

@@ -1 +1,115 @@
"use strict";const o=require("path"),e=require("electron"),p=require("os");let i;e.app.whenReady().then(()=>{i=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?i.loadURL(process.env.VITE_DEV_SERVER_URL):i.loadFile(o.resolve(__dirname,"../dist/index.html")),e.app.on("activate",()=>{e.BrowserWindow.getAllWindows().length===0&&createWindow()}),e.ipcMain.on("quitHandler",(n,t)=>{i=null,e.app.exit()}),e.ipcMain.on("getPrintList",()=>{i.webContents.getPrintersAsync().then(n=>{i.webContents.send("printList",n)})}),e.ipcMain.on("getOSmacSync",()=>{let n="";p.networkInterfaces().WLAN?(n=p.networkInterfaces().WLAN[0].mac,console.log("wlan.mac===",n)):(n=p.networkInterfaces().以太网[0].mac,console.log("以太网.mac===",n)),i.webContents.send("getOSmacRes",n)});const r=new e.BrowserWindow({show:!1,width:464,height:1726,webPreferences:{nodeIntegration:!0,contextIsolation:!1}});process.env.VITE_DEV_SERVER_URL?r.loadFile(o.join(__dirname,"../public/print.html")):r.loadFile(o.resolve(__dirname,"../dist/print.html")),e.ipcMain.on("printerInfoSync",(n,t)=>{r.webContents.send("getParams",t)}),e.ipcMain.on("printStart",(n,t)=>{console.log(t);let a=JSON.parse(t).deviceName;r.webContents.print({silent:!0,deviceName:a,pageSize:{width:58e3,height:216e3},scaleFactor:80,landscape:!1,margins:{marginType:"none",top:0,bottom:0,left:0,right:0},dpi:{horizontal:203,vertical:203}})});const s=new e.BrowserWindow({show:!1,width:464,height:1726,webPreferences:{nodeIntegration:!0,contextIsolation:!1}});process.env.VITE_DEV_SERVER_URL?s.loadFile(o.join(__dirname,"../public/work_print.html")):s.loadFile(o.resolve(__dirname,"../dist/work_print.html")),e.ipcMain.on("printerWorkSync",(n,t)=>{s.webContents.send("getParams",t)}),e.ipcMain.on("printWorkStart",(n,t)=>{let a=JSON.parse(t).deviceName;s.webContents.print({silent:!0,deviceName:a,pageSize:{width:58e3,height:216e3},scaleFactor:80,landscape:!1,margins:{marginType:"none",top:0,bottom:0,left:0,right:0},dpi:{horizontal:203,vertical:203}})});const l=new e.BrowserWindow({show:!1,width:360,height:240,webPreferences:{nodeIntegration:!0,contextIsolation:!1}});process.env.VITE_DEV_SERVER_URL?l.loadFile(o.join(__dirname,"../public/tag_print.html")):l.loadFile(o.resolve(__dirname,"../dist/tag_print.html")),e.ipcMain.on("printerTagSync",(n,t)=>{console.log(t),l.webContents.send("getParams",t)}),e.ipcMain.on("printTagStart",(n,t)=>{let a=JSON.parse(t).deviceName;l.webContents.print({silent:!0,deviceName:a,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",(n,t,c)=>{i&&(i.isMinimized()&&i.restore(),i.focus(),i.show())}):e.app.quit(),i.on("close",n=>{n.preventDefault(),i.webContents.send("showCloseDialog")})});e.app.on("window-all-closed",()=>{process.platform!=="darwin"&&e.app.quit()}); "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();
});

View File

@@ -73,109 +73,109 @@ app.whenReady().then(() => {
// }); // });
// 创建打印小票子窗口 // 创建打印小票子窗口
const printWin = new BrowserWindow({ // const printWin = new BrowserWindow({
show: false, // show: false,
width: 464, // width: 464,
height: 1726, // height: 1726,
webPreferences: { // webPreferences: {
// 集成网页和 Node.js也就是在渲染进程中可以调用 Node.js 方法 // // 集成网页和 Node.js也就是在渲染进程中可以调用 Node.js 方法
nodeIntegration: true, // nodeIntegration: true,
contextIsolation: false, // contextIsolation: false,
}, // },
}); // });
if (process.env.VITE_DEV_SERVER_URL) { // if (process.env.VITE_DEV_SERVER_URL) {
// 加载打印的html文件 // // 加载打印的html文件
printWin.loadFile(path.join(__dirname, "../public/print.html")); // printWin.loadFile(path.join(__dirname, "../public/print.html"));
} else { // } else {
printWin.loadFile(path.resolve(__dirname, "../dist/print.html")); // 打包后使用文件路径访问应用 // printWin.loadFile(path.resolve(__dirname, "../dist/print.html")); // 打包后使用文件路径访问应用
} // }
// 接收订单页面发过来的参数发送给打印页 // // 接收订单页面发过来的参数发送给打印页
ipcMain.on("printerInfoSync", (event, arg) => { // ipcMain.on("printerInfoSync", (event, arg) => {
printWin.webContents.send("getParams", arg); // printWin.webContents.send("getParams", arg);
}); // });
// 执行打印操作 // // 执行打印操作
ipcMain.on("printStart", (event, arg) => { // ipcMain.on("printStart", (event, arg) => {
console.log(arg); // console.log(arg);
const _parmas = JSON.parse(arg); // const _parmas = JSON.parse(arg);
// console.log(_parmas) // // console.log(_parmas)
let name = _parmas.deviceName; // let name = _parmas.deviceName;
printWin.webContents.print({ // printWin.webContents.print({
silent: true, // silent: true,
deviceName: name, // deviceName: name,
pageSize: { // pageSize: {
width: 58000, // width: 58000,
height: 216000, // height: 216000,
}, // },
scaleFactor: 80, // scaleFactor: 80,
landscape: false, // landscape: false,
margins: { // margins: {
marginType: "none", // marginType: "none",
top: 0, // top: 0,
bottom: 0, // bottom: 0,
left: 0, // left: 0,
right: 0, // right: 0,
}, // },
dpi: { // dpi: {
horizontal: 203, // horizontal: 203,
vertical: 203, // vertical: 203,
}, // },
}); // });
}); // });
// 交班小票的窗口 // // 交班小票的窗口
const workPrintWin = new BrowserWindow({ // const workPrintWin = new BrowserWindow({
show: false, // show: false,
width: 464, // width: 464,
height: 1726, // height: 1726,
webPreferences: { // webPreferences: {
nodeIntegration: true, // nodeIntegration: true,
contextIsolation: false, // contextIsolation: false,
}, // },
}); // });
if (process.env.VITE_DEV_SERVER_URL) { // if (process.env.VITE_DEV_SERVER_URL) {
// 加载打印的html文件 // // 加载打印的html文件
workPrintWin.loadFile(path.join(__dirname, "../public/work_print.html")); // workPrintWin.loadFile(path.join(__dirname, "../public/work_print.html"));
} else { // } else {
workPrintWin.loadFile(path.resolve(__dirname, "../dist/work_print.html")); // 打包后使用文件路径访问应用 // workPrintWin.loadFile(path.resolve(__dirname, "../dist/work_print.html")); // 打包后使用文件路径访问应用
} // }
// 接收渲染进程发送的数据 // // 接收渲染进程发送的数据
ipcMain.on("printerWorkSync", (event, arg) => { // ipcMain.on("printerWorkSync", (event, arg) => {
workPrintWin.webContents.send("getParams", arg); // workPrintWin.webContents.send("getParams", arg);
}); // });
// 执行交班小票的打印操作 // // 执行交班小票的打印操作
ipcMain.on("printWorkStart", (event, arg) => { // ipcMain.on("printWorkStart", (event, arg) => {
// console.log(arg); // // console.log(arg);
const _parmas = JSON.parse(arg); // const _parmas = JSON.parse(arg);
// console.log(_parmas) // // console.log(_parmas)
let name = _parmas.deviceName; // let name = _parmas.deviceName;
workPrintWin.webContents.print({ // workPrintWin.webContents.print({
silent: true, // silent: true,
deviceName: name, // deviceName: name,
pageSize: { // pageSize: {
width: 58000, // width: 58000,
height: 216000, // height: 216000,
}, // },
scaleFactor: 80, // scaleFactor: 80,
landscape: false, // landscape: false,
margins: { // margins: {
marginType: "none", // marginType: "none",
top: 0, // top: 0,
bottom: 0, // bottom: 0,
left: 0, // left: 0,
right: 0, // right: 0,
}, // },
dpi: { // dpi: {
horizontal: 203, // horizontal: 203,
vertical: 203, // vertical: 203,
}, // },
}); // });
}); // });
// 标签小票的窗口 // 标签小票的窗口
const tagPrintWin = new BrowserWindow({ const tagPrintWin = new BrowserWindow({

View File

@@ -1,11 +1,12 @@
{ {
"name": "vite-electron", "name": "vite-electron",
"private": true, "private": true,
"version": "1.4.3", "version": "1.4.14",
"main": "dist-electron/main.js", "main": "dist-electron/main.js",
"scripts": { "scripts": {
"dev": "chcp 65001 && vite", "dev": "chcp 65001 && vite",
"build": "node ./addVersion.js && vite build && electron-builder", "build": "node ./addVersion.js && vite build && electron-builder",
"build:test": "vite build --mode test && electron-builder",
"preview": "vite preview", "preview": "vite preview",
"build:win": "node ./addVersion.js && vite build && electron-builder --w" "build:win": "node ./addVersion.js && vite build && electron-builder --w"
}, },

View File

@@ -51,7 +51,7 @@ watch(route, (to) => {
includeList.push(to.name); includeList.push(to.name);
} }
// 需要全屏的路由 // 需要全屏的路由
let arr = ["/login", "/device_list", "/add_device", "/add_label", "/webview"]; let arr = ["/login", "/device_list", "/add_device", "/add_label", "/webview", '/workrecord'];
if (arr.includes(to.path)) { if (arr.includes(to.path)) {
hideLeftMenu.value = true; hideLeftMenu.value = true;
} else { } else {
@@ -193,7 +193,6 @@ onMounted(() => {
} }
ipcRenderer.on('showCloseDialog', (event, arg) => { ipcRenderer.on('showCloseDialog', (event, arg) => {
console.log('阻止系统关闭软件');
ElMessageBox.confirm("确定要关闭软件吗?") ElMessageBox.confirm("确定要关闭软件吗?")
.then(() => { .then(() => {
ipcRenderer.send("quitHandler", "退出吧"); ipcRenderer.send("quitHandler", "退出吧");

View File

@@ -119,3 +119,42 @@ export function douyinfulfilmentcertificatecancel(data) {
data, data,
}); });
} }
/**
* 门店列表
* @param {*} data
* @returns
*/
export function douyinstorelist(data) {
return request_php({
method: "post",
url: "douyin/storelist",
data,
});
}
/**
* 绑定门店
* @param {*} data
* @returns
*/
export function douyinbindstore(data) {
return request_php({
method: "post",
url: "douyin/bindstore",
data,
});
}
/**
* 登出团购
* @param {*} data
* @returns
*/
export function tglogout(data) {
return request_php({
method: "post",
url: "user/logout",
data,
});
}

40
src/api/invoice.js Normal file
View File

@@ -0,0 +1,40 @@
import request_kp from "@/utils/request_kp.js";
/**
* 开票人列表
* @param {*} data
* @returns
*/
export function issuedby(data) {
return request_kp({
method: "post",
url: "szzpy/syjissuedby",
data,
});
}
/**
* 商家通过收银机提交开票信息
* @param {*} data
* @returns
*/
export function carsubinvoicing(data) {
return request_kp({
method: "post",
url: "store/carsubinvoicing",
data,
});
}
/**
* 打印二维码
* @param {*} data
* @returns
*/
export function syjprintqrcode(data) {
return request_kp({
method: "post",
url: "store/syjprintqrcode",
data,
});
}

View File

@@ -29,10 +29,10 @@ export function orderorderDetail(params) {
* @param {*} params * @param {*} params
* @returns * @returns
*/ */
export function payreturnOrder(data, pwd) { export function payreturnOrder(data, pwd, isOnline) {
return request({ return request({
method: "post", method: "post",
url: `pay/returnOrder?pwd=${pwd}`, url: `pay/returnOrder?pwd=${pwd}&isOnline=${isOnline}`,
data, data,
}); });
} }

View File

@@ -51,3 +51,16 @@ export function handoverData(params) {
params, params,
}); });
} }
/**
* 打印交班数据
* @param {*} params
* @returns
*/
export function handoverprint(params) {
return request({
method: "get",
url: "data/handoverprint",
params,
});
}

View File

@@ -20,6 +20,12 @@
</el-icon> </el-icon>
<el-text class="text">{{ item.label }}</el-text> <el-text class="text">{{ item.label }}</el-text>
</router-link> </router-link>
<div class="item" @click="workRef.show()">
<el-icon class="icon">
<component is="SwitchButton" />
</el-icon>
<el-text class="text">交班</el-text>
</div>
<div class="item more" @click="moreref.show()"> <div class="item more" @click="moreref.show()">
<el-icon class="icon"> <el-icon class="icon">
<Operation /> <Operation />
@@ -27,6 +33,8 @@
<el-text class="text">更多</el-text> <el-text class="text">更多</el-text>
</div> </div>
</div> </div>
<!-- 交班 -->
<work ref="workRef" />
<!-- 更多 --> <!-- 更多 -->
<more ref="moreref" @openCall="openCall"></more> <more ref="moreref" @openCall="openCall"></more>
<!-- 叫号 --> <!-- 叫号 -->
@@ -39,14 +47,15 @@ import { useRoute } from 'vue-router'
import { useSocket } from '@/store/socket.js' import { useSocket } from '@/store/socket.js'
import more from '@/components/more.vue' import more from '@/components/more.vue'
import callNumber from './callNumber.vue' import callNumber from './callNumber.vue'
import work from '@/views/work/index.vue'
const emits = defineEmits(['connectWsHandle'])
const socketStore = useSocket() const socketStore = useSocket()
const route = useRoute() const route = useRoute()
const moreref = ref(null) const moreref = ref(null)
const callNumberRef = ref(null) const callNumberRef = ref(null)
const workRef = ref(null)
const menus = ref([ const menus = ref([
{ {
label: '收银', label: '收银',
@@ -78,11 +87,11 @@ const menus = ref([
path: '/member', path: '/member',
icon: 'User' icon: 'User'
}, },
{ // {
label: '交班', // label: '交班',
path: '/work', // path: '/work',
icon: 'SwitchButton' // icon: 'SwitchButton'
} // }
]) ])
// 更新叫号记录 // 更新叫号记录
@@ -97,7 +106,7 @@ function openCall() {
// 手动重新连接ws // 手动重新连接ws
function connectWsHandle() { function connectWsHandle() {
if (socketStore.online) return if (socketStore.online) return
emits('connectWsHandle') window.onload()
} }
defineExpose({ defineExpose({

View File

@@ -0,0 +1,207 @@
//==本JS是加载Lodop插件或Web打印服务CLodop/Lodop7的综合示例可直接使用建议理解后融入自己程序==
//用双端口加载主JS文件Lodop.js(或CLodopfuncs.js兼容老版本)以防其中某端口被占:
var MainJS = "CLodopfuncs.js",
URL_WS1 = "ws://localhost:8000/" + MainJS, //ws用8000/18000
URL_WS2 = "ws://localhost:18000/" + MainJS,
URL_HTTP1 = "http://localhost:8000/" + MainJS, //http用8000/18000
URL_HTTP2 = "http://localhost:18000/" + MainJS,
URL_HTTP3 = "https://localhost.lodop.net:8443/" + MainJS; //https用8000/8443
var CreatedOKLodopObject, CLodopIsLocal, LoadJsState;
//==判断是否需要CLodop(那些不支持插件的浏览器):==
function needCLodop() {
try {
var ua = navigator.userAgent;
if (ua.match(/Windows\sPhone/i) ||
ua.match(/iPhone|iPod|iPad/i) ||
ua.match(/Android/i) ||
ua.match(/Edge\D?\d+/i))
return true;
var verTrident = ua.match(/Trident\D?\d+/i);
var verIE = ua.match(/MSIE\D?\d+/i);
var verOPR = ua.match(/OPR\D?\d+/i);
var verFF = ua.match(/Firefox\D?\d+/i);
var x64 = ua.match(/x64/i);
if ((!verTrident) && (!verIE) && (x64)) return true;
else if (verFF) {
verFF = verFF[0].match(/\d+/);
if ((verFF[0] >= 41) || (x64)) return true;
} else if (verOPR) {
verOPR = verOPR[0].match(/\d+/);
if (verOPR[0] >= 32) return true;
} else if ((!verTrident) && (!verIE)) {
var verChrome = ua.match(/Chrome\D?\d+/i);
if (verChrome) {
verChrome = verChrome[0].match(/\d+/);
if (verChrome[0] >= 41) return true;
}
}
return false;
} catch (err) {
return true;
}
}
//==检查加载成功与否如没成功则用http(s)再试==
//==低版本CLODOP6.561/Lodop7.043及前)用本方法==
function checkOrTryHttp() {
if (window.getCLodop) {
LoadJsState = "complete";
return true;
}
if (LoadJsState == "loadingB" || LoadJsState == "complete") return;
LoadJsState = "loadingB";
var head = document.head || document.getElementsByTagName("head")[0] || document.documentElement;
var JS1 = document.createElement("script"),
JS2 = document.createElement("script"),
JS3 = document.createElement("script");
JS1.src = URL_HTTP1;
JS2.src = URL_HTTP2;
JS3.src = URL_HTTP3;
JS1.onload = JS2.onload = JS3.onload = JS2.onerror = JS3.onerror = function () {
LoadJsState = "complete";
}
JS1.onerror = function (e) {
if (window.location.protocol !== 'https:')
head.insertBefore(JS2, head.firstChild);
else
head.insertBefore(JS3, head.firstChild);
}
head.insertBefore(JS1, head.firstChild);
}
//==加载Lodop对象的主过程:==
(function loadCLodop() {
if (!needCLodop()) return;
CLodopIsLocal = !!((URL_WS1 + URL_WS2).match(/\/\/localho|\/\/127.0.0./i));
LoadJsState = "loadingA";
if (!window.WebSocket && window.MozWebSocket) window.WebSocket = window.MozWebSocket;
//ws方式速度快(小于200ms)且可避免CORS错误,但要求Lodop版本足够新:
try {
var WSK1 = new WebSocket(URL_WS1);
WSK1.onopen = function (e) {
setTimeout(checkOrTryHttp(), 200);
}
WSK1.onmessage = function (e) {
if (!window.getCLodop) eval(e.data);
}
WSK1.onerror = function (e) {
var WSK2 = new WebSocket(URL_WS2);
WSK2.onopen = function (e) {
setTimeout(checkOrTryHttp(), 200);
}
WSK2.onmessage = function (e) {
if (!window.getCLodop) eval(e.data);
}
WSK2.onerror = function (e) {
checkOrTryHttp();
}
}
} catch (e) {
checkOrTryHttp();
}
})();
//==获取LODOP对象主过程,判断是否安装、需否升级:==
function getLodop(oOBJECT, oEMBED) {
var strFontTag = "<br><font color='#FF00FF'>打印控件";
var strLodopInstall = strFontTag + "未安装!点击这里<a href='https://h5-invoice.sxczgkj.cn/invo/czg.zip'>执行安装</a>";
var strLodopUpdate = strFontTag + "需要升级!点击这里<a href='https://h5-invoice.sxczgkj.cn/invo/czg.zip'>执行升级</a>";
var strLodop64Install = strFontTag + "未安装!点击这里<a href='https://h5-invoice.sxczgkj.cn/invo/czg.zip'>执行安装</a>";
var strLodop64Update = strFontTag + "需要升级!点击这里<a href='https://h5-invoice.sxczgkj.cn/invo/czg.zip'>执行升级</a>";
var strCLodopInstallA =
"<br><font color='#FF00FF'>Web打印服务CLodop未安装启动点击这里<a href='https://h5-invoice.sxczgkj.cn/invo/czg.zip'>下载执行安装</a>";
// var strCLodopInstallB = "<br>(若此前已安装过,可<a href='CLodop.protocol:setup' target='_self'>点这里直接再次启动</a>";
var strCLodopUpdate =
"<br><font color='#FF00FF'>Web打印服务CLodop需升级!点击这里<a href='https://h5-invoice.sxczgkj.cn/invo/czg.zip'>执行升级</a>";
var strLodop7FontTag = "<br><font color='#FF00FF'>Web打印服务Lodop7";
var strLodop7HrefX86 = "点击这里<a href='https://h5-invoice.sxczgkj.cn/invo/czg.zip' target='_self'>下载安装</a>(下载后解压点击lodop文件开始执行)";
var strLodop7HrefARM = "点击这里<a href='https://h5-invoice.sxczgkj.cn/invo/czg.zip'>下载安装</a>(下载后解压点击lodop文件开始执行)";
var strLodop7Install_X86 = strLodop7FontTag + "未安装启动," + strLodop7HrefX86;
var strLodop7Install_ARM = strLodop7FontTag + "未安装启动," + strLodop7HrefARM;
var strLodop7Update_X86 = strLodop7FontTag + "需升级," + strLodop7HrefX86;
var strLodop7Update_ARM = strLodop7FontTag + "需升级," + strLodop7HrefARM;
var strInstallOK = ",成功后请刷新本页面或重启浏览器。</font>";
var LODOP;
try {
var isWinIE = (/MSIE/i.test(navigator.userAgent)) || (/Trident/i.test(navigator.userAgent));
var isWinIE64 = isWinIE && (/x64/i.test(navigator.userAgent));
var isLinuxX86 = (/Linux/i.test(navigator.platform)) && (/x86/i.test(navigator.platform));
var isLinuxARM = (/Linux/i.test(navigator.platform)) && (/aarch/i.test(navigator.platform));
if (needCLodop() || isLinuxX86 || isLinuxARM) {
try {
LODOP = window.getCLodop();
} catch (err) { }
if (!LODOP && LoadJsState !== "complete") {
if (!LoadJsState)
alert("未曾加载Lodop主JS文件请先调用loadCLodop过程.");
else
alert("网页还没下载完毕,请稍等一下再操作.");
return;
}
var strAlertMessage;
if (!LODOP) {
if (isLinuxX86)
strAlertMessage = strLodop7Install_X86;
else if (isLinuxARM)
strAlertMessage = strLodop7Install_ARM;
else
strAlertMessage = strCLodopInstallA + (CLodopIsLocal ? strCLodopInstallB : "");
document.body.innerHTML = strAlertMessage + strInstallOK + document.body.innerHTML;
return;
} else {
if (isLinuxX86 && LODOP.CVERSION < "7.0.7.5")
strAlertMessage = strLodop7Update_X86;
else if (isLinuxARM && LODOP.CVERSION < "7.0.7.5")
strAlertMessage = strLodop7Update_ARM;
else if (CLODOP.CVERSION < "6.5.9.4")
strAlertMessage = strCLodopUpdate;
if (strAlertMessage)
document.body.innerHTML = strAlertMessage + strInstallOK + document.body.innerHTML;
}
} else {
//==如果页面有Lodop插件就直接使用,否则新建:==
if (oOBJECT || oEMBED) {
if (isWinIE)
LODOP = oOBJECT;
else
LODOP = oEMBED;
} else if (!CreatedOKLodopObject) {
LODOP = document.createElement("object");
LODOP.setAttribute("width", 0);
LODOP.setAttribute("height", 0);
LODOP.setAttribute("style", "position:absolute;left:0px;top:-100px;width:0px;height:0px;");
if (isWinIE)
LODOP.setAttribute("classid", "clsid:2105C259-1E0C-4534-8141-A753534CB4CA");
else
LODOP.setAttribute("type", "application/x-print-lodop");
document.documentElement.appendChild(LODOP);
CreatedOKLodopObject = LODOP;
} else
LODOP = CreatedOKLodopObject;
//==Lodop插件未安装时提示下载地址:==
if ((!LODOP) || (!LODOP.VERSION)) {
document.body.innerHTML = (isWinIE64 ? strLodop64Install : strLodopInstall) + strInstallOK + document
.body.innerHTML;
return LODOP;
}
if (LODOP.VERSION < "6.2.2.6") {
document.body.innerHTML = (isWinIE64 ? strLodop64Update : strLodopUpdate) + strInstallOK + document.body
.innerHTML;
}
}
//===如下空白位置适合调用统一功能(如注册语句、语言选择等):=======================
// LODOP.SET_LICENSES("超掌柜独有!","DCFF409304DFCEB3E2C644BF96CD0720","","");
//===============================================================================
return LODOP;
} catch (err) {
alert("getLodop出错:" + err);
}
}
export default getLodop

View File

@@ -0,0 +1,113 @@
<template>
<div>
<el-dialog v-model="centerDialogVisible" title="二维码" width="666" center>
<div class="dialog-footer" style="text-align: center">
<!-- <qrcode-vue :value="form.url" :size="200" /> -->
<div class="qrcodefooter">{{ props.form.article }}</div>
<div class="qrcodefooter">{{ props.form.type }}</div>
<div class="qrcodefooter">
<el-select v-model="rintermodel" placeholder="请选择打印机" @change="changerintermodel">
<el-option v-for="item in rintermodeldata" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</div>
<el-button @click="centerDialogVisible = false">关闭</el-button>
<el-button type="primary" :disabled="rintermodel ? false : true" @click="Printing"> 打印 </el-button>
</div>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { dayjs } from 'element-plus'
import { ref } from 'vue'
import _lodash from 'lodash'
import getLodop from './LodopFuncs'
const props = defineProps({
form: Object,
})
const centerDialogVisible = ref(false) //显示隐藏
const rintermodeldata = ref([]) // 获取打印机列表
const rintermodel = ref() //打印机类型
// 确定打印机类型
const changerintermodel = (i: string) => {
rintermodel.value = i
}
const emit = defineEmits(['somethingDone'])
// 以下是打印
const Printing = () => {
let LODOP = getLodop()
centerDialogVisible.value = false
rintermodeldata.value = [] //清空
emit('somethingDone')
LODOP.PRINT_INIT('')
// 设置打印纸大小D
LODOP.SET_PRINT_PAGESIZE(3, 800, '', '')
// 二维码控制大小
LODOP.ADD_PRINT_BARCODE('', '30px', '150px', '150px', 'QRCode', props.form.url) //打印产品代码条码
LODOP.SET_PRINT_MODE('PRINT_PAGE_PERCENT', 'Full-Width ') //设置打印风格,这里是等宽打印
LODOP.SET_PRINTER_INDEX(rintermodel.value) //设置默认打印机(这里用的是打印机名称)
LODOP.SET_PRINT_STYLE("TextAlign", "Center");
// 文字内容
LODOP.ADD_PRINT_HTM(
'150px',
'5px',
'100%',
'100%',
`<div style="width: 100%;font-size: 12px; ">项目分类:${props.form.article}</div>
<div style="width: 100%;font-size: 12px; margin-top:6px;">发票类型:${props.form.type}</div>
<div style="width: 100%;font-size: 12px; margin-top:6px;">生成时间:${dayjs().format('YYYY-MM-DD HH:mm:ss')}</div>
<div style="width: 100%;font-size: 12px; margin-top:6px;">*二维码有效期30天,超过自动失效!</div>
<div style="width: 100%;font-size: 14px; margin-top: 15px;">您可以使用微信,扫码开票</div>`,
'150px',
'5px',
'100%',
'100%',
)
LODOP.SET_LICENSES('', 'DCFF409304DFCEB3E2C644BF96CD0720', '', '')
LODOP.PRINT()
}
const initialization = async () => {
rintermodeldata.value = [] //清空
let LODOP = getLodop()
setTimeout(() => {
if (LODOP == null) {
alert('请先安装打印控件')
return
}
for (var i = 0; i < LODOP.GET_PRINTER_COUNT(); i++) {
let obj: {
id: string
name: string
} = {
id: '',
name: '',
}
obj.id = LODOP.GET_PRINTER_NAME(i)
obj.name = LODOP.GET_PRINTER_NAME(i)
// console.log(obj)
rintermodeldata.value.push(obj)
}
}, 1000)
}
const centerDialogVisibleshow = () => {
centerDialogVisible.value = !centerDialogVisible.value
}
defineExpose({
Printing,
centerDialogVisibleshow,
initialization,
})
</script>
<style scoped lang="scss">
.dialog-footer {
text-align: center;
.qrcodefooter {
text-align: center;
margin: 10px;
}
}
</style>

View File

@@ -0,0 +1,32 @@
import getLodop from "./LodopFuncs.js";
/**
* 打印订单发票
*/
export default (data) => {
console.log("data.deviceName===", data.deviceName);
let LODOP = getLodop();
LODOP.PRINT_INIT("打印小票");
// 设置打印纸大小D
LODOP.SET_PRINT_PAGESIZE(3, "58mm", 20, "");
// 二维码控制大小;
LODOP.ADD_PRINT_BARCODE("", "40px", "150px", "150px", "QRCode", data.url);
//设置默认打印机(这里用的是打印机名称)
LODOP.SET_PRINTER_INDEX(data.deviceName);
// 文字内容
let html = `
<div style="height: 100px;"></div>
<div style="width: 100%;font-size: 16px;display:flex;justify-content:center;">
请使用微信扫码下载发票二维码有效期30天超过自动失效
</div>
<div>.</div>
<div>.</div>
<div>.</div>
<div>.</div>
`;
setTimeout(() => {
LODOP.ADD_PRINT_HTM("9mm", "0mm", "RightMargin:0mm", 20, html);
LODOP.SET_LICENSES("", "DCFF409304DFCEB3E2C644BF96CD0720", "", "");
LODOP.PRINT();
}, 800);
};

View File

@@ -0,0 +1,161 @@
import getLodop from "./LodopFuncs.js";
/**
* 打印交班小票
*/
export default (data) => {
console.log("data.deviceName===", data.deviceName);
let LODOP = getLodop();
LODOP.PRINT_INIT("打印小票");
// 设置打印纸大小D
LODOP.SET_PRINT_PAGESIZE(3, "58mm", 20, "");
//设置默认打印机(这里用的是打印机名称)
LODOP.SET_PRINTER_INDEX(data.deviceName);
// 文字内容
let html = `
<div style="font-size: 30px;display:flex;justify-content:center;">
${data.merchantName}
</div>
<div style="font-size: 16px;display: flex; justify-content:center;margin-top:6px;">
交班小票
</div>
<div style="font-size: 12px;margin-top:50px;">
当班时间:${data.startTime}
</div>
<div style="font-size: 12px;">
交班时间:${data.endTime}
</div>
<div style="font-size: 12px;">
收银员:${data.staff}
</div>
<div style="font-size: 12px;margin-top: 4px;">
当班收入:${data.totalAmount}
</div>
`;
let payInfos = "";
if (data.payInfos && data.payInfos.length) {
for (let item of data.payInfos) {
payInfos += `
<div style="font-size: 12px;padding-left:20px;">
${item.payType}${item.amount}
</div>
`;
}
}
let memberTitle = `
<div style="font-size: 12px;margin-top: 4px;">
会员数据
</div>
`;
let memberData = "";
if (data.memberData && data.memberData.length) {
for (let item of data.memberData) {
memberData += `
<div style="font-size: 12px;padding-left:20px;">
${item.deposit}${item.amount}
</div>
`;
}
}
let productCategoriesTabHead = `
<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:25%;">数量</td>
<td style="font-size: 12px;width:25%;">总计</td>
</tr>
`;
let productCategoriesTableBody = "";
if (data.productCategories && data.productCategories.length) {
for (let item of data.productCategories) {
productCategoriesTableBody += `
<tr>
<td style="font-size: 12px;width:50%;">
<div>${item.categoryName}</div>
</td>
<td style="font-size: 12px;width:25%;">${item.num}</td>
<td style="font-size: 12px;width:25%;">
${item.amount}
</td>
</tr>
`;
}
}
let tabHead = `
</table>
<div style="font-size: 12px;margin-top: 4px;">商品数据</div>
<table class="table" style="width: 100%;">
<tr>
<td style="font-size: 12px;width:75%;">商品</td>
<td style="font-size: 12px;width:25%;">数量</td>
</tr>
`;
let tableBody = "";
if (data.productInfos && data.productInfos.length) {
for (let item of data.productInfos) {
tableBody += `
<tr>
<td style="font-size: 12px;width:75%;">
<div>${item.productName}</div>
</td>
<td style="font-size: 12px;width:25%;">${item.num}</td>
</tr>
`;
}
}
if (!data.printShop) {
tabHead = "";
tableBody = "";
}
let str = `
</table>
<div style="font-size: 12px;margin-top: 4px;">
<span>快捷收款金额:</span>
<span>${data.quickAmount}</span>
</div>
<div style="font-size: 12px;">
<span>退款金额:</span>
<span>${data.returnAmount}</span>
</div>
<div style="font-size: 12px;">
<span>总收入:</span>
<span>${data.totalAmount}</span>
</div>
<div style="font-size: 12px;">
<span>备用金:</span>
<span>${data.imprest}</span>
</div>
<div style="font-size: 12px;">
<span>应交金额:</span>
<span>${data.payable}</span>
</div>
<div style="margin-top: 20px; font-size: 12px;">
<span>总订单数:</span>
<span>${data.orderNum}</span>
</div>
<div style="font-size: 12px;">
打印时间:${data.printTime}
</div>
<div>.</div>
<div>.</div>
<div>.</div>
<div>.</div>
`;
let lastHtml = `${html}${payInfos}${memberTitle}${memberData}${productCategoriesTabHead}${productCategoriesTableBody}${tabHead}${tableBody}${str}`;
setTimeout(() => {
LODOP.ADD_PRINT_HTM("9mm", "0mm", "RightMargin:0mm", 20, lastHtml);
LODOP.SET_LICENSES("", "DCFF409304DFCEB3E2C644BF96CD0720", "", "");
LODOP.PRINT();
}, 800);
};

View File

@@ -0,0 +1,104 @@
import getLodop from "./LodopFuncs.js";
/**
* 打印订单小票
*/
export default (data) => {
console.log(data);
console.log("data.deviceName===", data.deviceName);
let LODOP = getLodop();
LODOP.PRINT_INIT("打印小票");
// 设置打印纸大小D
LODOP.SET_PRINT_PAGESIZE(3, "58mm", 20, "");
//设置默认打印机(这里用的是打印机名称)
LODOP.SET_PRINTER_INDEX(data.deviceName);
// 文字内容
let t1 = 40;
let t2 = (100 - t1) / 3;
let html = `
<div style="font-size: 30px;display:flex;justify-content:center;">
${data.shop_name}
</div>
<div style="font-size: 16px;display: flex; justify-content:center;margin-top:6px;">
${data.isBefore ? "预" : ""}结算单【${
data.orderInfo.masterId ? data.orderInfo.masterId : ""
}
</div>
<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;">
订单号:${data.orderInfo && data.orderInfo.orderNo}
</div>
<div style="margin-top: 4px;font-size: 12px;">
交易时间:${data.createdAt}
</div>
<div style="margin-top: 4px;font-size: 12px;">
收银员:${data.loginAccount}
</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>
<td style="font-size: 12px;width:${t2}%;">单价</td>
<td style="font-size: 12px;width:${t2}%;">数量</td>
<td style="font-size: 12px;width:${t2}%;">小计</td>
</tr>
`;
let table = "";
for (let item of data.carts) {
table += `
<tr>
<td style="font-size: 12px;width:${t1}%;">
<div>${item.name}</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>
<td style="font-size: 12px;width:${t2}%;">
${item.totalAmount}
</td>
</tr>
`;
}
let str = `
</table>
<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>
</div>
<div style="margin-top: 4px; font-size: 12px;">
<span>余额:</span>
<span>0.00</span>
</div>
<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>.</div>
<div>.</div>
<div>.</div>
<div>.</div>
`;
let lastHtml = `${html}${table}${str}`;
setTimeout(() => {
LODOP.ADD_PRINT_HTM("9mm", "0mm", "RightMargin:0mm", 20, lastHtml);
LODOP.SET_LICENSES("", "DCFF409304DFCEB3E2C644BF96CD0720", "", "");
LODOP.PRINT();
}, 800);
};

View File

@@ -0,0 +1,96 @@
import getLodop from "./LodopFuncs.js";
/**
* 打印退单小票
*/
export default (data) => {
let LODOP = getLodop();
LODOP.PRINT_INIT("打印小票");
// 设置打印纸大小D
LODOP.SET_PRINT_PAGESIZE(3, "58mm", 20, "");
//设置默认打印机(这里用的是打印机名称)
LODOP.SET_PRINTER_INDEX(data.deviceName);
// 文字内容
let t1 = 40;
let t2 = (100 - t1) / 3;
let html = `
<div style="font-size: 30px;display:flex;justify-content:center;">
${data.shop_name}
</div>
<div style="font-size: 16px;display: flex; justify-content:center;margin-top:6px;">
退款单【${data.orderInfo.masterId ? data.orderInfo.masterId : ""}
</div>
<div style="margin-top: 30px;font-size: 12px;">
订单号:${data.orderInfo && data.orderInfo.orderNo}
</div>
<div style="margin-top: 4px;font-size: 12px;">
交易时间:${data.createdAt}
</div>
<div style="margin-top: 4px;font-size: 12px;">
收银员:${data.loginAccount}
</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>
<td style="font-size: 12px;width:${t2}%;">单价</td>
<td style="font-size: 12px;width:${t2}%;">数量</td>
<td style="font-size: 12px;width:${t2}%;">小计</td>
</tr>
`;
let table = "";
for (let item of data.carts) {
table += `
<tr>
<td style="font-size: 12px;width:${t1}%;">
<div>${item.name}</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>
<td style="font-size: 12px;width:${t2}%;">
${item.totalAmount}
</td>
</tr>
`;
}
let str = `
</table>
<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>
</div>
<div style="margin-top: 4px; font-size: 12px;">
<span>余额:</span>
<span>0.00</span>
</div>
<div style="margin-top: 6px;margin-bottom: 6px;width: 100%">
<hr/>
</div>
<div style="margin-top: 4px; font-size: 12px;">
打印时间:${data.printTime}
</div>
<div>.</div>
<div>.</div>
<div>.</div>
<div>.</div>
`;
let lastHtml = `${html}${table}${str}`;
setTimeout(() => {
LODOP.ADD_PRINT_HTM("9mm", "0mm", "RightMargin:0mm", 20, lastHtml);
LODOP.SET_LICENSES("", "DCFF409304DFCEB3E2C644BF96CD0720", "", "");
LODOP.PRINT();
}, 800);
};

View File

@@ -1,21 +1,17 @@
<template> <template>
<div class="drawerbox"> <div class="drawerbox">
<el-drawer <el-drawer size="60%" :with-header="false" direction="rtl" v-model="dialogVisible" style="padding: 0">
size="60%"
:with-header="false"
direction="rtl"
v-model="dialogVisible"
style="padding: 0"
>
<div class="drawerbox_box"> <div class="drawerbox_box">
<div class="drawerbox_bo_top"> <div class="drawerbox_bo_top">
<div class="drawerbox_bo_top_left"> <div class="drawerbox_bo_top_left">
<div class="drawerbox_bo_top_left_one"> <div class="drawerbox_bo_top_left_one" style="font-size: 24px;">
{{ store.userInfo.shopName }} {{ store.userInfo.shopName }}
</div> </div>
<div class="drawerbox_bo_top_left_tow" style="margin-top: 10px"> <div class="drawerbox_bo_top_left_tow" style="margin-top: 10px">
收银员{{ store.userInfo.userCode }} 收银员{{ store.userInfo.loginAccount }}
<span style="color: #666">{{ store.userInfo.loginTime }}</span> </div>
<div>
<span style="color: #666">{{ dayjs(store.userInfo.loginTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
</div> </div>
</div> </div>
<!-- <div class="drawerbox_bo_top_ring"> <!-- <div class="drawerbox_bo_top_ring">
@@ -36,13 +32,21 @@
<div class="drawerbox_bo_box"> <div class="drawerbox_bo_box">
<div style="padding: 10px; color: #999; font-weight: bold">系统</div> <div style="padding: 10px; color: #999; font-weight: bold">系统</div>
<div class="drawerbox_bo_box_itemb_felx"> <div class="drawerbox_bo_box_itemb_felx">
<div class="drawerbox_bo_box_itembox"> <!-- <div class="drawerbox_bo_box_itembox">
<div class="drawerbox_bo_box_icon"> <div class="drawerbox_bo_box_icon">
<el-icon size="40"> <el-icon size="40">
<Setting /> <Setting />
</el-icon> </el-icon>
</div> </div>
<div class="drawerbox_bo_box_icontext">设置</div> <div class="drawerbox_bo_box_icontext">设置</div>
</div> -->
<div class="drawerbox_bo_box_itembox" @click="router.push({ name: 'device_list' })">
<div class="drawerbox_bo_box_icon">
<el-icon size="40">
<TurnOff />
</el-icon>
</div>
<div class="drawerbox_bo_box_icontext">设备管理</div>
</div> </div>
<div class="drawerbox_bo_box_itembox" @click="openCallHandle"> <div class="drawerbox_bo_box_itembox" @click="openCallHandle">
<div class="drawerbox_bo_box_icon"> <div class="drawerbox_bo_box_icon">
@@ -52,21 +56,10 @@
</div> </div>
<div class="drawerbox_bo_box_icontext">叫号</div> <div class="drawerbox_bo_box_icontext">叫号</div>
</div> </div>
<div
class="drawerbox_bo_box_itembox"
@click="router.push({ name: 'device_list' })"
>
<div class="drawerbox_bo_box_icon">
<el-icon size="40">
<TurnOff />
</el-icon>
</div>
<div class="drawerbox_bo_box_icontext">设备管理</div>
</div>
<div class="drawerbox_bo_box_itembox" @click="screenref.shows()"> <div class="drawerbox_bo_box_itembox" @click="screenref.shows()">
<div class="drawerbox_bo_box_icon"> <div class="drawerbox_bo_box_icon">
<el-icon size="40"> <el-icon size="40">
<Switch /> <Lock />
</el-icon> </el-icon>
</div> </div>
<div class="drawerbox_bo_box_icontext">锁屏</div> <div class="drawerbox_bo_box_icontext">锁屏</div>
@@ -100,6 +93,7 @@
<script setup> <script setup>
import { ref } from "vue"; import { ref } from "vue";
import { dayjs } from 'element-plus'
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { useUser } from "@/store/user.js"; import { useUser } from "@/store/user.js";
import screen from "@/components/screen.vue"; import screen from "@/components/screen.vue";

View File

@@ -3,6 +3,10 @@ import { ipcRenderer } from "electron";
import { bySubType } from "@/api/device"; import { bySubType } from "@/api/device";
import { useUser } from "@/store/user.js"; import { useUser } from "@/store/user.js";
import dayjs from "dayjs"; 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";
export const usePrint = defineStore({ export const usePrint = defineStore({
id: "print", id: "print",
@@ -12,6 +16,8 @@ export const usePrint = defineStore({
deviceLableList: [], // 添加的打印机 deviceLableList: [], // 添加的打印机
labelList: [], // 要打印的队列数据 labelList: [], // 要打印的队列数据
printTimer: null, printTimer: null,
receiptList: [], // 小票队列数据
receiptTimer: null,
}), }),
actions: { actions: {
// 获取本地打印机和已添加的可以用打印机列表 // 获取本地打印机和已添加的可以用打印机列表
@@ -98,7 +104,7 @@ export const usePrint = defineStore({
// 执行打印操作 // 执行打印操作
this.startLabelPrint(); this.startLabelPrint();
} else { } else {
console.log("没有打印机"); console.log("没有标签打印机");
} }
}, },
// 开始打印标签数据 // 开始打印标签数据
@@ -119,5 +125,96 @@ export const usePrint = defineStore({
} }
}, 800); }, 800);
}, },
// 添加小票打印对列表数据
pushReceiptData(props, isDevice = true) {
console.log("pushReceiptData===", props);
if (!isDevice) {
// 测试打印,无需校验本地打印机
const store = useUser();
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 {
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("订单小票:没有小票打印机");
}
}
},
// 开始打印小票
startReceiptPrint() {
if (this.receiptTimer !== null) return;
this.receiptTimer = setInterval(() => {
if (!this.receiptList.length) {
clearInterval(this.receiptTimer);
this.receiptTimer = null;
} else {
receiptPrint(this.receiptList[0]);
this.receiptList.splice(0, 1);
}
}, 800);
},
// 打印交班小票
printWork(data) {
if (
this.deviceNoteList.length &&
this.checkLocalPrint(this.deviceNoteList[0].config.deviceName)
) {
data.deviceName = this.deviceNoteList[0].config.deviceName;
lodopPrintWork(data);
} else {
console.log("交班小票:没有小票打印机");
}
},
// 打印订单发票
printInvoice(data) {
if (
this.deviceNoteList.length &&
this.checkLocalPrint(this.deviceNoteList[0].config.deviceName)
) {
data.deviceName = this.deviceNoteList[0].config.deviceName;
invoicePrint(data);
} else {
console.log("订单发票:没有小票打印机");
}
},
// 打印退单小票
printRefund(data) {
if (
this.deviceNoteList.length &&
this.checkLocalPrint(this.deviceNoteList[0].config.deviceName)
) {
data.deviceName = this.deviceNoteList[0].config.deviceName;
refundPrint(data);
} else {
console.log("退单小票:没有小票打印机");
}
},
}, },
}); });

View File

@@ -1,4 +1,5 @@
import _ from "lodash"; import _ from "lodash";
import { dayjs } from "element-plus";
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { useUser } from "@/store/user.js"; import { useUser } from "@/store/user.js";
import { usePrint } from "@/store/print.js"; import { usePrint } from "@/store/print.js";
@@ -56,7 +57,14 @@ export const useSocket = defineStore({
if (this.ws == null) { if (this.ws == null) {
console.log("创建新的ws连接"); console.log("创建新的ws连接");
this.ws = new ReconnectingWebSocket(wsUrl);
const protocols = []; // 可选的子协议数组
const options = {
// 自动重新连接的选项(可选)
connectionTimeout: 1000,
maxRetries: 100,
};
this.ws = new ReconnectingWebSocket(wsUrl, protocols, options);
} else { } else {
console.log("重新连接ws"); console.log("重新连接ws");
this.wsReconnect(); this.wsReconnect();
@@ -96,6 +104,7 @@ export const useSocket = defineStore({
if (!this.orderList.some((el) => el == data.orderInfo.orderNo)) { if (!this.orderList.some((el) => el == data.orderInfo.orderNo)) {
// console.log("打印", data); // console.log("打印", data);
printStore.labelPrint(data); printStore.labelPrint(data);
printStore.pushReceiptData(data);
this.orderList.push(data.orderInfo.orderNo); this.orderList.push(data.orderInfo.orderNo);
if (this.orderList.length > 30) { if (this.orderList.length > 30) {
this.orderList.splice(0, 1); this.orderList.splice(0, 1);

View File

@@ -40,9 +40,10 @@ export function clearNoNum(obj) {
* 保留小数n位不进行四舍五入 * 保留小数n位不进行四舍五入
* num你传递过来的数字, * num你传递过来的数字,
* decimal你保留的几位,默认保留小数后两位 * decimal你保留的几位,默认保留小数后两位
* isInt 是否保留0
*/ */
export function formatDecimal(num, decimal = 2) { export function formatDecimal(num, decimal = 2, isInt = false) {
num = num.toString(); num = num.toFixed(3).toString();
const index = num.indexOf("."); const index = num.indexOf(".");
if (index !== -1) { if (index !== -1) {
num = num.substring(0, decimal + index + 1); num = num.substring(0, decimal + index + 1);
@@ -50,5 +51,9 @@ export function formatDecimal(num, decimal = 2) {
num = num.substring(0); num = num.substring(0);
} }
//截取后保留两位小数 //截取后保留两位小数
return parseFloat(num).toFixed(decimal); if (isInt) {
return parseFloat(num);
} else {
return parseFloat(num).toFixed(decimal);
}
} }

61
src/utils/request_kp.js Normal file
View File

@@ -0,0 +1,61 @@
import axios from "axios";
import { ElMessage } from "element-plus";
import useStorage from "@/utils/useStorage";
import router from "@/router";
const service = axios.create({
baseURL:
import.meta.env.MODE == "development"
? "/kp/"
: import.meta.env.VITE_API_KP_URL,
// withCredentials: true, // 跨域请求时发送 cookies
timeout: 5000, // 请求超时
});
// 请求拦截器
service.interceptors.request.use(
(config) => {
// 在发送请求之前做些什么 token
config.headers["pctoken"] = useStorage.get("token");
config.headers["ispc"] = 1;
config.headers["loginName"] = useStorage.get("userInfo").loginName;
config.headers["clientType"] = "pc";
config.headers["shopId"] = useStorage.get("userInfo").shopId;
return config;
},
(error) => {
// 处理请求错误
return Promise.reject(error);
}
);
// 响应拦截器
service.interceptors.response.use(
(response) => {
// 对响应数据做点什么
if (+response.status === 200) {
if (+response.data.code == 1) {
return response.data.data;
} else {
// 响应错误
ElMessage.error(response.data.msg);
return Promise.reject(response.data);
}
}
},
(error) => {
// 对响应错误做点什么
if (error.message.indexOf("timeout") != -1) {
ElMessage.error("网络超时");
} else if (error.message == "Network Error") {
ElMessage.error("网络连接错误");
} else {
console.log(error);
if (error.response.data) ElMessage.error(error.response.statusText);
else ElMessage.error("接口路径找不到");
}
return Promise.reject(error);
}
);
export default service;

View File

@@ -7,7 +7,7 @@ const service = axios.create({
baseURL: baseURL:
import.meta.env.MODE == "development" import.meta.env.MODE == "development"
? "/php/" ? "/php/"
: import.meta.env.VITE_API_URL, : import.meta.env.VITE_API_PHP_URL,
// withCredentials: true, // 跨域请求时发送 cookies // withCredentials: true, // 跨域请求时发送 cookies
timeout: 5000, // 请求超时 timeout: 5000, // 请求超时
}); });

View File

@@ -61,11 +61,11 @@
</div> </div>
<div class="menu_wrap"> <div class="menu_wrap">
<div class="print_view"> <div class="print_view">
<div class="title t1">溜溜</div> <div class="title t1">{{ printData.shop_name }}</div>
<div class="title t2">结算单#002</div> <div class="title t2">结算单{{ printData.orderInfo.masterId }}</div>
<div class="row">订单号:202404021023542223445</div> <div class="row">订单号{{ printData.orderInfo.orderNo }}</div>
<div class="row">交易时间:2024-04-02 10:15</div> <div class="row">交易时间{{ printData.createdAt }}</div>
<div class="row">收银员:POS-11</div> <div class="row">收银员{{ printData.loginAccount }}</div>
<div class="line"></div> <div class="line"></div>
<table class="table"> <table class="table">
<tr> <tr>
@@ -74,51 +74,31 @@
<td>数量</td> <td>数量</td>
<td>小计</td> <td>小计</td>
</tr> </tr>
<tr> <tr v-for="(item, index) in printData.carts" :key="index">
<td> <td>
<div>娃哈哈矿泉水</div> <div>{{ item.name }}</div>
<div class="sku">500ml</div> <div class="sku">{{ item.skuName }}</div>
</td> </td>
<td>1.0</td> <td>{{ item.salePrice }}</td>
<td>10</td> <td>{{ item.number }}</td>
<td>10</td> <td>{{ item.totalAmount }}</td>
</tr>
<tr>
<td>
<div>柠檬奶茶</div>
<div class="sku">加冰加珍珠</div>
</td>
<td>10.0</td>
<td>2</td>
<td>20</td>
</tr> </tr>
</table> </table>
<div class="line"></div> <div class="line"></div>
<div class="row between"> <div class="row between">
<span>合计:</span> <span>合计</span>
<span>30.00</span> <span>{{ printData.amount }}</span>
</div> </div>
<div class="row between"> <div class="row between">
<span>合计:</span> <span>余额</span>
<span>30.00</span>
</div>
<div class="row between">
<span>原价:20.00节省了0</span>
</div>
<div class="row between">
<span>积分:</span>
<span>0</span>
</div>
<div class="row between">
<span>余额:</span>
<span>0.00</span> <span>0.00</span>
</div> </div>
<div class="line"></div> <div class="line"></div>
<div class="row">备注:</div> <div class="row">备注{{ printData.remark }}</div>
<div class="row">打印时间:2024-04-02 10:15</div> <div class="row">打印时间{{ printData.printTime }}</div>
<div class="btn_wrap"> <div class="btn_wrap">
<div class="btn"> <div class="btn">
<el-button plain style="width: 100%" @click="printHandle"> <el-button plain style="width: 100%" :loading="printDataLoading" @click="printHandle">
打印测试小票 打印测试小票
</el-button> </el-button>
</div> </div>
@@ -137,7 +117,7 @@
<script setup> <script setup>
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { ipcRenderer } from "electron"; import { ipcRenderer } from "electron";
import { onMounted, ref } from "vue"; import { onMounted, reactive, ref } from "vue";
import { useRouter, useRoute } from "vue-router"; import { useRouter, useRoute } from "vue-router";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { tbPrintMachinePost, tbPrintMachineDetail } from "@/api/device"; import { tbPrintMachinePost, tbPrintMachineDetail } from "@/api/device";
@@ -175,6 +155,40 @@ const form = ref({
shopId: store.userInfo.shopId, shopId: store.userInfo.shopId,
}); });
const printDataLoading = ref(false)
const printData = reactive({
shop_name: store.userInfo.shopName,
loginAccount: store.userInfo.loginAccount,
isBefore: true,
carts: [
{
id: 1,
name: '【测试】娃哈哈矿泉水',
skuName: '500ml',
salePrice: '1.0',
number: '10',
totalAmount: '10'
},
{
id: 2,
name: '【测试】柠檬奶茶',
skuName: '加冰、加珍珠',
salePrice: '10',
number: '2',
totalAmount: '20'
}
],
amount: '30.00',
remark: '给我多放点辣椒,谢谢老板',
orderInfo: {
masterId: '#002',
orderNo: '202404021023542223445'
},
deviceName: '',
createdAt: '2024-04-02 10:15',
printTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
});
// 获取打印机列表 // 获取打印机列表
function getPrintList() { function getPrintList() {
ipcRenderer.send("getPrintList"); ipcRenderer.send("getPrintList");
@@ -189,43 +203,13 @@ function printHandle() {
ElMessage.warning("请选择打印设备"); ElMessage.warning("请选择打印设备");
return; return;
} }
printDataLoading.value = true
// ipcRenderer.send( printData.deviceName = form.value.config.deviceName
// "printStart", printData.printTime = dayjs().format('YYYY-MM-DD HH:mm:ss')
// JSON.stringify({ deviceName: form.value.config.deviceName }) printStore.pushReceiptData(printData, false)
// ); setTimeout(() => {
printDataLoading.value = false
const data = { }, 1500)
shop_name: '溜溜',
carts: [
{
id: 1,
name: '娃哈哈矿泉水',
skuName: '500ml',
salePrice: '1.0',
number: '10',
totalAmount: '10'
},
{
id: 2,
name: '柠檬奶茶',
skuName: '加冰、加珍珠',
salePrice: '10',
number: '2',
totalAmount: '20'
}
],
amount: '30.00',
remark: '',
orderInfo: {
masterId: '#002',
orderNo: '202404021023542223445'
},
deviceName: form.value.config.deviceName,
createdAt: '2024-04-02 10:15',
printTime: '2024-04-02 10:15',
};
ipcRenderer.send("printerInfoSync", JSON.stringify(data));
} }
// 提交打印机 // 提交打印机

View File

@@ -179,6 +179,7 @@ const printHandle = _.throttle(function () {
ElMessage.error("请选择打印设备"); ElMessage.error("请选择打印设备");
return; return;
} }
printData.value.deviceName = form.value.config.deviceName
ipcRenderer.send( ipcRenderer.send(
"printerTagSync", "printerTagSync",
JSON.stringify(printData.value) JSON.stringify(printData.value)

View File

@@ -88,7 +88,7 @@
<div class="intro">用来打印商品标签的打印机</div> <div class="intro">用来打印商品标签的打印机</div>
</div> </div>
</div> </div>
<div class="row"> <!-- <div class="row">
<div class="icon" style="background-color: #8fc783"> <div class="icon" style="background-color: #8fc783">
<el-image :src="icons.kitchen" style="width: 44px; height: 44px"></el-image> <el-image :src="icons.kitchen" style="width: 44px; height: 44px"></el-image>
</div> </div>
@@ -96,7 +96,7 @@
<div class="name">添加出品打印机</div> <div class="name">添加出品打印机</div>
<div class="intro">用来打印商品至厨房或出品台的打印机</div> <div class="intro">用来打印商品至厨房或出品台的打印机</div>
</div> </div>
</div> </div> -->
</div> </div>
</div> </div>
</div> </div>
@@ -141,10 +141,10 @@ const deviceRoute = ref({
}); });
async function statusChange(e, item) { async function statusChange(e, item) {
console.log(e, item);
try { try {
await tbPrintMachinePost(item, "put"); await tbPrintMachinePost(item, "put");
tbPrintMachineGetAjax(); tbPrintMachineGetAjax();
printStore.init();
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }

View File

@@ -0,0 +1,104 @@
<template>
<el-dialog title="绑定门店" v-model="showDialog" width="80%">
<div class="dialog">
<div class="tips">注意门店绑定后无法更改请谨慎选择</div>
<el-table :data="tableData.list" height="240px" border v-loading="tableData.loading">
<el-table-column label="门店名称" prop="poi_name"></el-table-column>
<el-table-column label="门店地址" prop="address"></el-table-column>
<el-table-column label="操作" width="120px">
<template v-slot="scope">
<el-button type="primary" size="small"
@click="bindShopHandle(scope.row.poi_id)">选择门店</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination @current-change="paginationChange" :current-page="tableData.page"
:page-size="tableData.size" layout="total, prev, pager, next, jumper" :total="tableData.total"
background>
</el-pagination>
</div>
</div>
</el-dialog>
</template>
<script setup>
import { ElMessage } from 'element-plus'
import { onMounted, reactive, ref } from 'vue';
import { douyinstorelist, douyinbindstore } from '@/api/group.js'
const emits = defineEmits(['success'])
const showDialog = ref(false)
const tableData = reactive({
page: 1,
size: 10,
total: 0,
loading: false,
list: []
})
// 绑定门店
async function bindShopHandle(poi_id) {
try {
await douyinbindstore({
poi_id: poi_id
})
showDialog.value = false
ElMessage.success('绑定成功')
emits('success')
} catch (error) {
console.log(error);
}
}
// 分页变化
function paginationChange(e) {
tableData.page = e
getTableData()
}
// 获取门店列表
async function getTableData() {
try {
tableData.loading = true
const { list, count } = await douyinstorelist({
page: tableData.page,
size: tableData.size
})
tableData.loading = false
tableData.list = list
tableData.total = count
} catch (error) {
console.log(error);
}
}
// 显示
function show() {
showDialog.value = true;
getTableData()
}
defineExpose({
show
})
</script>
<style scoped lang="scss">
.tips {
color: var(--el-color-danger);
padding-bottom: 14px;
}
.pagination {
display: flex;
padding: 0 14px;
margin-top: 14px;
}
.dialog {
padding: 14px;
}
</style>

View File

@@ -2,7 +2,7 @@
<template> <template>
<div class="dialog"> <div class="dialog">
<el-dialog :title="`核销${props.title}团购券`" width="600" v-model="dialogVisible" @open="reset"> <el-dialog :title="`核销${props.title}团购券`" width="600" v-model="dialogVisible" @open="reset" @close="close">
<div class="content"> <div class="content">
<div class="left"> <div class="left">
<el-image :src="icon" style="width: 60px; height: 60px"></el-image> <el-image :src="icon" style="width: 60px; height: 60px"></el-image>
@@ -79,8 +79,7 @@
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<el-table ref="douyin_table" :data="groupDetail.goods" border v-if="props.type == 2" <el-table ref="douyin_table" :data="groupDetail.goods" border v-if="props.type == 2">
@selection-change="douyinSelectionChange">
<el-table-column type="selection" width="55" /> <el-table-column type="selection" width="55" />
<el-table-column label="名称" prop="title"></el-table-column> <el-table-column label="名称" prop="title"></el-table-column>
<el-table-column label="价格" prop="amount"></el-table-column> <el-table-column label="价格" prop="amount"></el-table-column>
@@ -93,6 +92,7 @@
@click="groupOrdergroupScanHandle">确认核销</el-button> @click="groupOrdergroupScanHandle">确认核销</el-button>
</div> </div>
</el-dialog> </el-dialog>
<BindShop ref="BindShopRef" @success="submitHandle()" />
</div> </div>
</template> </template>
@@ -102,6 +102,8 @@ import { ref } from "vue";
import icon from "@/assets/icon_scan.png"; import icon from "@/assets/icon_scan.png";
import { groupOrderorderInfo, groupOrdergroupScan, douyinfulfilmentcertificateprepare, douyincertificateprepare } from '@/api/group' import { groupOrderorderInfo, groupOrdergroupScan, douyinfulfilmentcertificateprepare, douyincertificateprepare } from '@/api/group'
import { useUser } from "@/store/user.js"; import { useUser } from "@/store/user.js";
import BindShop from './bindShop.vue'
const BindShopRef = ref(null)
const store = useUser(); const store = useUser();
import { import {
queryMembermember, queryMembermember,
@@ -110,6 +112,10 @@ import {
accountPaymember, accountPaymember,
} from "@/api/member/index.js"; } from "@/api/member/index.js";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { useGlobal } from '@/store/global.js'
const global = useGlobal()
const emits = defineEmits(["success"]); const emits = defineEmits(["success"]);
const props = defineProps({ const props = defineProps({
@@ -151,13 +157,20 @@ async function groupOrdergroupScanHandle() {
break; break;
case 2: case 2:
{ {
groupDetailLoading.value = true let encrypted_codes = douyin_table.value.getSelectionRows()
let encrypted_codes = groupDetail.value.goods.map(item => item.encrypted_code) if (encrypted_codes.length) {
const res = await douyincertificateprepare({ groupDetailLoading.value = true
verify_token: groupDetail.value.verify_token, let arr = encrypted_codes.map(item => item.encrypted_code)
encrypted_codes: encrypted_codes.join(','), console.log(encrypted_codes);
id: groupDetail.value.id const res = await douyincertificateprepare({
}) verify_token: groupDetail.value.verify_token,
encrypted_codes: arr.join(','),
id: groupDetail.value.id
})
} else {
ElMessage.error('请选择核销项目')
return
}
} }
break; break;
default: default:
@@ -171,17 +184,12 @@ async function groupOrdergroupScanHandle() {
emits('succcess') emits('succcess')
} catch (error) { } catch (error) {
groupDetailLoading.value = false groupDetailLoading.value = false
console.log(error); console.log('groupOrdergroupScanHandle.error', error);
} }
} }
const douyin_table = ref(null) const douyin_table = ref(null)
// 选择要核销的券
function douyinSelectionChange(e) {
console.log(e);
}
// 核销券码 // 核销券码
async function submitHandle() { async function submitHandle() {
try { try {
@@ -202,6 +210,7 @@ async function submitHandle() {
const res = await douyinfulfilmentcertificateprepare({ const res = await douyinfulfilmentcertificateprepare({
object_id: decodeURI(scanCode.value), object_id: decodeURI(scanCode.value),
}); });
dialogVisible.value = false
loading.value = false loading.value = false
groupDetail.value = res groupDetail.value = res
detailVisible.value = true detailVisible.value = true
@@ -217,7 +226,10 @@ async function submitHandle() {
} }
} catch (error) { } catch (error) {
loading.value = false loading.value = false
console.log(error); console.log('submitHandle.error', error);
if (error.code == 4399) {
BindShopRef.value.show()
}
} }
} }
@@ -255,6 +267,7 @@ const inputChange = _.debounce(function (e) {
}, 500); }, 500);
function show() { function show() {
global.updateData(false)
dialogVisible.value = true; dialogVisible.value = true;
setTimeout(() => { setTimeout(() => {
inputRef.value.focus(); inputRef.value.focus();
@@ -262,6 +275,7 @@ function show() {
} }
function close() { function close() {
global.updateData(true)
dialogVisible.value = false; dialogVisible.value = false;
} }
@@ -274,6 +288,7 @@ defineExpose({
show, show,
close, close,
loading, loading,
submitHandle
}); });
</script> </script>

View File

@@ -3,7 +3,7 @@
<div class="cart_wrap card"> <div class="cart_wrap card">
<div class="header"> <div class="header">
<div class="left"> <div class="left">
<el-select v-model="tableData.type" placeholder="核销类型"> <el-select v-model="tableData.type" placeholder="核销类型" @change="typeChange">
<el-option v-for="item in typeList" :key="item.value" :value="item.value" <el-option v-for="item in typeList" :key="item.value" :value="item.value"
:label="item.label"></el-option> :label="item.label"></el-option>
</el-select> </el-select>
@@ -79,14 +79,16 @@
<template v-slot="scope"> <template v-slot="scope">
<div class="goods_list"> <div class="goods_list">
<div class="row" v-for="item in scope.row.douyinCodeGoods" :key="item.id"> <div class="row" v-for="item in scope.row.douyinCodeGoods" :key="item.id">
<div class="item" style="flex: 1;white-space: nowrap;margin-right: 10px;"> <div class="item" style="width: 240px;">
{{ item.title }} {{ item.title }}
</div> </div>
<div class="item" style="flex: 1;margin-right: 10px;color: var(--primary-color);"> <div class="item" style="width: 100px;color: var(--primary-color);">
{{ item.pay_amount }} {{ item.pay_amount }}
</div> </div>
<div class="item" style="margin-right: 10px;"> <div class="item"
<el-tag type="success" disable-transitions size="default" effect="light" round> style="margin-right: 10px;display: flex;justify-content: flex-end;">
<el-tag :type="typeStatus(item.status)" disable-transitions size="default"
effect="light" round>
{{ item.status_text }} {{ item.status_text }}
</el-tag> </el-tag>
</div> </div>
@@ -101,9 +103,9 @@
</el-table> </el-table>
</div> </div>
<div class="pagination"> <div class="pagination">
<el-pagination @current-change="paginationChange" :current-page="tableData.page" <el-pagination v-model:current-page="tableData.page" v-model:page-size="tableData.size"
:page-size="tableData.size" layout="total, prev, pager, next, jumper" :total="tableData.total" layout="total, prev, pager, next" :total="tableData.total" background
background> @current-change="paginationChange" @size-change="paginationChange">
</el-pagination> </el-pagination>
</div> </div>
</div> </div>
@@ -121,6 +123,7 @@ import { ref, onMounted, reactive } from 'vue'
import scanGroup from './components/scanGroup.vue' import scanGroup from './components/scanGroup.vue'
import refundDialog from './components/refundDialog.vue' import refundDialog from './components/refundDialog.vue'
import { useUser } from "@/store/user.js" import { useUser } from "@/store/user.js"
import BindShop from './components/bindShop.vue'
const store = useUser() const store = useUser()
import { useGlobal } from '@/store/global.js' import { useGlobal } from '@/store/global.js'
@@ -129,10 +132,19 @@ const global = useGlobal()
const scanGroupRef = ref(null) const scanGroupRef = ref(null)
const refundDialogRef = ref(null) const refundDialogRef = ref(null)
function typeStatus(t) {
const m = {
0: 'warning',
1: 'success',
2: 'danger'
}
return m[t]
}
const tableData = reactive({ const tableData = reactive({
resetLoading: false, resetLoading: false,
proName: '', proName: '',
type: 1, type: 2,
status: '', status: '',
loading: false, loading: false,
list: [], list: [],
@@ -162,7 +174,8 @@ const typeList = reactive([
} }
]) ])
const statusList = reactive([ // 本店团购订单状态
const originStatus = [
{ {
value: 'unpaid', value: 'unpaid',
label: '待付款' label: '待付款'
@@ -187,16 +200,51 @@ const statusList = reactive([
value: 'cancelled', value: 'cancelled',
label: '已取消' label: '已取消'
} }
]) ]
// 抖音美团
const dmStatus = [
{
value: 0,
label: '等待验券'
},
{
value: 1,
label: '成功'
},
{
value: 2,
label: '失败'
}
]
const statusList = ref([])
// 切换筛选条件
function typeChange(e) {
switch (e) {
case 1:
statusList.value = [...originStatus]
break;
case 2:
statusList.value = [...dmStatus]
break;
default:
break;
}
tableData.status = ''
tableData.page = 1
tableData.list = []
groupOrderlistAjax()
}
// 状态 // 状态
function statusFilter(t) { function statusFilter(t) {
return statusList.find(item => item.value == t)?.label return originStatus.find(item => item.value == t)?.label
} }
// 分页变化 // 分页变化
function paginationChange(e) { function paginationChange(e) {
tableData.page = e
groupOrderlistAjax() groupOrderlistAjax()
} }
@@ -243,7 +291,9 @@ async function groupOrderlistAjax() {
case 2: case 2:
// 获取抖音团购数据 // 获取抖音团购数据
res = await douyinorderlist({ res = await douyinorderlist({
page: tableData.page page: tableData.page,
status: tableData.status,
d_order_id: tableData.proName
}) })
tableData.resetLoading = false tableData.resetLoading = false
tableData.loading = false tableData.loading = false
@@ -260,7 +310,7 @@ async function groupOrderlistAjax() {
} }
onMounted(() => { onMounted(() => {
groupOrderlistAjax() typeChange(tableData.type)
}) })
</script> </script>

View File

@@ -1,5 +1,4 @@
<!-- 结算订单 --> <!-- 结算订单 -->
<template> <template>
<el-drawer size="100%" :with-header="false" direction="btt" v-model="dialogVisible"> <el-drawer size="100%" :with-header="false" direction="btt" v-model="dialogVisible">
<div class="drawer_wrap"> <div class="drawer_wrap">
@@ -16,7 +15,7 @@
<span class="member_info" v-if="memberInfo.telephone">会员{{ memberInfo.telephone }}</span> <span class="member_info" v-if="memberInfo.telephone">会员{{ memberInfo.telephone }}</span>
</div> </div>
<div class="btm"> <div class="btm">
<span class="p">服务员{{ store.userInfo.shopName || "暂无" }}</span> <span class="p">服务员{{ store.userInfo.loginAccount || "暂无" }}</span>
<span class="t">{{ <span class="t">{{
props.orderInfo.createdAt && props.orderInfo.createdAt &&
dayjs(props.orderInfo.createdAt).format("MM-DD HH:mm") dayjs(props.orderInfo.createdAt).format("MM-DD HH:mm")
@@ -77,6 +76,8 @@ import { ElMessage } from "element-plus";
import dayjs from "dayjs"; import dayjs from "dayjs";
import useStorage from '@/utils/useStorage' import useStorage from '@/utils/useStorage'
import { ipcRenderer } from "electron"; import { ipcRenderer } from "electron";
import { formatDecimal } from '@/utils/index.js'
import receiptPrint from "@/components/lodop/receiptPrint.js";
import { usePrint } from '@/store/print.js' import { usePrint } from '@/store/print.js'
const printStore = usePrint() const printStore = usePrint()
@@ -121,31 +122,32 @@ const isPrint = ref(true);
const printHandle = _.throttle(async function () { const printHandle = _.throttle(async function () {
try { try {
if (!isPrint.value) return; if (!isPrint.value) return;
printLoading.value = true;
const data = { const data = {
shop_name: store.userInfo.merchantName, shop_name: store.userInfo.shopName,
loginAccount: store.userInfo.loginAccount,
isBefore: true,
carts: props.cart, carts: props.cart,
amount: props.amount, amount: props.amount,
remark: props.remark, remark: props.remark,
orderInfo: props.orderInfo, orderInfo: props.orderInfo,
createdAt: dayjs(props.orderInfo.createdAt).format( createdAt: dayjs(props.orderInfo.createdAt).format("YYYY-MM-DD HH:mm:ss"),
"YYYY-MM-DD HH:mm:ss"
),
printTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), printTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
}; };
printStore.labelPrint(data) printStore.labelPrint(data)
setTimeout(() => {
try { printLoading.value = false;
printLoading.value = true; }, 1500)
if (printStore.deviceNoteList.length) {
printStore.pushReceiptData(data)
} else {
await print({ await print({
type: "normal", type: "normal",
ispre: true, ispre: true,
orderId: props.orderInfo.id, orderId: props.orderInfo.id,
}); });
printLoading.value = false; printLoading.value = false;
// ElMessage.success("打印成功"); ElMessage.success("打印成功");
} catch (error) {
printLoading.value = false;
console.log(error);
} }
} catch (error) { } catch (error) {
console.log(error); console.log(error);
@@ -155,6 +157,7 @@ const printHandle = _.throttle(async function () {
// 打印订单标签 // 打印订单标签
async function printOrderLable() { async function printOrderLable() {
try { try {
if (!isPrint.value) return
const res = await orderfindOrder({ const res = await orderfindOrder({
shopId: store.userInfo.shopId, shopId: store.userInfo.shopId,
status: '', status: '',
@@ -166,13 +169,17 @@ async function printOrderLable() {
const printLabelOrder = res.list[0] const printLabelOrder = res.list[0]
const data = { const data = {
shop_name: store.userInfo.merchantName, shop_name: store.userInfo.shopName,
loginAccount: store.userInfo.loginAccount,
carts: [], carts: [],
amount: printLabelOrder.orderAmount,
remark: printLabelOrder.remark,
orderInfo: printLabelOrder, orderInfo: printLabelOrder,
outNumber: printLabelOrder.outNumber, outNumber: printLabelOrder.outNumber,
createdAt: dayjs(printLabelOrder.createdAt).format( createdAt: dayjs(printLabelOrder.createdAt).format(
"YYYY-MM-DD HH:mm:ss" "YYYY-MM-DD HH:mm:ss"
) ),
printTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
} }
printLabelOrder.skuInfos.map(item => { printLabelOrder.skuInfos.map(item => {
data.carts.push( data.carts.push(
@@ -180,13 +187,27 @@ async function printOrderLable() {
categoryId: item.categoryId, categoryId: item.categoryId,
name: item.productName, name: item.productName,
number: item.num, number: item.num,
skuName: item.productSkuName skuName: item.productSkuName,
salePrice: formatDecimal(item.priceAmount / item.num),
totalAmount: formatDecimal(item.priceAmount)
} }
) )
}) })
// 打印标签
// console.log('重打标签小票', data);
printStore.labelPrint(data) printStore.labelPrint(data)
if (printStore.deviceNoteList.length) {
// 打印小票
printStore.pushReceiptData(data)
} else {
await print({
type: "normal",
ispre: true,
orderId: props.orderInfo.id,
});
printLoading.value = false;
ElMessage.success("打印成功");
}
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
@@ -291,6 +312,10 @@ onMounted(() => {
.p { .p {
color: #999; color: #999;
width: 160px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
} }
} }
} }

View File

@@ -12,19 +12,23 @@
<el-text class="t">{{ masterId }}</el-text> <el-text class="t">{{ masterId }}</el-text>
</div> </div>
<div class="select_user" @click="fastCashierRef.show()" v-if="!memberInfo.telephone"> <div class="select_user" @click="fastCashierRef.show()" v-if="!memberInfo.telephone">
<el-icon class="icon"> <div class="left">
<WalletFilled /> <el-icon class="icon">
</el-icon> <WalletFilled />
<el-text class="t">快捷收银</el-text> </el-icon>
<el-text class="t">快捷收银</el-text>
</div>
<el-icon class="arrow"> <el-icon class="arrow">
<ArrowRight /> <ArrowRight />
</el-icon> </el-icon>
</div> </div>
<div class="select_user" v-else @click="clearMember"> <div class="select_user" v-else @click="clearMember">
<el-icon class="icon"> <div class="left">
<UserFilled /> <el-icon class="icon">
</el-icon> <UserFilled />
<el-text class="t">{{ memberInfo.telephone }}</el-text> </el-icon>
<el-text class="t">{{ memberInfo.telephone }}</el-text>
</div>
<el-icon class="arrow"> <el-icon class="arrow">
<Close /> <Close />
</el-icon> </el-icon>
@@ -418,7 +422,7 @@ onMounted(() => {
.menu { .menu {
background-color: var(--el-color-warning); background-color: var(--el-color-warning);
color: #fff; color: #fff;
width: 100px; width: 60px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -437,7 +441,7 @@ onMounted(() => {
} }
.number { .number {
flex: 1; width: 50px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -450,24 +454,31 @@ onMounted(() => {
} }
.select_user { .select_user {
flex: 1;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between;
background-color: var(--el-color-info-light-8); background-color: var(--el-color-info-light-8);
padding: 0 var(--el-font-size-base); padding: 0 var(--el-font-size-base);
.icon { .left {
color: var(--el-color-primary); display: flex;
font-size: 18px; align-items: center;
}
.t { .icon {
font-size: var(--el-font-size-base); color: var(--el-color-primary);
padding: 0 10px; font-size: 20px;
}
.t {
font-size: var(--el-font-size-base);
margin-left: 4px;
}
} }
.arrow { .arrow {
color: #999; color: #999;
font-size: 20px; font-size: 16px;
position: relative; position: relative;
top: 2px; top: 2px;
} }

View File

@@ -1,6 +1,9 @@
<template> <template>
<!-- <el-button @click="chooseSerial">获取串口列表</el-button> --> <!-- <el-button @click="chooseSerial">获取串口列表</el-button> -->
<el-button @click="initWebSocket()">连接ws</el-button> <el-button @click="initWebSocket()">连接ws</el-button>
<el-button @click="dakai()"></el-button>
<!-- 打印二维码 -->
<rintermodelindex ref="rintermodelindexref" :form="form" @somethingDone="handleSomethingDone"></rintermodelindex>
</template> </template>
<script setup> <script setup>
@@ -12,8 +15,24 @@ import { ipcRenderer } from 'electron'
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
import { useUser } from "@/store/user.js"; import { useUser } from "@/store/user.js";
import useStorage from '@/utils/useStorage' import useStorage from '@/utils/useStorage'
import rintermodelindex from '@/components/lodop/index.vue'
const store = useUser(); const store = useUser();
const rintermodelindexref = ref()//打印机ref
// 打印成功回调
const handleSomethingDone = () => {
console.log('打印成功回调成功')
}
const form = ref({
article: '1',
type: '2',
})
const dakai = () => {
rintermodelindexref.value.centerDialogVisibleshow() //打开二维码打印
rintermodelindexref.value.initialization()
}
// 小票打印机列表 // 小票打印机列表
const printList = ref([]); const printList = ref([]);
// 标签打印机列表 // 标签打印机列表

View File

@@ -22,7 +22,16 @@
<el-input v-model="form.loginName" placeholder="请输入11位手机号码"></el-input> <el-input v-model="form.loginName" placeholder="请输入11位手机号码"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="登录密码" prop="password"> <el-form-item label="登录密码" prop="password">
<el-input v-model="form.password" type="password" placeholder="请输入登录密码"></el-input> <el-input v-model="form.password" :type="passwordType" placeholder="请输入登录密码">
<template #suffix>
<el-icon class="el-input__icon" v-if="passwordType == 'password'" @click="passwordType = 'text'">
<Hide />
</el-icon>
<el-icon class="el-input__icon" v-else @click="passwordType = 'password'">
<View />
</el-icon>
</template>
</el-input>
</el-form-item> </el-form-item>
<!-- <el-form-item> <!-- <el-form-item>
<div style="width: 100%; display: flex; justify-content: flex-end"> <div style="width: 100%; display: flex; justify-content: flex-end">
@@ -54,7 +63,8 @@
import packageData from "../../package.json"; import packageData from "../../package.json";
import logo from "@/assets/logo.png"; import logo from "@/assets/logo.png";
import { ElMessage, ElMessageBox } from "element-plus"; import { ElMessage, ElMessageBox } from "element-plus";
import { reactive, ref } from "vue"; import { Hide, View } from '@element-plus/icons-vue'
import { onMounted, reactive, ref } from "vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { ipcRenderer } from "electron"; import { ipcRenderer } from "electron";
import { RandomNumBoth } from "@/utils"; import { RandomNumBoth } from "@/utils";
@@ -62,6 +72,8 @@ import useStorage from "@/utils/useStorage";
import { douyincheckIn } from "@/api/group"; import { douyincheckIn } from "@/api/group";
import { useUser } from "@/store/user.js"; import { useUser } from "@/store/user.js";
import { useSocket } from "@/store/socket.js"; import { useSocket } from "@/store/socket.js";
import { useGlobal } from '@/store/global.js'
const global = useGlobal()
const store = useUser(); const store = useUser();
const socket = useSocket(); const socket = useSocket();
@@ -69,6 +81,7 @@ const socket = useSocket();
const router = useRouter(); const router = useRouter();
const formRef = ref(null); const formRef = ref(null);
const loading = ref(false); const loading = ref(false);
const passwordType = ref('password')
const form = reactive({ const form = reactive({
serialNumber: RandomNumBoth(1000, 9999), serialNumber: RandomNumBoth(1000, 9999),
@@ -110,12 +123,6 @@ const submitHandle = () => {
store store
.userlogin(form) .userlogin(form)
.then(async (res) => { .then(async (res) => {
// const douyin = await douyincheckIn({
// token: res.token,
// loginName: res.loginName,
// clientType: 'pc'
// })
// useStorage.set('douyin', douyin.userInfo)
ElMessage.success("登录成功"); ElMessage.success("登录成功");
socket.init(); socket.init();
setTimeout(() => { setTimeout(() => {
@@ -123,6 +130,13 @@ const submitHandle = () => {
name: "home", name: "home",
}); });
}, 1000); }, 1000);
const douyin = await douyincheckIn({
token: res.token,
loginName: res.loginName,
clientType: 'pc'
})
useStorage.set('douyin', douyin.userInfo)
global.updateData(true)
}) })
.catch((err) => { .catch((err) => {
loading.value = false; loading.value = false;
@@ -138,6 +152,10 @@ const logout = () => {
}) })
.catch(() => { }); .catch(() => { });
}; };
onMounted(() => {
global.updateData(false)
})
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@@ -0,0 +1,134 @@
<template>
<el-dialog title="选择开票人" width="60%" v-model="dialogVisible">
<el-table :data="tableData.list" border>
<el-table-column label="开票人" prop="name"></el-table-column>
<el-table-column label="操作" width="140">
<template v-slot="scope">
<el-button type="primary" icon="" :loading="scope.row.loading"
@click="selectHandle(scope.row)">选择</el-button>
</template>
</el-table-column>
</el-table>
</el-dialog>
<el-dialog title="扫描二维码开票" width="330px" v-model="showEwmDialog">
<canvas class="ewm" ref="canvasRef"></canvas>
<div class="footer">
<el-button type="primary" style="width: 100%" :loading="printEwmLoading"
@click="printEwmHandle">打印二维码</el-button>
</div>
</el-dialog>
</template>
<script setup>
import QRCode from 'qrcode'
import { ElMessage } from 'element-plus'
import { reactive, ref } from 'vue'
import { issuedby, carsubinvoicing, syjprintqrcode } from '@/api/invoice.js'
import { useUser } from "@/store/user.js";
import { usePrint } from "@/store/print.js";
const printStore = usePrint();
const store = useUser();
const emits = defineEmits(['loadComplete', 'success'])
const dialogVisible = ref(false)
const showEwmDialog = ref(false)
const canvasRef = ref(null)
const ewmInfo = ref({})
const printEwmLoading = ref(false)
const tableData = reactive({
list: []
})
const orderInfo = ref({})
// 打印二维码
async function printEwmHandle() {
try {
printEwmLoading.value = true
if (printStore.deviceNoteList.length) {
printStore.printInvoice({
url: ewmInfo.value.wechat_url
})
ElMessage.success('打印成功')
showEwmDialog.value = false
setTimeout(() => {
printEwmLoading.value = false
}, 1000)
} else {
const res = await syjprintqrcode({
id: ewmInfo.value.id
})
ElMessage.success('打印成功')
showEwmDialog.value = false
setTimeout(() => {
printEwmLoading.value = false
}, 1000)
}
} catch (error) {
console.log(error);
printEwmLoading.value = false
}
}
// 选择开票
async function selectHandle(row) {
try {
row.loading = true
const res = await carsubinvoicing({
store_id: store.userInfo.loginName,
orderNo: orderInfo.value.id,
dlzh: row.id
})
console.log(res);
row.loading = false
ewmInfo.value = res
dialogVisible.value = false
showEwmDialog.value = true
setTimeout(() => {
QRCode.toCanvas(canvasRef.value, ewmInfo.value.wechat_url, function (error) {
if (error) console.error(error)
// console.log('success!');
})
}, 10)
} catch (error) {
row.loading = false
console.log(error);
}
}
// 获取开票人列表
async function getTableData() {
try {
const res = await issuedby({
store_id: store.userInfo.loginName
})
emits('loadComplete', false)
dialogVisible.value = true
tableData.list = res.map(item => {
item.loading = false
return item
})
} catch (error) {
console.log(error);
emits('loadComplete', false)
}
}
function show(order) {
console.log(order);
orderInfo.value = order
getTableData()
}
defineExpose({
show
})
</script>
<style scoped lang="scss">
.ewm {
width: 300px !important;
height: 300px !important;
}
</style>

View File

@@ -15,8 +15,10 @@
<div v-else style="width: 100%; text-align: center; margin: 30px 0"> <div v-else style="width: 100%; text-align: center; margin: 30px 0">
暂无数据 暂无数据
</div> </div>
<el-pagination background v-if="ordereData.list.length" layout="prev, pager, next" <el-pagination background v-if="ordereData.list.length" v-model:current-page="ordereData.page"
style="margin-top: 20px" :total="Number(ordereData.total)" @current-change="handleCurrentChange" /> v-model:page-size="ordereData.size" :page-sizes="[10, 30, 50, 100]" layout="prev, pager, next"
style="margin-top: 20px" :total="Number(ordereData.total)" @size-change="handleCurrentChange"
@current-change="handleCurrentChange" />
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="销售" name="closed"> <el-tab-pane label="销售" name="closed">
<add :loading="ordereData.loading" :ordereData="ordereData" @emititemboxshow="emititemboxshow" <add :loading="ordereData.loading" :ordereData="ordereData" @emititemboxshow="emititemboxshow"
@@ -25,8 +27,10 @@
<div v-else style="width: 100%; text-align: center; margin: 30px 0"> <div v-else style="width: 100%; text-align: center; margin: 30px 0">
暂无数据 暂无数据
</div> </div>
<el-pagination v-if="ordereData.list.length" background layout="prev, pager, next" <el-pagination background v-if="ordereData.list.length" v-model:current-page="ordereData.page"
style="margin-top: 20px" :total="Number(ordereData.total)" @current-change="handleCurrentChange" /> v-model:page-size="ordereData.size" :page-sizes="[10, 30, 50, 100]" layout="prev, pager, next"
style="margin-top: 20px" :total="Number(ordereData.total)" @size-change="handleCurrentChange"
@current-change="handleCurrentChange" />
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="退单" name="refund"> <el-tab-pane label="退单" name="refund">
<add :loading="ordereData.loading" :ordereData="ordereData" @emititemboxshow="emititemboxshow" <add :loading="ordereData.loading" :ordereData="ordereData" @emititemboxshow="emititemboxshow"
@@ -35,8 +39,10 @@
<div v-else style="width: 100%; text-align: center; margin: 30px 0"> <div v-else style="width: 100%; text-align: center; margin: 30px 0">
暂无数据 暂无数据
</div> </div>
<el-pagination v-if="ordereData.list.length" background layout="prev, pager, next" <el-pagination background v-if="ordereData.list.length" v-model:current-page="ordereData.page"
style="margin-top: 20px" :total="Number(ordereData.total)" @current-change="handleCurrentChange" /> v-model:page-size="ordereData.size" :page-sizes="[10, 30, 50, 100]" layout="prev, pager, next"
style="margin-top: 20px" :total="Number(ordereData.total)" @size-change="handleCurrentChange"
@current-change="handleCurrentChange" />
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="快捷收银" name="cash"> <el-tab-pane label="快捷收银" name="cash">
<cashTable /> <cashTable />
@@ -115,7 +121,11 @@
<div class="orderbox_right_button" ref="reforderboxrightbutton"> <div class="orderbox_right_button" ref="reforderboxrightbutton">
<div class="orderbox_right_buttonbutton"> <div class="orderbox_right_buttonbutton">
<el-button style="width: 100%" type="warning" :loading="callLoading" @click="callNumberHandle"> <el-button style="width: 100%" type="warning" :loading="callLoading" @click="callNumberHandle" v-if="
orderDetaildata.orderType != 'return' &&
(orderDetaildata.status == 'refund' ||
orderDetaildata.status == 'closed')
">
叫号 叫号
</el-button> </el-button>
</div> </div>
@@ -127,8 +137,24 @@
" type="primary" @click="recharge = true">退单</el-button> " type="primary" @click="recharge = true">退单</el-button>
</div> </div>
<div class="orderbox_right_buttonbutton"> <div class="orderbox_right_buttonbutton">
<el-button @click="print('normal')" style="flex: 1">重打收银打票</el-button> <el-button style="flex: 1" :loading="invoiceLoading" @click="invoiveHandle" v-if="
<el-button @click="print('label')" style="flex: 1">重打标签小票</el-button> orderDetaildata.orderType != 'return' &&
(orderDetaildata.status == 'refund' ||
orderDetaildata.status == 'closed')
">开发票</el-button>
<el-button :loading="normalPrintLoading" @click="print('normal')" style="flex: 1" v-if="
orderDetaildata.orderType != 'return' &&
orderDetaildata.status == 'closed'
">重打小票</el-button>
<el-button :loading="labelPrintLoading" @click="print('label')" style="flex: 1" v-if="
orderDetaildata.orderType != 'return' &&
(orderDetaildata.status == 'refund' ||
orderDetaildata.status == 'closed')
">重打标签</el-button>
<el-button :loading="normalPrintLoading" @click="print('refund')" style="flex: 1"
v-if="orderDetaildata.status == 'refund'">
重打小票
</el-button>
</div> </div>
</div> </div>
</div> </div>
@@ -251,9 +277,12 @@
¥{{ refundamount > 0 ? refundamount : "0.00" }} ¥{{ refundamount > 0 ? refundamount : "0.00" }}
</div> </div>
</div> </div>
<div class="recharge_footer_itemright_botton_boxtow" style="margin-right: 10px;">
<el-button style="width: 100%; height: 100%" @click="payreturnOrderclick(false)">手动退款</el-button>
</div>
<div class="recharge_footer_itemright_botton_boxtow"> <div class="recharge_footer_itemright_botton_boxtow">
<el-button type="primary" style="width: 100%; height: 100%" :loading="buttonloading" <el-button type="primary" style="width: 100%; height: 100%" :loading="buttonloading"
@click="payreturnOrderclick"> @click="payreturnOrderclick(true)">
<span v-if="!buttonloading">支付退回</span> <span v-if="!buttonloading">支付退回</span>
<span v-else>支付退回...</span> <span v-else>支付退回...</span>
</el-button> </el-button>
@@ -264,10 +293,12 @@
</el-dialog> </el-dialog>
</div> </div>
<takeFoodCode ref="takeFoodCodeRef" title="支付密码" type="password" placeholder="请输入支付密码" @success="passwordSuccess" /> <takeFoodCode ref="takeFoodCodeRef" title="支付密码" type="password" placeholder="请输入支付密码" @success="passwordSuccess" />
<invoice ref="invoiceRef" @load-complete="invoiceLoading = false" />
</template> </template>
<script setup> <script setup>
import { ref, onMounted, reactive } from "vue"; import { ref, onMounted, reactive } from "vue";
import { issuedby } from '@/api/invoice.js'
import { ElMessage, dayjs } from "element-plus"; import { ElMessage, dayjs } from "element-plus";
import { useUser } from "@/store/user.js"; import { useUser } from "@/store/user.js";
import lodash from "lodash"; import lodash from "lodash";
@@ -280,15 +311,20 @@ import {
} from "@/api/order/index.js"; } from "@/api/order/index.js";
import add from "@/views/order/components/add.vue"; import add from "@/views/order/components/add.vue";
import cashTable from "@/views/order/components/cashTable.vue"; import cashTable from "@/views/order/components/cashTable.vue";
import { clearNoNum } from "@/utils"; import { clearNoNum, formatDecimal } from "@/utils";
import md5 from "js-md5"; import md5 from "js-md5";
import dateRange from './components/dateRange.vue' import dateRange from './components/dateRange.vue'
import { useGlobal } from "@/store/global.js"; import { useGlobal } from "@/store/global.js";
import takeFoodCode from "@/components/takeFoodCode.vue"; import takeFoodCode from "@/components/takeFoodCode.vue";
import invoice from './components/invoice.vue'
const invoiceLoading = ref(false)
const invoiceRef = ref(null)
const takeFoodCodeRef = ref(null); const takeFoodCodeRef = ref(null);
const labelPrintLoading = ref(false)
const normalPrintLoading = ref(false)
const global = useGlobal(); const global = useGlobal();
const store = useUser(); const store = useUser();
@@ -318,13 +354,23 @@ const handlerecharge = () => {
const buttonloading = ref(); //loading const buttonloading = ref(); //loading
// 显示开票人列表
function invoiveHandle() {
invoiceLoading.value = true
invoiceRef.value.show(printLabelOrder.value)
}
// 确认选择时间 // 确认选择时间
function dateConfirm(time) { function dateConfirm(time) {
ordereData.startTime = time[0] ordereData.startTime = time[0]
ordereData.endTime = time[1] ordereData.endTime = time[1]
ordereData.page = 1
asyncorderfindOrder(); asyncorderfindOrder();
} }
// 是否线上退款
const isOnline = ref(true)
// 获取支付密码 // 获取支付密码
async function passwordSuccess(pwd) { async function passwordSuccess(pwd) {
try { try {
@@ -345,7 +391,7 @@ async function passwordSuccess(pwd) {
}); });
if (arr.length != 0) { if (arr.length != 0) {
// await payreturnOrder(arr, md5(pwd)); // await payreturnOrder(arr, md5(pwd));
await payreturnOrder(arr, ''); await payreturnOrder(arr, '', isOnline.value);
changechecked.value = false; changechecked.value = false;
recharge.value = false; recharge.value = false;
itemboxshow.value = false; itemboxshow.value = false;
@@ -355,7 +401,7 @@ async function passwordSuccess(pwd) {
asyncorderfindOrder(); asyncorderfindOrder();
} else { } else {
buttonloading.value = false; buttonloading.value = false;
ElMessage.error("没有退款项目!"); ElMessage.error("没有退款项目!");
} }
} catch (error) { } catch (error) {
buttonloading.value = false; buttonloading.value = false;
@@ -363,7 +409,9 @@ async function passwordSuccess(pwd) {
} }
const payreturnOrderclick = lodash.debounce( const payreturnOrderclick = lodash.debounce(
async () => { async (e) => {
console.log(e);
isOnline.value = e
//搜索手机号 //搜索手机号
if (refundamount.value == 0) { if (refundamount.value == 0) {
buttonloading.value = false; buttonloading.value = false;
@@ -383,8 +431,10 @@ const print = lodash.throttle(
try { try {
if (e == "label") { if (e == "label") {
// checkLabelPrint(printLabelOrder.value) // checkLabelPrint(printLabelOrder.value)
labelPrintLoading.value = true
const data = { const data = {
shop_name: store.userInfo.merchantName, shop_name: store.userInfo.shopName,
loginAccount: store.userInfo.loginAccount,
carts: [], carts: [],
orderInfo: printLabelOrder.value, orderInfo: printLabelOrder.value,
outNumber: printLabelOrder.value.outNumber, outNumber: printLabelOrder.value.outNumber,
@@ -403,16 +453,97 @@ const print = lodash.throttle(
// console.log('重打标签小票', data); // console.log('重打标签小票', data);
printStore.labelPrint(data); printStore.labelPrint(data);
} else { setTimeout(() => {
await cloudPrinterprint({ labelPrintLoading.value = false
type: e, }, 1000)
orderId: orderDetaildata.value.id, } else if (e == 'normal') {
ispre: false, if (printStore.deviceNoteList.length) {
}); normalPrintLoading.value = true
ElMessage({ const data = {
message: "成功打票", shop_name: store.userInfo.shopName,
type: "success", loginAccount: store.userInfo.loginAccount,
}); carts: [],
amount: printLabelOrder.value.orderAmount,
remark: printLabelOrder.value.remark,
orderInfo: printLabelOrder.value,
outNumber: printLabelOrder.value.outNumber,
createdAt: dayjs(printLabelOrder.value.createdAt).format(
"YYYY-MM-DD HH:mm:ss"
),
printTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
}
printLabelOrder.value.skuInfos.map(item => {
data.carts.push(
{
categoryId: item.categoryId,
name: item.productName,
number: item.num,
skuName: item.productSkuName,
salePrice: formatDecimal(item.priceAmount / item.num),
totalAmount: formatDecimal(item.priceAmount)
}
)
})
printStore.pushReceiptData(data);
setTimeout(() => {
normalPrintLoading.value = false
}, 1000)
} else {
// 云打票
await cloudPrinterprint({
type: e,
orderId: orderDetaildata.value.id,
ispre: false,
});
ElMessage({
message: "成功打票",
type: "success",
});
}
} else if (e == 'refund') {
if (printStore.deviceNoteList.length) {
normalPrintLoading.value = true
const data = {
shop_name: store.userInfo.shopName,
loginAccount: store.userInfo.loginAccount,
carts: [],
amount: printLabelOrder.value.orderAmount,
remark: printLabelOrder.value.remark,
orderInfo: printLabelOrder.value,
outNumber: printLabelOrder.value.outNumber,
createdAt: dayjs(printLabelOrder.value.createdAt).format(
"YYYY-MM-DD HH:mm:ss"
),
printTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
}
printLabelOrder.value.skuInfos.map(item => {
data.carts.push(
{
categoryId: item.categoryId,
name: item.productName,
number: item.num,
skuName: item.productSkuName,
salePrice: formatDecimal(item.priceAmount / item.num),
totalAmount: formatDecimal(item.priceAmount)
}
)
})
printStore.printRefund(data);
setTimeout(() => {
normalPrintLoading.value = false
}, 1000)
} else {
// 云打票
await cloudPrinterprint({
type: 'normal',
orderId: orderDetaildata.value.id,
ispre: false,
});
ElMessage({
message: "成功打票",
type: "success",
});
}
} }
} catch (error) { } catch (error) {
console.log(error); console.log(error);
@@ -866,19 +997,13 @@ onMounted(() => {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center;
.recharge_footer_itemright_botton_boxoneabsolute { .recharge_footer_itemright_botton_boxoneabsolute {
position: absolute;
top: 0;
left: 0;
color: #c0c0c0; color: #c0c0c0;
} }
.recharge_footer_itemright_botton_boxonetext { .recharge_footer_itemright_botton_boxonetext {
font-size: 26px; font-size: 26px;
height: 60px;
line-height: 60px;
} }
} }

View File

@@ -30,7 +30,7 @@
</template> </template>
<script setup> <script setup>
import { ref, defineEmits } from 'vue' import { ref } from 'vue'
const emit = defineEmits(['close']) const emit = defineEmits(['close'])

View File

@@ -2,12 +2,12 @@
<el-drawer size="100%" :with-header="false" direction="btt" v-model="dialogVisible"> <el-drawer size="100%" :with-header="false" direction="btt" v-model="dialogVisible">
<div class="box"> <div class="box">
<div class="box_top"> <div class="box_top">
<router-link to="/" class="box_top_left"> <div class="box_top_left" @click="dialogVisible = false">
<el-icon size="20"> <el-icon size="20">
<ArrowLeft /> <ArrowLeft />
</el-icon> </el-icon>
<div style="margin-left: 10px;">返回</div> <div style="margin-left: 4px;">返回</div>
</router-link> </div>
<router-link to='/workrecord' class="box_top_right"> <router-link to='/workrecord' class="box_top_right">
交班记录 交班记录
</router-link> </router-link>
@@ -26,7 +26,7 @@
</div> </div>
<div class="box_content_left_top_item_top"> <div class="box_content_left_top_item_top">
<div style="color:#ff5252; font-size: 30px;"> <div style="color:#ff5252; font-size: 30px;">
{{ infoData.amount || 0 }} {{ formatDecimal(infoData.amount || 0) }}
</div> </div>
<div style="margin-top: 6px; color: #666;"> <div style="margin-top: 6px; color: #666;">
营业额 营业额
@@ -36,83 +36,95 @@
<div class="box_content_left_top_item"> <div class="box_content_left_top_item">
<div class="box_content_left_top_item_botton"> <div class="box_content_left_top_item_botton">
<div style=" font-size: 20px;"> <div style=" font-size: 20px;">
{{ infoData.cashAmount || 0 }} {{ formatDecimal(infoData.cashAmount || 0) }}
</div> </div>
<div style="margin-top: 6px;"> <div style="margin-top: 6px;">
现金支付 现金支付
</div> </div>
<div style="margin-top: 6px;font-size: 14px;"> <!-- <div style="margin-top: 6px;font-size: 14px;">
查看详情 查看详情
</div> </div> -->
</div> </div>
<div class="box_content_left_top_item_botton"> <div class="box_content_left_top_item_botton">
<div style=" font-size: 20px;"> <div style=" font-size: 20px;">
{{ infoData.returnAmount || 0 }} {{ formatDecimal(infoData.returnAmount || 0) }}
</div> </div>
<div style="margin-top: 6px;"> <div style="margin-top: 6px;">
退款金额 退款金额
</div> </div>
<div style="margin-top: 6px;font-size: 14px;"> <!-- <div style="margin-top: 6px;font-size: 14px;">
查看详情 查看详情
</div> </div> -->
</div> </div>
</div> </div>
</div> </div>
<div class="box_content_left_bottom"> <div class="box_content_left_bottom">
<el-table :data="infoData.detailList" style="width: 100%;" height="400px"> <el-table :data="infoData.detailList" border style="width: 100%;" height="360px">
<el-table-column prop="productName" label="商品名称" /> <el-table-column prop="productName" label="商品名称" />
<el-table-column prop="skuName" label="规格名称" /> <el-table-column prop="skuName" label="规格名称" />
<el-table-column prop="num" label="商品数量" /> <el-table-column prop="num" label="商品数量" />
<el-table-column prop="amount" label="商品金额" /> <el-table-column prop="amount" label="商品金额">
<template v-slot="scope">
{{ formatDecimal(scope.row.amount || 0) }}
</template>
</el-table-column>
</el-table> </el-table>
</div> </div>
</div> </div>
<div class="box_content_right"> <div class="box_content_right">
<div class="box_content_right_tiem"> <div class="top">
<div class="box_content_right_tiemleft"> <div class="box_content_right_tiem">
上岗时间 <div class="box_content_right_tiemleft">
上岗时间
</div>
<div class="box_content_right_tiemright">
{{ dayjs(infoData.loginTime).format("YYYY-MM-DD HH:mm:ss") }}
</div>
</div> </div>
<div class="box_content_right_tiemright"> <div class="box_content_right_tiem">
{{ dayjs(infoData.loginTime).format("YYYY-MM-DD HH:mm:ss") }} <div class="box_content_right_tiemleft">
交班时间
</div>
<div class="box_content_right_tiemright">
{{ dayjs(infoData.loginOutTime).format("YYYY-MM-DD HH:mm:ss") }}
</div>
</div>
<div class="box_content_right_tiem">
<div class="box_content_right_tiemleft">
终端名称
</div>
<div class="box_content_right_tiemright">
{{ infoData.equipment || '无' }}
</div>
</div>
<div class="box_content_right_tiem">
<div class="box_content_right_tiemleft">
备用金
</div>
<div class="box_content_right_tiemright">
{{ infoData.pettyCash || '无' }}
</div>
</div>
<div class="box_content_right_tiem">
<div class="box_content_right_tiemleft">
收营员
</div>
<div class="box_content_right_tiemright">
{{ infoData.userName || '无' }}
</div>
</div> </div>
</div> </div>
<div class="box_content_right_tiem"> <div class="footer">
<div class="box_content_right_tiemleft"> <div class="is_shop">
交班时间 <div class="button">
<el-checkbox v-model="isPrint" border label="是否打印商品销售数据" style="width: 100%" />
</div>
</div> </div>
<div class="box_content_right_tiemright"> <div class="box_content_right_tiembutton" :loading="loading" @click="exit">
{{ dayjs(infoData.loginOutTime).format("YYYY-MM-DD HH:mm:ss") }} <span v-if="!loading">交班/关班</span>
<span v-else>交班/关班中....</span>
</div> </div>
</div> </div>
<div class="box_content_right_tiem">
<div class="box_content_right_tiemleft">
终端名称
</div>
<div class="box_content_right_tiemright">
{{ infoData.equipment || '无' }}
</div>
</div>
<div class="box_content_right_tiem">
<div class="box_content_right_tiemleft">
备用金
</div>
<div class="box_content_right_tiemright">
{{ infoData.pettyCash || '无' }}
</div>
</div>
<div class="box_content_right_tiem">
<div class="box_content_right_tiemleft">
收营员
</div>
<div class="box_content_right_tiemright">
{{ infoData.userName || '无' }}
</div>
</div>
<div class="box_content_right_tiembutton" :loading="loading" @click="exit">
<span v-if="!loading">交班/关班</span>
<span v-else>交班/关班中....</span>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -122,115 +134,89 @@
<script setup> <script setup>
import { ipcRenderer } from "electron"; import { ipcRenderer } from "electron";
import { ref, onMounted } from 'vue' import { ref, onMounted } from 'vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { ElMessage, dayjs } from 'element-plus' import { ElMessage, dayjs } from 'element-plus'
import { shopInfoqueryDuty, loginlogout, handoverData } from '@/api/work/index.js' import { tglogout } from '@/api/group.js'
import { shopInfoqueryDuty, loginlogout, handoverData, handoverprint } from '@/api/work/index.js'
import useStorage from '@/utils/useStorage' import useStorage from '@/utils/useStorage'
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { bySubType } from "@/api/device"; import { bySubType } from "@/api/device";
import { useUser } from "@/store/user.js"; import { useUser } from "@/store/user.js";
import { useSocket } from "@/store/socket.js"; import { useSocket } from "@/store/socket.js";
import { formatDecimal } from '@/utils/index.js'
import { usePrint } from "@/store/print.js";
const printStore = usePrint();
const socket = useSocket(); const socket = useSocket();
const store = useUser(); const store = useUser();
const router = useRouter(); const router = useRouter();
const dialogVisible = ref(true) //交班 const dialogVisible = ref(false) //交班
//详情数据 //详情数据
const infoData = ref({}) const infoData = ref({})
const loading = ref(false); const loading = ref(false);
const printList = ref([]); const isPrint = ref(true)
const localPrintList = ref([])
// 获取打印机状态
async function bySubTypeAjax() {
try {
const res = await bySubType({
shopId: store.userInfo.shopId,
contentType: "local",
subType: "cash",
});
printList.value = res;
} catch (error) {
console.log(error);
}
}
// 获取本地打印机列表
function getPrintList() {
ipcRenderer.send("getPrintList");
ipcRenderer.on("printList", (event, arg) => {
localPrintList.value = arg;
// console.log(localPrintList.value);
});
}
// 检查本地打印机是否能正常使用
function checkLocalPrint(deviceName) {
let print = ''
for (let item of localPrintList.value) {
if (item.name == deviceName) {
print = item
}
}
if (!print.name) {
return false
} else {
return true
}
}
// 开始交班
const exit = async () => { const exit = async () => {
try { try {
if (printList.value.length) { let data = {}
if (!checkLocalPrint(printList.value[0].config.deviceName)) { // 获取交班打印小票数据
loading.value = true; data = await handoverData({
let res = await loginlogout({ id: infoData.value.id
status: 1 })
})
// useStorage.clear() if (printStore.deviceNoteList.length) {
useStorage.del('userInfo')
useStorage.del('token')
ElMessage.success("交班成功");
setTimeout(() => {
router.replace({
name: "login",
});
}, 1000);
loading.value = false;
} else {
// 获取交班打印小票数据
const data = await handoverData({
id: infoData.value.id
})
data.deviceName = printList.value[0].config.deviceName
data.printTime = dayjs().format('YYYY-MM-DD HH:mm:ss')
ipcRenderer.send("printerWorkSync", JSON.stringify(data));
// return
// useStorage.clear()
useStorage.del('userInfo')
useStorage.del('token')
ElMessage.success("交班成功");
setTimeout(() => {
router.replace({
name: "login",
});
}, 1000);
loading.value = false;
}
} else {
loading.value = true; loading.value = true;
let res = await loginlogout({
data.printTime = dayjs().format('YYYY-MM-DD HH:mm:ss')
data.printShop = isPrint.value
printStore.printWork(data)
// return
await loginlogout({
status: 1 status: 1
}) })
useStorage.del('userInfo')
useStorage.del('token')
useStorage.del('douyin')
useStorage.del('categorysActive')
ElMessage.success("交班成功");
setTimeout(() => {
router.replace({
name: "login",
});
}, 1000);
loading.value = false;
} else {
console.log('云打印交班数据');
loading.value = true;
await tglogout()
// 退出登录
await loginlogout({
status: 1
})
// 打印交班数据
await handoverprint({
id: infoData.value.id,
isprintProduct: isPrint.value
})
// useStorage.clear() // useStorage.clear()
useStorage.del('userInfo') useStorage.del('userInfo')
useStorage.del('token') useStorage.del('token')
useStorage.del('douyin')
useStorage.del('categorysActive')
ElMessage.success("交班成功"); ElMessage.success("交班成功");
setTimeout(() => { setTimeout(() => {
router.replace({ router.replace({
@@ -241,9 +227,12 @@ const exit = async () => {
} }
socket.close() socket.close()
} catch (error) { } catch (error) {
console.log(error);
loading.value = false; loading.value = false;
} }
} }
// 获取交班打印数据前置
const infoshopInfoqueryDutys = async () => { const infoshopInfoqueryDutys = async () => {
try { try {
let res = await shopInfoqueryDuty({ let res = await shopInfoqueryDuty({
@@ -252,14 +241,23 @@ const infoshopInfoqueryDutys = async () => {
}) })
infoData.value = res infoData.value = res
} catch (error) { } catch (error) {
console.log(error);
} }
} }
onMounted(() => {
getPrintList() function show() {
bySubTypeAjax() dialogVisible.value = true
infoshopInfoqueryDutys() infoshopInfoqueryDutys()
}
defineExpose({
show
})
onMounted(() => {
// getPrintList()
// bySubTypeAjax()
}) })
</script> </script>
@@ -310,7 +308,6 @@ onMounted(() => {
.box_content_left_top { .box_content_left_top {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
border-bottom: 1px solid #ccc;
padding-bottom: 20px; padding-bottom: 20px;
.box_content_left_top_item { .box_content_left_top_item {
@@ -360,21 +357,17 @@ onMounted(() => {
.box_content_right { .box_content_right {
width: 30%; width: 30%;
height: 100%; height: 100%;
background: #fff;
margin-left: 10px; margin-left: 10px;
border-radius: 6px;
padding: 10px 12px;
position: relative; position: relative;
display: flex;
.box_content_right_tiem:nth-child(1) { flex-direction: column;
margin-top: 0; gap: 10px;
}
.box_content_right_tiem { .box_content_right_tiem {
margin-top: 10px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 10px;
.box_content_right_tiemleft { .box_content_right_tiemleft {
color: #9e9e9e; color: #9e9e9e;
@@ -383,11 +376,7 @@ onMounted(() => {
} }
.box_content_right_tiembutton { .box_content_right_tiembutton {
position: absolute;
bottom: 10px;
left: 5%;
background: #ba5050; background: #ba5050;
width: 90%;
border-radius: 5px; border-radius: 5px;
color: #fff; color: #fff;
text-align: center; text-align: center;
@@ -398,4 +387,44 @@ onMounted(() => {
} }
} }
} }
.top {
flex: 1;
background-color: #fff;
padding: 10px 0;
border-radius: 6px;
}
.footer {
padding: 10px;
background: #fff;
border-radius: 6px;
}
.is_shop {
.button {
flex: 1;
margin-bottom: 10px;
:deep(.el-checkbox.el-checkbox--large) {
height: var(--el-component-size-large);
background-color: #fff;
}
:deep(.el-checkbox__inner) {
width: 20px;
height: 20px;
&::after {
border-width: 2px;
top: 0;
left: 4px;
}
}
:deep(.el-checkbox__label) {
font-size: var(--el-font-size-base) !important;
}
}
}
</style> </style>

View File

@@ -1,130 +1,132 @@
<template> <template>
<el-drawer size="100%" :with-header="false" direction="btt" v-model="record"> <div class="box">
<div class="box"> <div class="box_top" @click="clickrecord">
<div class="box_top" @click="clickrecord"> <div class="box_top_left" @click="router.back()">
<router-link to='/work' class="box_top_left"> <el-icon size="20">
<el-icon size="20"> <ArrowLeft />
<ArrowLeft /> </el-icon>
</el-icon> <div class="box_top_right">
<div class="box_top_right"> 交班记录
交班记录 </div>
</div>
</router-link>
</div> </div>
<div class="box_content"> </div>
<div class="box_content_left"> <div class="box_content">
<div class="box_content_left_top"> <div class="box_content_left">
<div class="box_content_left_top_item"> <div class="box_content_left_top">
<div class="box_content_left_top_item_top"> <div class="box_content_left_top_item">
<div> <div class="box_content_left_top_item_top">
{{ infoData.total }} <div>
</div> {{ infoData.total }}
<div>
交班数
</div>
</div> </div>
<div class="box_content_left_top_item_top"> <div>
<div> 交班数
{{ infoData.amount }} </div>
</div> </div>
<div> <div class="box_content_left_top_item_top">
总收款 <div>
</div> {{ infoData.amount }}
</div>
<div>
总收款
</div> </div>
</div> </div>
</div> </div>
<div class="box_content_left_bouttom"> </div>
<div class="box_content_left_bouttomox"> <div class="box_content_left_bouttom">
<div class="box_content_left_bouttom_item" v-for="(item, index) in infoData.pageInfo.list" <div class="box_content_left_bouttomox">
:key="index"> <div class="box_content_left_bouttom_item" v-for="(item, index) in infoData.pageInfo.list"
<div class="wbox_content_left_bouttom_item_top"> :key="index">
<div> <div class="wbox_content_left_bouttom_item_top">
{{ dayjs(item.loginTime).format("YYYY-MM-DD HH:mm:ss") }} <div>
</div> {{ dayjs(item.loginTime).format("YYYY-MM-DD HH:mm:ss") }}
<div>
{{ item.amount }}
</div>
</div> </div>
<div class="wbox_content_left_bouttom_item_topone"> <div>
<div style="display: flex;"> {{ item.amount }}
<span>收营员</span>
<span style="font-weight: bold;">{{ item.userName }}</span>
</div>
<div style="display: flex;">
<span>总订单数</span>
<span style="font-weight: bold;">{{ item.orderNum }}</span>
</div>
</div> </div>
<div class="wbox_content_left_bouttom_item_topone"> </div>
<div style="display: flex;"> <div class="wbox_content_left_bouttom_item_topone">
<span>起止时间</span> <div style="display: flex;">
<span style="font-weight: bold;"> {{ dayjs(item.loginTime).format("YYYY-MM-DD HH:mm:ss") }}</span> <span>收营员</span>
</div> <span style="font-weight: bold;">{{ item.userName }}</span>
<div style="display: flex;"> </div>
<span>备用金</span> <div style="display: flex;">
<span style="font-weight: bold;">{{ item.pettyCash }}</span> <span>总订单数</span>
</div> <span style="font-weight: bold;">{{ item.orderNum }}</span>
</div>
</div>
<div class="wbox_content_left_bouttom_item_topone">
<div style="display: flex;">
<span>起止时间</span>
<span style="font-weight: bold;"> {{
dayjs(item.loginTime).format("YYYY-MM-DD HH:mm:ss") }}</span>
</div>
<div style="display: flex;">
<span>备用金</span>
<span style="font-weight: bold;">{{ item.pettyCash }}</span>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!-- <div class="box_content_right">
<div class="box_content_right_tiem">
<div class="box_content_right_tiemleft">
上岗时间
</div>
<div class="box_content_right_tiemright">
2024-03-05-19:33
</div>
</div>
<div class="box_content_right_tiem">
<div class="box_content_right_tiemleft">
交班时间
</div>
<div class="box_content_right_tiemright">
2024-03-05-19:33
</div>
</div>
<div class="box_content_right_tiem">
<div class="box_content_right_tiemleft">
终端名称
</div>
<div class="box_content_right_tiemright">
POS-1
</div>
</div>
<div class="box_content_right_tiem">
<div class="box_content_right_tiemleft">
备用金
</div>
<div class="box_content_right_tiemright">
0.00
</div>
</div>
<div class="box_content_right_tiem">
<div class="box_content_right_tiemleft">
收营员
</div>
<div class="box_content_right_tiemright">
测试
</div>
</div>
<div class="box_content_right_tiembutton">
关班/退出
</div>
</div> -->
</div> </div>
<!-- <div class="box_content_right">
<div class="box_content_right_tiem">
<div class="box_content_right_tiemleft">
上岗时间
</div>
<div class="box_content_right_tiemright">
2024-03-05-19:33
</div>
</div>
<div class="box_content_right_tiem">
<div class="box_content_right_tiemleft">
交班时间
</div>
<div class="box_content_right_tiemright">
2024-03-05-19:33
</div>
</div>
<div class="box_content_right_tiem">
<div class="box_content_right_tiemleft">
终端名称
</div>
<div class="box_content_right_tiemright">
POS-1
</div>
</div>
<div class="box_content_right_tiem">
<div class="box_content_right_tiemleft">
备用金
</div>
<div class="box_content_right_tiemright">
0.00
</div>
</div>
<div class="box_content_right_tiem">
<div class="box_content_right_tiemleft">
收营员
</div>
<div class="box_content_right_tiemright">
测试
</div>
</div>
<div class="box_content_right_tiembutton">
关班/退出
</div>
</div> -->
</div> </div>
</el-drawer> </div>
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from 'vue' import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { shopinfoqueryDutyFlow } from '@/api/work/index.js' import { shopinfoqueryDutyFlow } from '@/api/work/index.js'
import { useUser } from "@/store/user.js" import { useUser } from "@/store/user.js"
import { ElMessage, dayjs } from 'element-plus' import { ElMessage, dayjs } from 'element-plus'
const router = useRouter()
const store = useUser() const store = useUser()
const record = ref(true)//交班记录 const record = ref(true)//交班记录
//详情数据 //详情数据
@@ -150,8 +152,10 @@ onMounted(() => {
<style scoped lang="scss"> <style scoped lang="scss">
.box { .box {
padding: 16px 0; width: 100%;
height: 100%; padding: 16px;
height: 100vh;
background-color: #efefef;
.box_top { .box_top {
display: flex; display: flex;
@@ -160,7 +164,7 @@ onMounted(() => {
background: #fff; background: #fff;
padding: 6px 10px; padding: 6px 10px;
border-radius: 6px; border-radius: 6px;
/* 取消下划线效果 */ /* 取消下划线效果 */
.box_top_left { .box_top_left {
display: flex; display: flex;
@@ -214,13 +218,16 @@ onMounted(() => {
.box_content_left_bouttom { .box_content_left_bouttom {
width: 100%; width: 100%;
height: 80%; height: 85%;
padding: 0 20px; padding: 0 20px;
overflow-y: auto;
.box_content_left_bouttomox::after { .box_content_left_bouttomox::after {
content: ''; content: '';
display: inline-block; display: inline-block;
width: 32%; width: 32%;
} }
.box_content_left_bouttomox { .box_content_left_bouttomox {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;

View File

@@ -20,6 +20,11 @@ export default defineConfig(({ command, mode }) => {
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/php/, ""), rewrite: (path) => path.replace(/^\/php/, ""),
}, },
"/kp": {
target: env.VITE_API_KP_URL,
changeOrigin: true,
rewrite: (path) => path.replace(/^\/kp/, ""),
},
}, },
}, },
plugins: [ plugins: [
@@ -34,5 +39,8 @@ export default defineConfig(({ command, mode }) => {
"@": path.resolve(__dirname, "./src"), "@": path.resolve(__dirname, "./src"),
}, },
}, },
esbuild: {
drop: ["console"],
},
}; };
}); });