Compare commits
47 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| de8c5e20f4 | |||
| 8e69969c0e | |||
| 105e38c726 | |||
| 1f20c18384 | |||
| c7758f66d7 | |||
| 78672a0cf9 | |||
| 105ad4ee52 | |||
| 89b078daae | |||
| b5356d8370 | |||
| f3dfd4a121 | |||
| 87627e7b35 | |||
|
|
408e0e44c4 | ||
| c4cb307275 | |||
| ed8b593c1a | |||
|
|
776523c1ea | ||
| 328b512411 | |||
| 44495c3ee7 | |||
| 0b2b4b44d0 | |||
| c86fff9691 | |||
| 1439f12ee5 | |||
| fde0ed0eaf | |||
| 883eb268f3 | |||
| 0b42be9964 | |||
| a1c8757aaf | |||
| b6030331ff | |||
| ffb6807a90 | |||
| 69a74cc416 | |||
| bcdf4a5b73 | |||
| 4e954e42d5 | |||
| a5e04e3f97 | |||
| 1f5f910e99 | |||
| c9dc11fa93 | |||
| 3b0e6513c7 | |||
| bf0614e10b | |||
| 69482f81a7 | |||
| 6d7db2d743 | |||
| c54304f3d6 | |||
| 6c1e34be7a | |||
| b8ea253d6e | |||
| 6df40c8423 | |||
| d08ef6f271 | |||
| 94fb2d2c8e | |||
| 443f9ed305 | |||
| 5c56f5a277 | |||
| dbc7444e78 | |||
| 6f378cc3c0 | |||
| 43ccf82177 |
@@ -1,7 +1,28 @@
|
||||
# 本地环境
|
||||
ENV = development
|
||||
|
||||
# 本地环境接口地址
|
||||
VITE_API_URL = 'http://192.168.2.27:10587/cashier-client'
|
||||
# VITE_API_URL = 'https://cashiernew.sxczgkj.cn/cashier-client'
|
||||
# VITE_API_URL = 'https://cashierclient.sxczgkj.cn/cashier-client/'
|
||||
|
||||
# 正式ws
|
||||
VITE_API_WSS = 'wss://cashier.sxczgkj.cn/client'
|
||||
|
||||
#测试ws
|
||||
# VITE_API_WSS = 'wss://wxcashiertest.sxczgkj.cn/client'
|
||||
|
||||
# 阿伟本地ws
|
||||
# VITE_API_WSS = 'ws://192.168.2.17:9998/client'
|
||||
|
||||
|
||||
# 测试 php
|
||||
VITE_API_PHP_URL = 'http://192.168.2.33:1666/index.php/api'
|
||||
|
||||
# 阿伟
|
||||
# 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 = 'https://cashier-client.sxczgkj.cn/cashier-client'
|
||||
|
||||
# 正式
|
||||
VITE_API_URL = 'https://cashierclient.sxczgkj.cn/cashier-client'
|
||||
@@ -1,6 +1,17 @@
|
||||
# 线上环境
|
||||
ENV = production
|
||||
|
||||
# 正式ws
|
||||
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'
|
||||
|
||||
# 测试
|
||||
# VITE_API_URL = 'https://cashier-client.sxczgkj.cn/cashier-client'
|
||||
|
||||
# 线上环境接口地址
|
||||
VITE_API_URL = 'https://cashierclient.sxczgkj.cn/cashier-client/'
|
||||
# VITE_API_URL = 'https://cashiernew.sxczgkj.cn/cashier-client'
|
||||
@@ -79,6 +79,91 @@ electron.app.whenReady().then(() => {
|
||||
}
|
||||
});
|
||||
});
|
||||
const workPrintWin = new electron.BrowserWindow({
|
||||
show: false,
|
||||
width: 464,
|
||||
height: 1726,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false
|
||||
}
|
||||
});
|
||||
if (process.env.VITE_DEV_SERVER_URL) {
|
||||
workPrintWin.loadFile(path.join(__dirname, "../public/work_print.html"));
|
||||
} else {
|
||||
workPrintWin.loadFile(path.resolve(__dirname, "../dist/work_print.html"));
|
||||
}
|
||||
electron.ipcMain.on("printerWorkSync", (event, arg) => {
|
||||
workPrintWin.webContents.send("getParams", arg);
|
||||
});
|
||||
electron.ipcMain.on("printWorkStart", (event, arg) => {
|
||||
const _parmas = JSON.parse(arg);
|
||||
let name = _parmas.deviceName;
|
||||
workPrintWin.webContents.print({
|
||||
silent: true,
|
||||
deviceName: name,
|
||||
pageSize: {
|
||||
width: 58e3,
|
||||
height: 216e3
|
||||
},
|
||||
scaleFactor: 80,
|
||||
landscape: false,
|
||||
margins: {
|
||||
marginType: "none",
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0
|
||||
},
|
||||
dpi: {
|
||||
horizontal: 203,
|
||||
vertical: 203
|
||||
}
|
||||
});
|
||||
});
|
||||
const tagPrintWin = new electron.BrowserWindow({
|
||||
show: false,
|
||||
width: 320,
|
||||
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: 4e4,
|
||||
height: 3e4
|
||||
},
|
||||
scaleFactor: 80,
|
||||
landscape: false,
|
||||
margins: {
|
||||
marginType: "none",
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0
|
||||
},
|
||||
dpi: {
|
||||
horizontal: 203,
|
||||
vertical: 203
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
electron.app.on("window-all-closed", () => {
|
||||
if (process.platform !== "darwin")
|
||||
|
||||
150
electron/main.js
150
electron/main.js
@@ -1,5 +1,6 @@
|
||||
import path from "path";
|
||||
import { app, BrowserWindow, ipcMain } from "electron";
|
||||
// const SerialPort = require("serialport");
|
||||
|
||||
let win;
|
||||
app.whenReady().then(() => {
|
||||
@@ -40,11 +41,21 @@ app.whenReady().then(() => {
|
||||
});
|
||||
|
||||
// 给渲染进程返回打印机列表
|
||||
ipcMain.on('getPrintList', () => {
|
||||
win.webContents.getPrintersAsync().then(res => {
|
||||
win.webContents.send('printList', res)
|
||||
})
|
||||
})
|
||||
ipcMain.on("getPrintList", () => {
|
||||
win.webContents.getPrintersAsync().then((res) => {
|
||||
win.webContents.send("printList", res);
|
||||
});
|
||||
});
|
||||
|
||||
// ipcMain.on("getSerialPort", () => {
|
||||
// SerialPort.SerialPort.list().then(
|
||||
// (ports) => {
|
||||
// console.log(ports);
|
||||
// win.webContents.send("seriaportList", ports);
|
||||
// },
|
||||
// (err) => console.error(err)
|
||||
// );
|
||||
// });
|
||||
|
||||
// 创建打印小票子窗口
|
||||
const printWin = new BrowserWindow({
|
||||
@@ -66,22 +77,22 @@ app.whenReady().then(() => {
|
||||
}
|
||||
|
||||
// 接收订单页面发过来的参数发送给打印页
|
||||
ipcMain.on('printerInfoSync', (event, arg) => {
|
||||
printWin.webContents.send('getParams', arg)
|
||||
})
|
||||
ipcMain.on("printerInfoSync", (event, arg) => {
|
||||
printWin.webContents.send("getParams", arg);
|
||||
});
|
||||
|
||||
// 执行打印操作
|
||||
ipcMain.on('printStart', (event, arg) => {
|
||||
ipcMain.on("printStart", (event, arg) => {
|
||||
console.log(arg);
|
||||
const _parmas = JSON.parse(arg)
|
||||
const _parmas = JSON.parse(arg);
|
||||
// console.log(_parmas)
|
||||
let name = _parmas.deviceName
|
||||
let name = _parmas.deviceName;
|
||||
printWin.webContents.print({
|
||||
silent: true,
|
||||
deviceName: name,
|
||||
pageSize: {
|
||||
width: 58000,
|
||||
height: 216000
|
||||
height: 216000,
|
||||
},
|
||||
scaleFactor: 80,
|
||||
landscape: false,
|
||||
@@ -90,14 +101,119 @@ app.whenReady().then(() => {
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0
|
||||
right: 0,
|
||||
},
|
||||
dpi: {
|
||||
horizontal: 203,
|
||||
vertical: 203
|
||||
}
|
||||
})
|
||||
})
|
||||
vertical: 203,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 交班小票的窗口
|
||||
const workPrintWin = new BrowserWindow({
|
||||
show: false,
|
||||
width: 464,
|
||||
height: 1726,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false,
|
||||
},
|
||||
});
|
||||
|
||||
if (process.env.VITE_DEV_SERVER_URL) {
|
||||
// 加载打印的html文件
|
||||
workPrintWin.loadFile(path.join(__dirname, "../public/work_print.html"));
|
||||
} else {
|
||||
workPrintWin.loadFile(path.resolve(__dirname, "../dist/work_print.html")); // 打包后使用文件路径访问应用
|
||||
}
|
||||
|
||||
// 接收渲染进程发送的数据
|
||||
ipcMain.on("printerWorkSync", (event, arg) => {
|
||||
workPrintWin.webContents.send("getParams", arg);
|
||||
});
|
||||
|
||||
// 执行交班小票的打印操作
|
||||
ipcMain.on("printWorkStart", (event, arg) => {
|
||||
// console.log(arg);
|
||||
const _parmas = JSON.parse(arg);
|
||||
// console.log(_parmas)
|
||||
let name = _parmas.deviceName;
|
||||
workPrintWin.webContents.print({
|
||||
silent: true,
|
||||
deviceName: name,
|
||||
pageSize: {
|
||||
width: 58000,
|
||||
height: 216000,
|
||||
},
|
||||
scaleFactor: 80,
|
||||
landscape: false,
|
||||
margins: {
|
||||
marginType: "none",
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
},
|
||||
dpi: {
|
||||
horizontal: 203,
|
||||
vertical: 203,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// 标签小票的窗口
|
||||
const tagPrintWin = new BrowserWindow({
|
||||
show: false,
|
||||
width: 320,
|
||||
height: 240,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false,
|
||||
},
|
||||
});
|
||||
|
||||
if (process.env.VITE_DEV_SERVER_URL) {
|
||||
// 加载打印的html文件
|
||||
tagPrintWin.loadFile(path.join(__dirname, "../public/tag_print.html"));
|
||||
} else {
|
||||
tagPrintWin.loadFile(path.resolve(__dirname, "../dist/tag_print.html")); // 打包后使用文件路径访问应用
|
||||
}
|
||||
|
||||
// 接收渲染进程发送的数据
|
||||
ipcMain.on("printerTagSync", (event, arg) => {
|
||||
console.log(arg);
|
||||
tagPrintWin.webContents.send("getParams", arg);
|
||||
});
|
||||
|
||||
// 执行标签小票的打印操作
|
||||
ipcMain.on("printTagStart", (event, arg) => {
|
||||
// console.log(arg);
|
||||
const _parmas = JSON.parse(arg);
|
||||
// console.log(_parmas)
|
||||
let name = _parmas.deviceName;
|
||||
tagPrintWin.webContents.print({
|
||||
silent: true,
|
||||
deviceName: name,
|
||||
pageSize: {
|
||||
width: 40000,
|
||||
height: 30000,
|
||||
},
|
||||
scaleFactor: 80,
|
||||
landscape: false,
|
||||
margins: {
|
||||
marginType: "none",
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
},
|
||||
dpi: {
|
||||
horizontal: 203,
|
||||
vertical: 203,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
app.on("window-all-closed", () => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "vite-electron",
|
||||
"private": true,
|
||||
"version": "1.0.25",
|
||||
"version": "1.3.41",
|
||||
"main": "dist-electron/main.js",
|
||||
"scripts": {
|
||||
"dev": "chcp 65001 && vite",
|
||||
@@ -18,6 +18,11 @@
|
||||
"element-plus": "^2.4.3",
|
||||
"lodash": "^4.17.21",
|
||||
"pinia": "^2.1.7",
|
||||
"qrcode": "^1.5.3",
|
||||
"reconnecting-websocket": "^4.4.0",
|
||||
"serialport": "^12.0.0",
|
||||
"swiper": "^11.1.1",
|
||||
"uuid": "^10.0.0",
|
||||
"vue": "^3.3.8",
|
||||
"vue-router": "^4.2.5"
|
||||
},
|
||||
|
||||
BIN
public/logo.png
Normal file
BIN
public/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.2 KiB |
1540
public/qrcode.js
Normal file
1540
public/qrcode.js
Normal file
File diff suppressed because it is too large
Load Diff
71
public/tag_print.css
Normal file
71
public/tag_print.css
Normal file
@@ -0,0 +1,71 @@
|
||||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
font-size: 12px;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
padding: 2mm;
|
||||
}
|
||||
|
||||
#app {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.print_view {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
.print_view .ewm {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 99;
|
||||
}
|
||||
.print_view .header {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
.print_view .header .logo {
|
||||
width: 90px;
|
||||
}
|
||||
.print_view .header .title {
|
||||
margin-left: 6px;
|
||||
}
|
||||
.print_view .number_wrap {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-align: end;
|
||||
-ms-flex-align: end;
|
||||
align-items: flex-end;
|
||||
}
|
||||
.print_view .number_wrap .num {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.print_view .number_wrap .info {
|
||||
margin-left: 12px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
.print_view .time {
|
||||
font-weight: bold;
|
||||
}
|
||||
80
public/tag_print.html
Normal file
80
public/tag_print.html
Normal file
@@ -0,0 +1,80 @@
|
||||
<!--
|
||||
~ Copyright (c) 2023. Author Hubert Formin <2399270194@qq.com>
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Print preview</title>
|
||||
<link rel="stylesheet" href="./tag_print.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app">
|
||||
<div class="print_view">
|
||||
<div class="ewm" id="ewm"></div>
|
||||
<div class="header">
|
||||
<img class="logo" src="./logo.png" />
|
||||
<!-- <span class="title">双屿Pisces</span> -->
|
||||
</div>
|
||||
<div class="number_wrap">
|
||||
<div class="num" v-if="data.outNumber">{{data.outNumber}}</div>
|
||||
<div class="info" v-if="data.masterId">座位号:{{data.masterId}}</div>
|
||||
</div>
|
||||
<div class="shop_info">
|
||||
<div class="name">{{data.name}}</div>
|
||||
<div class="text" v-if="data.skuName">【{{data.skuName}}】</div>
|
||||
</div>
|
||||
<div class="time">{{data.createdAt}}</div>
|
||||
<div class="tips">建议尽快享用,风味更佳 {{ data.count }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="./qrcode.js"></script>
|
||||
<script type="module">
|
||||
const { ipcRenderer } = require("electron");
|
||||
|
||||
import {
|
||||
createApp,
|
||||
ref,
|
||||
onMounted,
|
||||
} from "../node_modules/vue/dist/vue.esm-browser.js";
|
||||
|
||||
createApp({
|
||||
setup() {
|
||||
const data = ref({});
|
||||
|
||||
onMounted(() => {
|
||||
ipcRenderer.on("getParams", (event, arg) => {
|
||||
data.value = JSON.parse(arg);
|
||||
// console.log(data.value);
|
||||
|
||||
let size = 46;
|
||||
let qrcode = new QRCode(document.getElementById("ewm"), {
|
||||
text: data.value.outNumber,
|
||||
width: size,
|
||||
height: size,
|
||||
correctLevel: QRCode.CorrectLevel.H,
|
||||
});
|
||||
|
||||
ipcRenderer.send(
|
||||
"printTagStart",
|
||||
JSON.stringify({ deviceName: data.value.deviceName })
|
||||
);
|
||||
|
||||
// setTimeout(() => {
|
||||
// ipcRenderer.send(
|
||||
// "printTagStart",
|
||||
// JSON.stringify({ deviceName: data.value.deviceName })
|
||||
// );
|
||||
// }, 100);
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
data,
|
||||
};
|
||||
},
|
||||
}).mount("#app");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
60
public/tag_print.scss
Normal file
60
public/tag_print.scss
Normal file
@@ -0,0 +1,60 @@
|
||||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
font-size: 12px;
|
||||
color: #000;
|
||||
}
|
||||
html,
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
body {
|
||||
padding: 2mm;
|
||||
}
|
||||
#app{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.print_view {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
.ewm {
|
||||
$size: 50px;
|
||||
width: $size;
|
||||
height: $size;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 99;
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.logo {
|
||||
$size: 90px;
|
||||
width: $size;
|
||||
}
|
||||
.title {
|
||||
margin-left: 6px;
|
||||
}
|
||||
}
|
||||
.number_wrap {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
.num {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.info {
|
||||
margin-left: 12px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
}
|
||||
.time {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
83
public/work_print.css
Normal file
83
public/work_print.css
Normal file
@@ -0,0 +1,83 @@
|
||||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
padding: 0 8mm;
|
||||
}
|
||||
|
||||
.empty {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.print_view {
|
||||
padding: 20px 0;
|
||||
}
|
||||
.print_view .title {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.print_view .title.t1 {
|
||||
font-size: 24px;
|
||||
}
|
||||
.print_view .title.t2 {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.print_view .row {
|
||||
margin-top: 2px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.print_view .row.between {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-pack: justify;
|
||||
-ms-flex-pack: justify;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.print_view .line {
|
||||
margin: 10px 0;
|
||||
border-bottom: 1px solid #000;
|
||||
}
|
||||
.print_view .table {
|
||||
width: 100%;
|
||||
}
|
||||
.print_view .table tr {
|
||||
width: 100%;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
}
|
||||
.print_view .table tr:not(:last-child) {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.print_view .table tr td {
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex: 1;
|
||||
flex: 1;
|
||||
font-size: 12px;
|
||||
}
|
||||
.print_view .table tr td:nth-child(1) {
|
||||
-webkit-box-flex: 2;
|
||||
-ms-flex: 2;
|
||||
flex: 2;
|
||||
}
|
||||
.print_view .table tr td:not(:first-child) {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-pack: end;
|
||||
-ms-flex-pack: end;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.print_view .table tr td .sku {
|
||||
font-size: 10px;
|
||||
}
|
||||
80
public/work_print.html
Normal file
80
public/work_print.html
Normal file
@@ -0,0 +1,80 @@
|
||||
<!--
|
||||
~ Copyright (c) 2023. Author Hubert Formin <2399270194@qq.com>
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Print preview</title>
|
||||
<link rel="stylesheet" href="./work_print.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app">
|
||||
<div class="print_view">
|
||||
<div class="title t1">{{data.merchantName}}</div>
|
||||
<div class="title t2">交班小票</div>
|
||||
<div class="row">交班时间:{{data.startTime}}</div>
|
||||
<div class="row">收银员:{{data.staff}}</div>
|
||||
<div class="row">当班收入:{{data.totalAmount}}</div>
|
||||
<div class="row" v-for="(item,index) in data.payInfos" :key="index">
|
||||
  {{item.payType }}:{{item.amount}}
|
||||
</div>
|
||||
<div class="row">会员数据</div>
|
||||
<div class="row" v-for="(item,index) in data.memberData" :key="index">
|
||||
  {{item.deposit }}:{{item.amount}}
|
||||
</div>
|
||||
<div class="row">分类数据</div>
|
||||
<div
|
||||
class="row"
|
||||
v-for="(item,index) in data.productCategories"
|
||||
:key="index"
|
||||
>
|
||||
  {{item.categoryName
|
||||
}} {{item.num}} {{item.amount}}
|
||||
</div>
|
||||
<div class="row">快捷收款金额:{{data.quickAmount}}</div>
|
||||
<div class="row">退款金额:{{data.returnAmount}}</div>
|
||||
<div class="row">总收入:{{data.totalAmount}}</div>
|
||||
<div class="row">备用金:{{data.imprest}}</div>
|
||||
<div class="row">应交金额:{{data.payable}}</div>
|
||||
<div class="row">上交金额:{{data.handIn}}</div>
|
||||
<div class="empty"></div>
|
||||
<div class="row">总订单数:{{data.orderNum}}</div>
|
||||
<div class="row">打印时间:{{data.printTime}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="module">
|
||||
const { ipcRenderer } = require("electron");
|
||||
import {
|
||||
createApp,
|
||||
ref,
|
||||
onMounted,
|
||||
} from "../node_modules/vue/dist/vue.esm-browser.js";
|
||||
|
||||
createApp({
|
||||
setup() {
|
||||
const data = ref({});
|
||||
|
||||
onMounted(() => {
|
||||
ipcRenderer.on("getParams", (event, arg) => {
|
||||
data.value = JSON.parse(arg);
|
||||
console.log(data.value);
|
||||
|
||||
setTimeout(() => {
|
||||
ipcRenderer.send(
|
||||
"printWorkStart",
|
||||
JSON.stringify({ deviceName: data.value.deviceName })
|
||||
);
|
||||
}, 500);
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
data,
|
||||
};
|
||||
},
|
||||
}).mount("#app");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
74
public/work_print.scss
Normal file
74
public/work_print.scss
Normal file
@@ -0,0 +1,74 @@
|
||||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body {
|
||||
padding: 0 8mm;
|
||||
}
|
||||
.empty {
|
||||
height: 20px;
|
||||
}
|
||||
.print_view {
|
||||
padding: 20px 0;
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 4px;
|
||||
|
||||
&.t1 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
&.t2 {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.row {
|
||||
margin-top: 2px;
|
||||
font-size: 12px;
|
||||
|
||||
&.between {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
.line {
|
||||
margin: 10px 0;
|
||||
border-bottom: 1px solid #000;
|
||||
}
|
||||
|
||||
.table {
|
||||
width: 100%;
|
||||
|
||||
tr {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
td {
|
||||
flex: 1;
|
||||
font-size: 12px;
|
||||
|
||||
&:nth-child(1) {
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
&:not(:first-child) {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.sku {
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
409
src/App.vue
409
src/App.vue
@@ -2,7 +2,7 @@
|
||||
<el-config-provider size="large">
|
||||
<div class="container">
|
||||
<div class="left" v-if="!hideLeftMenu">
|
||||
<left-menu />
|
||||
<left-menu ref="leftMenuRef" @connectWsHandle="initWebSocket()" />
|
||||
</div>
|
||||
<div :class="{ view: !hideLeftMenu }">
|
||||
<!-- <div class="wrapper">
|
||||
@@ -22,26 +22,76 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, watch } from "vue";
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { ref, reactive, watch, onMounted } from "vue";
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
import leftMenu from "@/components/leftMenu.vue";
|
||||
import useStorage from '@/utils/useStorage'
|
||||
import { useUser } from "@/store/user.js";
|
||||
import { dayjs, ElMessage } from "element-plus";
|
||||
import { scanSendMessage } from '@/api/order/index'
|
||||
import { useGlobal } from '@/store/global.js'
|
||||
import { useSocket } from '@/store/socket.js'
|
||||
import { usePrint } from '@/store/print.js'
|
||||
import ReconnectingWebSocket from 'reconnecting-websocket';
|
||||
|
||||
const global = useGlobal()
|
||||
const socketStore = useSocket()
|
||||
const printStore = usePrint()
|
||||
|
||||
const leftMenuRef = ref(null)
|
||||
|
||||
const uuid = ref('')
|
||||
|
||||
function createUUID() {
|
||||
if (!useStorage.get('uuid')) {
|
||||
useStorage.set('uuid', uuidv4())
|
||||
uuid.value = useStorage.get('uuid')
|
||||
} else {
|
||||
uuid.value = useStorage.get('uuid')
|
||||
}
|
||||
}
|
||||
|
||||
const store = useUser();
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
const includeList = reactive([]);
|
||||
const hideLeftMenu = ref(false);
|
||||
watch(route, (to) => {
|
||||
// console.log(to);
|
||||
if (to.meta.keepAlive) {
|
||||
includeList.push(to.name);
|
||||
}
|
||||
let arr = ["/login", "/device_list", "/add_device", "/add_label"];
|
||||
// 需要全屏的路由
|
||||
let arr = ["/login", "/device_list", "/add_device", "/add_label", '/webview'];
|
||||
if (arr.includes(to.path)) {
|
||||
hideLeftMenu.value = true;
|
||||
} else {
|
||||
hideLeftMenu.value = false;
|
||||
}
|
||||
if (to.fullPath == '/login') {
|
||||
if (ws.value != null) {
|
||||
console.log('关闭ws');
|
||||
ws.value.close()
|
||||
ws.value = null
|
||||
wsIsClose.value = true
|
||||
}
|
||||
} else {
|
||||
// 打开ws
|
||||
openWs()
|
||||
}
|
||||
});
|
||||
|
||||
// 登录成功后开始连接ws
|
||||
function openWs() {
|
||||
if (store.userInfo && store.userInfo.shopId && ws.value == null) {
|
||||
initWebSocket()
|
||||
// 更新print
|
||||
printStore.init()
|
||||
}
|
||||
}
|
||||
|
||||
let transitionName = ref();
|
||||
let router = useRouter();
|
||||
router.beforeEach((to, from) => {
|
||||
@@ -56,6 +106,319 @@ router.beforeEach((to, from) => {
|
||||
transitionName.value = "";
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
let ws = ref(null)
|
||||
let wsIsClose = ref(false)
|
||||
// 初始化websocket
|
||||
function initWebSocket(wsUrl = import.meta.env.VITE_API_WSS) {
|
||||
createUUID()
|
||||
|
||||
wsIsClose.value = false
|
||||
ws.value = new ReconnectingWebSocket(wsUrl, null, {
|
||||
reconnectInterval: 10000
|
||||
})
|
||||
// console.log("websocket:", ws.value);
|
||||
|
||||
ws.value.addEventListener('open', function (event) {
|
||||
console.log('wss连接成功');
|
||||
socketStore.changeOnline(true)
|
||||
|
||||
// 清除心跳
|
||||
clearInterval(heartbeatTimer.value)
|
||||
heartbeatTimer.value = null
|
||||
startheartbeat()
|
||||
|
||||
// 清除重连
|
||||
clearInterval(reConnectTimer.value)
|
||||
reConnectTimer.value = null
|
||||
reConnectCount.value = 0
|
||||
|
||||
ws.value.send(JSON.stringify({
|
||||
type: "connect",
|
||||
shopId: store.userInfo.shopId,
|
||||
clientId: uuid.value
|
||||
}))
|
||||
})
|
||||
|
||||
// ws.value.onopen = function () {
|
||||
// console.log('wss连接成功');
|
||||
// socketStore.changeOnline(true)
|
||||
|
||||
// // 清除心跳
|
||||
// clearInterval(heartbeatTimer.value)
|
||||
// heartbeatTimer.value = null
|
||||
// startheartbeat()
|
||||
|
||||
// // 清除重连
|
||||
// clearInterval(reConnectTimer.value)
|
||||
// reConnectTimer.value = null
|
||||
// reConnectCount.value = 0
|
||||
|
||||
// ws.value.send(JSON.stringify({
|
||||
// type: "connect",
|
||||
// shopId: store.userInfo.shopId,
|
||||
// clientId: uuid.value
|
||||
// }))
|
||||
// };
|
||||
|
||||
ws.value.addEventListener('message', function (e) {
|
||||
let data = JSON.parse(e.data)
|
||||
if (data.type == 'order') {
|
||||
console.log('接收消息', data);
|
||||
ws.value.send(JSON.stringify({
|
||||
type: "send",
|
||||
orderNo: data.orderInfo.orderNo
|
||||
}))
|
||||
// 接收订单消息,打印小票
|
||||
// printBill(data)
|
||||
|
||||
// 检测是否需要打印标签小票
|
||||
// checkLabelPrint(data)
|
||||
printStore.labelPrint(data)
|
||||
}
|
||||
})
|
||||
|
||||
// 连接已关闭或无法打开
|
||||
// ws.value.addEventListener('WebSocket.CLOSED', function () {
|
||||
|
||||
// })
|
||||
|
||||
// 接收消息
|
||||
// ws.value.onmessage = function (e) {
|
||||
// // websocketonmessage(e);
|
||||
// let data = JSON.parse(e.data)
|
||||
// if (data.type == 'order') {
|
||||
// console.log('接收消息', data);
|
||||
// ws.value.send(JSON.stringify({
|
||||
// type: "send",
|
||||
// orderNo: data.orderInfo.orderNo
|
||||
// }))
|
||||
// // 接收订单消息,打印小票
|
||||
// // printBill(data)
|
||||
|
||||
// // 检测是否需要打印标签小票
|
||||
// // checkLabelPrint(data)
|
||||
// printStore.labelPrint(data)
|
||||
// }
|
||||
// };
|
||||
|
||||
ws.value.addEventListener('error', function () {
|
||||
console.log("WebSocket连接发生错误");
|
||||
socketStore.changeOnline(false)
|
||||
|
||||
// 清除心跳
|
||||
clearInterval(heartbeatTimer.value)
|
||||
heartbeatTimer.value = null
|
||||
|
||||
// 手动关闭后不在执行自动连接任务
|
||||
if (!wsIsClose.value) reConnect(wsUrl);
|
||||
})
|
||||
|
||||
// 连接发生错误
|
||||
// ws.value.onerror = function () {
|
||||
// console.log("WebSocket连接发生错误");
|
||||
// socketStore.changeOnline(false)
|
||||
|
||||
// // 清除心跳
|
||||
// clearInterval(heartbeatTimer.value)
|
||||
// heartbeatTimer.value = null
|
||||
|
||||
// // 手动关闭后不在执行自动连接任务
|
||||
// if (!wsIsClose.value) reConnect(wsUrl);
|
||||
// };
|
||||
|
||||
ws.value.addEventListener('error', function (e) {
|
||||
console.log('ws关闭了', e);
|
||||
socketStore.changeOnline(false)
|
||||
|
||||
// 清除心跳
|
||||
clearInterval(heartbeatTimer.value)
|
||||
heartbeatTimer.value = null
|
||||
|
||||
// 手动关闭后不在执行自动连接任务
|
||||
if (!wsIsClose.value) reConnect(wsUrl);
|
||||
})
|
||||
|
||||
// 关闭
|
||||
// ws.value.onclose = function (e) {
|
||||
// console.log('ws关闭了', e);
|
||||
// socketStore.changeOnline(false)
|
||||
|
||||
// // 清除心跳
|
||||
// clearInterval(heartbeatTimer.value)
|
||||
// heartbeatTimer.value = null
|
||||
|
||||
// // 手动关闭后不在执行自动连接任务
|
||||
// if (!wsIsClose.value) reConnect(wsUrl);
|
||||
// };
|
||||
}
|
||||
|
||||
// 启动心跳连接
|
||||
let heartbeatTimer = ref(null)
|
||||
function startheartbeat() {
|
||||
heartbeatTimer.value = setInterval(() => {
|
||||
console.log('发送心跳');
|
||||
ws.value.send(JSON.stringify({ type: 'heartbeat' }))
|
||||
}, 10000)
|
||||
}
|
||||
|
||||
// 重连最大次数5次
|
||||
let reConnectCount = ref(0)
|
||||
let reConnectTimer = ref(null)
|
||||
function reConnect(wsUrl) {
|
||||
if (reConnectTimer.value != null) return
|
||||
ws.value.reconnect();
|
||||
reConnectTimer.value = setInterval(() => {
|
||||
// 自动连接超过5次不在连接,需手动出发
|
||||
// console.log('reConnectCount.value===', reConnectCount.value);
|
||||
// if (reConnectCount.value >= 100) {
|
||||
// console.log('重连超过5次,不在连接');
|
||||
// clearInterval(reConnectTimer.value)
|
||||
// reConnectTimer.value = null
|
||||
// reConnectCount.value = 0
|
||||
// wsIsClose.value = true
|
||||
// ws.value.close()
|
||||
// } else {
|
||||
// }
|
||||
// reConnectCount.value++
|
||||
// initWebSocket(wsUrl)
|
||||
ws.value.reconnect();
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 监听网络
|
||||
function updateInfo() {
|
||||
// 获取网络状态
|
||||
let isOnLine = navigator.onLine
|
||||
// 获取网络信息
|
||||
let info = navigator.connection
|
||||
|
||||
console.log('isOnLine===', isOnLine);
|
||||
console.log('info===', info);
|
||||
if (isOnLine) {
|
||||
console.log('有网了,重连ws连接');
|
||||
reConnect()
|
||||
} else {
|
||||
console.log('没网了,断开ws连接');
|
||||
ws.value.close()
|
||||
|
||||
// 清除重连
|
||||
clearInterval(reConnectTimer.value)
|
||||
reConnectTimer.value = null
|
||||
|
||||
clearInterval(heartbeatTimer.value)
|
||||
heartbeatTimer.value = null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const nextCodeRef = ref('')
|
||||
const lastTimeRef = ref('')
|
||||
const codeRef = ref('')
|
||||
// 通过扫码枪获取条形码
|
||||
async function getBarCode(e) {
|
||||
let nextCode = ''
|
||||
let nextTime = ''
|
||||
const lastTime = lastTimeRef.value
|
||||
let code = codeRef.value
|
||||
if (window.event) {
|
||||
// IE
|
||||
nextCode = e.keyCode
|
||||
} else if (e.which) {
|
||||
// Netscape/Firefox/Opera
|
||||
nextCode = e.which
|
||||
}
|
||||
nextTime = new Date().getTime()
|
||||
// 字母上方 数字键0-9 对应键码值 48-57; 数字键盘 数字键0-9 对应键码值 96-105
|
||||
if (
|
||||
(nextCode >= 48 && nextCode <= 57) ||
|
||||
(nextCode >= 96 && nextCode <= 105)
|
||||
) {
|
||||
const codes = {
|
||||
'48': 48,
|
||||
'49': 49,
|
||||
'50': 50,
|
||||
'51': 51,
|
||||
'52': 52,
|
||||
'53': 53,
|
||||
'54': 54,
|
||||
'55': 55,
|
||||
'56': 56,
|
||||
'57': 57,
|
||||
'96': 48,
|
||||
'97': 49,
|
||||
'98': 50,
|
||||
'99': 51,
|
||||
'100': 52,
|
||||
'101': 53,
|
||||
'102': 54,
|
||||
'103': 55,
|
||||
'104': 56,
|
||||
'105': 57
|
||||
}
|
||||
nextCode = codes[nextCode]
|
||||
nextTime = new Date().getTime()
|
||||
}
|
||||
// 第二次输入延迟两秒,删除之前的数据重新计算
|
||||
if (nextTime && lastTime && nextTime - lastTime > 2000) {
|
||||
code = String.fromCharCode(nextCode)
|
||||
} else {
|
||||
code += String.fromCharCode(nextCode)
|
||||
}
|
||||
|
||||
|
||||
// 保存数据
|
||||
nextCodeRef.value = nextCode
|
||||
lastTimeRef.value = nextTime
|
||||
codeRef.value = code
|
||||
// 键入Enter
|
||||
if (e.which === 13) {
|
||||
// 判断 code 长度(这里就获取到条码值了,以下业务自由发挥)
|
||||
code = code.trim()
|
||||
if (code.length == 13) {
|
||||
console.log('A类条码:' + code);
|
||||
} else if (code.length == 23) {
|
||||
console.log('B类条码:' + code);
|
||||
} else if (code.length == 0) {
|
||||
console.log('请输入条码');
|
||||
} else {
|
||||
console.log('条码不合法:' + code);
|
||||
try {
|
||||
if (!global.isCallNumber || !code.length) return
|
||||
await scanSendMessage({
|
||||
outNumber: code,
|
||||
shopId: store.userInfo.shopId
|
||||
})
|
||||
ElMessage.success('叫号成功')
|
||||
leftMenuRef.value.updateCallNumber()
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
// console.log('code', code);
|
||||
// 键入回车务必清空code值
|
||||
codeRef.value = ''
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
document.addEventListener('keydown', (e) => {
|
||||
getBarCode(e)
|
||||
})
|
||||
// 监听网络在线状态
|
||||
// window.addEventListener("onLine", updateInfo)
|
||||
// // 监听网络离线
|
||||
// window.addEventListener("offLine", updateInfo)
|
||||
// // 监听网络信息变化
|
||||
// navigator.connection.addEventListener('change', updateInfo)
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@@ -87,28 +450,20 @@ router.beforeEach((to, from) => {
|
||||
--b-darker: calc(var(--b) * 0.8);
|
||||
|
||||
--primary-color: rgb(var(--r), var(--g), var(--b));
|
||||
--primary-color-hover: rgb(
|
||||
var(--r-lighter3),
|
||||
var(--g-lighter3),
|
||||
var(--b-lighter3)
|
||||
);
|
||||
--primary-color-hover: rgb(var(--r-lighter3),
|
||||
var(--g-lighter3),
|
||||
var(--b-lighter3));
|
||||
--el-color-primary: var(--primary-color) !important;
|
||||
--el-button-hover-bg-color: var(--primary-color) !important;
|
||||
--el-color-primary-light-3: rgb(
|
||||
var(--r-lighter),
|
||||
var(--g-lighter),
|
||||
var(--b-lighter)
|
||||
) !important;
|
||||
--el-color-primary-dark-2: rgb(
|
||||
var(--r-darker),
|
||||
var(--g-darker),
|
||||
var(--b-darker)
|
||||
) !important;
|
||||
--el-color-primary-light-5: rgb(
|
||||
var(--r-lighter2),
|
||||
var(--g-lighter2),
|
||||
var(--b-lighter2)
|
||||
) !important;
|
||||
--el-color-primary-light-3: rgb(var(--r-lighter),
|
||||
var(--g-lighter),
|
||||
var(--b-lighter)) !important;
|
||||
--el-color-primary-dark-2: rgb(var(--r-darker),
|
||||
var(--g-darker),
|
||||
var(--b-darker)) !important;
|
||||
--el-color-primary-light-5: rgb(var(--r-lighter2),
|
||||
var(--g-lighter2),
|
||||
var(--b-lighter2)) !important;
|
||||
|
||||
--el-font-size-base: 16px !important;
|
||||
--el-message-close-size: var(--el-font-size-base) !important;
|
||||
@@ -163,8 +518,7 @@ html {
|
||||
background-color: #555;
|
||||
margin-right: 0 !important;
|
||||
padding-bottom: 20px !important;
|
||||
border-radius: var(--el-dialog-border-radius) var(--el-dialog-border-radius) 0
|
||||
0;
|
||||
border-radius: var(--el-dialog-border-radius) var(--el-dialog-border-radius) 0 0;
|
||||
}
|
||||
|
||||
.el-dialog__title {
|
||||
@@ -185,8 +539,7 @@ html {
|
||||
}
|
||||
|
||||
.el-dialog__body {
|
||||
padding: calc(var(--el-dialog-padding-primary) + 10px)
|
||||
var(--el-dialog-padding-primary);
|
||||
padding: calc(var(--el-dialog-padding-primary) + 10px) var(--el-dialog-padding-primary);
|
||||
}
|
||||
|
||||
.el-dialog__header {
|
||||
@@ -274,7 +627,7 @@ html {
|
||||
display: flex;
|
||||
width: 200%;
|
||||
|
||||
& > div {
|
||||
&>div {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@ import request from "@/utils/request.js";
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function tbPrintMachinePost(data, method = 'post') {
|
||||
return request({
|
||||
method: method,
|
||||
url: "tbPrintMachine",
|
||||
data
|
||||
});
|
||||
export function tbPrintMachinePost(data, method = "post") {
|
||||
return request({
|
||||
method: method,
|
||||
url: "tbPrintMachine",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -19,11 +19,11 @@ export function tbPrintMachinePost(data, method = 'post') {
|
||||
* @returns
|
||||
*/
|
||||
export function tbPrintMachineGet(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/tbPrintMachine",
|
||||
params
|
||||
});
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/tbPrintMachine",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -32,10 +32,10 @@ export function tbPrintMachineGet(params) {
|
||||
* @returns
|
||||
*/
|
||||
export function tbPrintMachineDetail(id) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: `/tbPrintMachine/${id}`
|
||||
});
|
||||
return request({
|
||||
method: "get",
|
||||
url: `/tbPrintMachine/${id}`,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,11 +44,11 @@ export function tbPrintMachineDetail(id) {
|
||||
* @returns
|
||||
*/
|
||||
export function tbPrintMachineDelete(params) {
|
||||
return request({
|
||||
method: 'DELETE',
|
||||
url: "tbPrintMachine",
|
||||
params
|
||||
});
|
||||
return request({
|
||||
method: "DELETE",
|
||||
url: "tbPrintMachine",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,11 +57,11 @@ export function tbPrintMachineDelete(params) {
|
||||
* @returns
|
||||
*/
|
||||
export function bySubType(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/tbPrintMachine/bySubType",
|
||||
params
|
||||
});
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/tbPrintMachine/bySubType",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,9 +69,9 @@ export function bySubType(params) {
|
||||
* @returns
|
||||
*/
|
||||
export function tbShopCategoryGet(params) {
|
||||
return request({
|
||||
url: `/tbShopCategory`,
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
return request({
|
||||
url: `/product/queryAllCategory`,
|
||||
method: "get",
|
||||
params,
|
||||
});
|
||||
}
|
||||
121
src/api/group.js
Normal file
121
src/api/group.js
Normal file
@@ -0,0 +1,121 @@
|
||||
import request from "@/utils/request.js";
|
||||
import request_php from "@/utils/request_php.js";
|
||||
|
||||
/**
|
||||
* 团购卷订单列表(分页)
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function groupOrderlist(data) {
|
||||
return request({
|
||||
method: "post",
|
||||
url: "/groupOrder/list",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 团购卷核销前回显
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export function groupOrderorderInfo(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/groupOrder/orderInfo",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 团购卷核销(仅核销待使用订单)
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export function groupOrdergroupScan(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/groupOrder/groupScan",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 退单
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function returnGpOrder(data) {
|
||||
return request({
|
||||
method: "post",
|
||||
url: "/pay/returnGpOrder",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 注意 抖音核销使用的请求为PHP服务 request_php
|
||||
|
||||
/**
|
||||
* 会员签入
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function douyincheckIn(data) {
|
||||
return request_php({
|
||||
method: "post",
|
||||
url: "douyin/checkIn",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 团购核销准备
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function douyinfulfilmentcertificateprepare(data) {
|
||||
return request_php({
|
||||
method: "post",
|
||||
url: "douyin/fulfilmentcertificateprepare",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 团购核销
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function douyincertificateprepare(data) {
|
||||
return request_php({
|
||||
method: "post",
|
||||
url: "douyin/certificateprepare",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 团购核销记录
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function douyinorderlist(data) {
|
||||
return request_php({
|
||||
method: "post",
|
||||
url: "douyin/orderlist",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 团购核销撤销
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function douyinfulfilmentcertificatecancel(data) {
|
||||
return request_php({
|
||||
method: "post",
|
||||
url: "douyin/fulfilmentcertificatecancel",
|
||||
data,
|
||||
});
|
||||
}
|
||||
@@ -6,11 +6,11 @@ import request from "@/utils/request.js";
|
||||
* @returns
|
||||
*/
|
||||
export function orderfindOrder(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "order/findOrder",
|
||||
params
|
||||
});
|
||||
return request({
|
||||
method: "get",
|
||||
url: "order/findOrder",
|
||||
params,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 订单详情
|
||||
@@ -18,11 +18,11 @@ export function orderfindOrder(params) {
|
||||
* @returns
|
||||
*/
|
||||
export function orderorderDetail(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "order/orderDetail",
|
||||
params
|
||||
});
|
||||
return request({
|
||||
method: "get",
|
||||
url: "order/orderDetail",
|
||||
params,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 退单
|
||||
@@ -30,11 +30,11 @@ export function orderorderDetail(params) {
|
||||
* @returns
|
||||
*/
|
||||
export function payreturnOrder(data) {
|
||||
return request({
|
||||
method: "post",
|
||||
url: "pay/returnOrder",
|
||||
data
|
||||
});
|
||||
return request({
|
||||
method: "post",
|
||||
url: "pay/returnOrder",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,9 +43,61 @@ export function payreturnOrder(data) {
|
||||
* @returns
|
||||
*/
|
||||
export function cloudPrinterprint(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "cloudPrinter/print",
|
||||
params
|
||||
});
|
||||
return request({
|
||||
method: "get",
|
||||
url: "cloudPrinter/print",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询快捷收银订单
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export function queryQuickPay(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "pay/queryQuickPay",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 叫号
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export function sendMessage(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/order/sendMessage",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫码叫号
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export function scanSendMessage(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/order/scanSendMessage",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取叫号记录
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export function getsendMessage(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/order/getsendMessage",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
108
src/api/pay.js
108
src/api/pay.js
@@ -1,4 +1,4 @@
|
||||
import request from "@/utils/request.js"
|
||||
import request from "@/utils/request.js";
|
||||
|
||||
/**
|
||||
* 查询分类信息
|
||||
@@ -6,11 +6,11 @@ import request from "@/utils/request.js"
|
||||
* @returns
|
||||
*/
|
||||
export function queryPayType(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "pay/queryPayType",
|
||||
params
|
||||
});
|
||||
return request({
|
||||
method: "get",
|
||||
url: "pay/queryPayType",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -19,11 +19,11 @@ export function queryPayType(params) {
|
||||
* @returns
|
||||
*/
|
||||
export function payOrder(api, params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: api,
|
||||
params
|
||||
});
|
||||
return request({
|
||||
method: "get",
|
||||
url: api,
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -32,11 +32,11 @@ export function payOrder(api, params) {
|
||||
* @returns
|
||||
*/
|
||||
export function scanpay(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: 'pay/scanpay',
|
||||
params
|
||||
});
|
||||
return request({
|
||||
method: "get",
|
||||
url: "pay/scanpay",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -45,11 +45,11 @@ export function scanpay(params) {
|
||||
* @returns
|
||||
*/
|
||||
export function accountPay(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: 'pay/accountPay',
|
||||
params
|
||||
});
|
||||
return request({
|
||||
method: "get",
|
||||
url: "pay/accountPay",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,11 +58,11 @@ export function accountPay(params) {
|
||||
* @returns
|
||||
*/
|
||||
export function cashPay(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: 'pay/cashPay',
|
||||
params
|
||||
});
|
||||
return request({
|
||||
method: "get",
|
||||
url: "pay/cashPay",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,11 +71,11 @@ export function cashPay(params) {
|
||||
* @returns
|
||||
*/
|
||||
export function queryOrder(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "pay/queryOrder",
|
||||
params
|
||||
});
|
||||
return request({
|
||||
method: "get",
|
||||
url: "pay/queryOrder",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,11 +84,11 @@ export function queryOrder(params) {
|
||||
* @returns
|
||||
*/
|
||||
export function print(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "cloudPrinter/print",
|
||||
params
|
||||
});
|
||||
return request({
|
||||
method: "get",
|
||||
url: "cloudPrinter/print",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,9 +97,35 @@ export function print(params) {
|
||||
* @returns
|
||||
*/
|
||||
export function quickPay(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "pay/quickPay",
|
||||
params
|
||||
});
|
||||
return request({
|
||||
method: "get",
|
||||
url: "pay/quickPay",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询快捷收银订单
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export function queryQuickPayStatus(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "pay/queryQuickPayStatus",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会员支付状态查询
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export function queryScanPay(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "member/queryScanPay",
|
||||
params,
|
||||
});
|
||||
}
|
||||
@@ -26,6 +26,19 @@ export function productqueryCommodityInfo(params) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询商品信息
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export function queryNewCommodityInfo(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "product/queryNewCommodityInfo",
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过选中的商品规格查询价格
|
||||
* @param {*} params
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import request from "@/utils/request.js"
|
||||
import request from "@/utils/request.js";
|
||||
|
||||
/**
|
||||
* 当前用户交班详情
|
||||
@@ -6,11 +6,11 @@ import request from "@/utils/request.js"
|
||||
* @returns
|
||||
*/
|
||||
export function shopInfoqueryDuty(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "shopInfo/queryDuty",
|
||||
params
|
||||
});
|
||||
return request({
|
||||
method: "get",
|
||||
url: "shopInfo/queryDuty",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -19,22 +19,35 @@ export function shopInfoqueryDuty(params) {
|
||||
* @returns
|
||||
*/
|
||||
export function shopinfoqueryDutyFlow(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "shopInfo/queryDutyFlow",
|
||||
params
|
||||
});
|
||||
return request({
|
||||
method: "get",
|
||||
url: "shopInfo/queryDutyFlow",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 登出
|
||||
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export function loginlogout(params) {
|
||||
return request({
|
||||
method: "post",
|
||||
url: "login/logout",
|
||||
params
|
||||
});
|
||||
return request({
|
||||
method: "post",
|
||||
url: "login/logout",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取交班数据
|
||||
* @param {*} params
|
||||
* @returns
|
||||
*/
|
||||
export function handoverData(params) {
|
||||
return request({
|
||||
method: "get",
|
||||
url: "/data/handoverData",
|
||||
params,
|
||||
});
|
||||
}
|
||||
BIN
src/assets/prinnt_label_logo.png
Normal file
BIN
src/assets/prinnt_label_logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.2 KiB |
289
src/components/callNumber.vue
Normal file
289
src/components/callNumber.vue
Normal file
@@ -0,0 +1,289 @@
|
||||
<!-- 取餐号组件 -->
|
||||
<template>
|
||||
<el-dialog :title="props.title" width="600" v-model="dialogVisible" @open="opne">
|
||||
<!-- <el-input v-model="number" :placeholder="props.placeholder" readonly></el-input> -->
|
||||
<!-- <el-input ref="inputRef" v-model="number" :placeholder="props.placeholder" :readonly="loading" clearable
|
||||
@change="inputChange"></el-input> -->
|
||||
<div class="tips">注意:请扫描标签二维码</div>
|
||||
<!-- <div class="keybord_wrap">
|
||||
<div v-for="item in 9" :key="item">
|
||||
<el-button plain type="info" style="width: 100%;" @click="inputHandle(item)">{{ item }}</el-button>
|
||||
</div>
|
||||
<div>
|
||||
<el-button plain type="info" disabled style="width: 100%;">.</el-button>
|
||||
</div>
|
||||
<div>
|
||||
<el-button plain type="info" style="width: 100%;" @click="inputHandle(0)">0</el-button>
|
||||
</div>
|
||||
<div>
|
||||
<el-button plain type="info" icon="CloseBold" style="width: 100%;" @click="delHandle"></el-button>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="list" v-loading="tableData.loading">
|
||||
<div class="item" v-for="item in tableData.list" :key="item.id">
|
||||
<div class="top">
|
||||
<div class="left">
|
||||
<div class="title">取餐号:{{ filterCode(item.outCode) }}</div>
|
||||
<div class="shop">商品:{{ item.productName }}</div>
|
||||
</div>
|
||||
<div class="state s1" v-if="item.status == 0">
|
||||
<div class="dot"></div> 叫号成功
|
||||
</div>
|
||||
<div class="state s2" v-if="item.status == 1">
|
||||
<div class="dot"></div> 叫号失败
|
||||
</div>
|
||||
</div>
|
||||
<div class="btm">
|
||||
<div class="time">{{ dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss') }}</div>
|
||||
<div class="info" v-if="item.status == 1">
|
||||
{{ item.remark }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-empty description="暂无记录" :image-size="60" v-if="!tableData.list.length" />
|
||||
</div>
|
||||
<div class="page">
|
||||
<el-pagination v-model:current-page="tableData.page" v-model:page-size="tableData.pageSize" background
|
||||
layout="total, prev, pager, next" :total="tableData.total" @current-change="handleCurrentChange" />
|
||||
</div>
|
||||
<!-- <div class="footer">
|
||||
<el-button type="primary" style="width: 100%;" :loading="loading" @click="confirmHandle">确认</el-button>
|
||||
</div> -->
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import _ from "lodash";
|
||||
import dayjs from 'dayjs'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { useUser } from "@/store/user.js";
|
||||
import { scanSendMessage, getsendMessage } from '@/api/order/index'
|
||||
import { useGlobal } from '@/store/global.js'
|
||||
const global = useGlobal()
|
||||
const store = useUser();
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '叫号取餐记录'
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请扫描取餐号'
|
||||
}
|
||||
})
|
||||
|
||||
const inputRef = ref(null)
|
||||
const loading = ref(false)
|
||||
const dialogVisible = ref(false)
|
||||
const number = ref('')
|
||||
|
||||
const tableData = reactive({
|
||||
loading: false,
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
list: []
|
||||
})
|
||||
|
||||
const emit = defineEmits(['success'])
|
||||
|
||||
// 截取字符串
|
||||
function filterCode(t, c = '#') {
|
||||
let n = t.split(c)
|
||||
return n[1]
|
||||
}
|
||||
|
||||
function show() {
|
||||
dialogVisible.value = true
|
||||
getsendMessageAjax()
|
||||
// setTimeout(() => {
|
||||
// inputRef.value.focus();
|
||||
// }, 500);
|
||||
}
|
||||
|
||||
function opne() {
|
||||
number.value = ''
|
||||
global.updateData(true)
|
||||
}
|
||||
|
||||
// 输入
|
||||
function inputHandle(n) {
|
||||
number.value += n
|
||||
}
|
||||
|
||||
// 删除
|
||||
function delHandle() {
|
||||
if (!number.value) return
|
||||
number.value = number.value.substring(0, number.value.length - 1)
|
||||
}
|
||||
|
||||
const inputChange = _.debounce(function (e) {
|
||||
// console.log(e);
|
||||
confirmHandle();
|
||||
}, 100);
|
||||
|
||||
// 页码改变
|
||||
function handleCurrentChange() {
|
||||
getsendMessageAjax()
|
||||
}
|
||||
|
||||
// 获取叫号记录
|
||||
async function getsendMessageAjax() {
|
||||
try {
|
||||
if (!store.userInfo.shopId) return
|
||||
tableData.loading = true
|
||||
const res = await getsendMessage({
|
||||
page: tableData.page,
|
||||
pageSize: tableData.pageSize,
|
||||
shopId: store.userInfo.shopId,
|
||||
// shopId: 4,
|
||||
})
|
||||
tableData.loading = false
|
||||
tableData.list = res.list
|
||||
tableData.total = res.total
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
tableData.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
// 确认
|
||||
const confirmHandle = _.throttle(async function () {
|
||||
try {
|
||||
if (!number.value) return
|
||||
loading.value = true
|
||||
|
||||
const res = await scanSendMessage({
|
||||
outNumber: number.value,
|
||||
shopId: store.userInfo.shopId,
|
||||
// shopId: 4
|
||||
})
|
||||
ElMessage.success('叫号成功')
|
||||
|
||||
loading.value = false
|
||||
number.value = ''
|
||||
getsendMessageAjax()
|
||||
setTimeout(() => {
|
||||
inputRef.value.focus();
|
||||
}, 500);
|
||||
} catch (error) {
|
||||
getsendMessageAjax()
|
||||
loading.value = false
|
||||
number.value = ''
|
||||
console.log(error);
|
||||
setTimeout(() => {
|
||||
inputRef.value.focus();
|
||||
}, 500);
|
||||
}
|
||||
}, 800, { leading: true, trailing: false })
|
||||
|
||||
defineExpose({
|
||||
show,
|
||||
getsendMessageAjax
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-input__inner) {
|
||||
height: 60px;
|
||||
font-size: 36px;
|
||||
}
|
||||
|
||||
.page {
|
||||
display: flex;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.tips {
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.keybord_wrap {
|
||||
padding: var(--el-font-size-base) 0;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-template-rows: 1fr 1fr 1fr 1fr;
|
||||
gap: var(--el-font-size-base);
|
||||
|
||||
:deep(.el-button--large) {
|
||||
height: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
.list {
|
||||
height: 200px;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
overflow-y: auto;
|
||||
padding: 0 14px;
|
||||
|
||||
.item {
|
||||
padding: 16px 0;
|
||||
|
||||
&:not(:last-child) {
|
||||
border-bottom: 1px solid #ececec;
|
||||
}
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.left {
|
||||
color: #000;
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.shop {
|
||||
color: #555;
|
||||
}
|
||||
}
|
||||
|
||||
.state {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.dot {
|
||||
$size: 6px;
|
||||
width: $size;
|
||||
height: $size;
|
||||
border-radius: 50%;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
&.s1 {
|
||||
color: var(--primary-color);
|
||||
|
||||
.dot {
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.s2 {
|
||||
color: var(--el-color-error);
|
||||
|
||||
.dot {
|
||||
background-color: var(--el-color-error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btm {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding-top: 4px;
|
||||
|
||||
.time,
|
||||
.info {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -4,18 +4,9 @@
|
||||
<div class="row" v-for="(item, index) in categorys" :key="item.id">
|
||||
<div class="list_title">{{ item.name }}</div>
|
||||
<div class="item_wrap">
|
||||
<el-button
|
||||
:type="item.active ? 'primary' : ''"
|
||||
@click="selectHandle(item)"
|
||||
>全部</el-button
|
||||
>
|
||||
<el-button
|
||||
:type="val.active ? 'primary' : ''"
|
||||
v-for="val in item.childrenList"
|
||||
:key="val.id"
|
||||
@click="selectHandle(val, index)"
|
||||
>{{ val.name }}</el-button
|
||||
>
|
||||
<el-button :type="item.active ? 'primary' : ''" @click="selectHandle(item)">全部</el-button>
|
||||
<el-button :type="val.active ? 'primary' : ''" v-for="val in item.childrenList" :key="val.id"
|
||||
@click="selectHandle(val, index)">{{ val.name }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -82,15 +73,16 @@ async function tbShopCategoryGetAjax() {
|
||||
shopId: store.userInfo.shopId,
|
||||
sort: "sort,desc",
|
||||
page: 0,
|
||||
size: 500,
|
||||
pageSize: 200,
|
||||
});
|
||||
res.map((item) => {
|
||||
// console.log(res);
|
||||
res.list.map((item) => {
|
||||
item.active = false;
|
||||
item.childrenList.map((item) => {
|
||||
item.active = false;
|
||||
});
|
||||
});
|
||||
categorys.value = res;
|
||||
categorys.value = res.list;
|
||||
|
||||
setTimeout(() => {
|
||||
loading.value = false;
|
||||
|
||||
@@ -7,10 +7,14 @@
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="t1">
|
||||
<div class="t1" v-if="props.type == 0">
|
||||
<span class="title">应收:¥</span>
|
||||
<span class="num">{{ money }}</span>
|
||||
</div>
|
||||
<div class="t1" v-else>
|
||||
<span class="title">会员:</span>
|
||||
<span class="num">{{ props.userInfo.id && props.userInfo.telephone }}</span>
|
||||
</div>
|
||||
<div class="t2">
|
||||
<span>已付:¥0.00</span>
|
||||
<span>优惠:¥0.00</span>
|
||||
@@ -19,13 +23,8 @@
|
||||
</div>
|
||||
<div class="number_wrap">
|
||||
<div class="menus">
|
||||
<div
|
||||
class="item"
|
||||
:class="{ active: payActive == index }"
|
||||
v-for="(item, index) in payList"
|
||||
:key="item.id"
|
||||
@click="payTypeChange(index, item)"
|
||||
>
|
||||
<div class="item" :class="{ active: payActive == index }" v-for="(item, index) in payList" :key="item.id"
|
||||
@click="payTypeChange(index, item)">
|
||||
<div class="icon">
|
||||
<el-image :src="item.icon" class="img"></el-image>
|
||||
</div>
|
||||
@@ -40,12 +39,7 @@
|
||||
</div>
|
||||
<div class="keybord_wrap">
|
||||
<div class="left">
|
||||
<div
|
||||
class="item"
|
||||
v-for="item in 9"
|
||||
:key="item"
|
||||
@click="amountInput(`${item}`)"
|
||||
>
|
||||
<div class="item" v-for="item in 9" :key="item" @click="amountInput(`${item}`)">
|
||||
{{ item }}
|
||||
</div>
|
||||
<div class="item" @click="amountInput('.')">.</div>
|
||||
@@ -63,23 +57,31 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<scanModal
|
||||
ref="scanModalRef"
|
||||
fast
|
||||
:amount="money"
|
||||
@success="scanCodeSuccess"
|
||||
/>
|
||||
<scanModal ref="scanModalRef" fast :amount="money" :selecttype="props.type" :orderId="props.userInfo.id"
|
||||
@success="scanCodeSuccess" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onMounted, ref } from "vue";
|
||||
import { queryPayType, quickPay } from "@/api/pay";
|
||||
import { queryMembermember, createMembermember, membermemberScanPay, accountPaymember } from '@/api/member/index.js'
|
||||
import { useUser } from "@/store/user.js";
|
||||
import { clearNoNum } from "@/utils";
|
||||
|
||||
import scanModal from "@/components/payCard/scanModal.vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
|
||||
const props = defineProps({
|
||||
type: {
|
||||
type: [String, Number],
|
||||
default: 0 // 1快捷收银 2会员支付
|
||||
},
|
||||
userInfo: {
|
||||
type: Object,
|
||||
default: {}
|
||||
}
|
||||
})
|
||||
|
||||
const store = useUser();
|
||||
|
||||
const emit = defineEmits(["paySuccess", "close"]);
|
||||
@@ -115,8 +117,13 @@ function payTypeChange(index, item) {
|
||||
|
||||
// 结算支付
|
||||
async function confirmOrder() {
|
||||
if (payLoading.value) return
|
||||
try {
|
||||
if (payList.value[payActive.value].payType == "scanCode") {
|
||||
if (money.value <= 0) {
|
||||
ElMessage.error("请输入大于0的金额");
|
||||
return;
|
||||
}
|
||||
scanModalRef.value.show();
|
||||
} else {
|
||||
if (money.value <= 0) {
|
||||
@@ -126,11 +133,19 @@ async function confirmOrder() {
|
||||
payLoading.value = true;
|
||||
switch (payList.value[payActive.value].payType) {
|
||||
case "cash": //现金
|
||||
await quickPay({
|
||||
amount: money.value,
|
||||
authCode: "",
|
||||
payType: payList.value[payActive.value].payType,
|
||||
});
|
||||
if (props.type == 0) {
|
||||
await quickPay({
|
||||
amount: money.value,
|
||||
authCode: "",
|
||||
payType: payList.value[payActive.value].payType,
|
||||
});
|
||||
} else {
|
||||
await accountPaymember({
|
||||
shopId: store.userInfo.shopId,
|
||||
memberId: props.userInfo.id,
|
||||
amount: money.value
|
||||
})
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -203,6 +218,7 @@ onMounted(() => {
|
||||
border-bottom: 1px solid #ececec;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.return {
|
||||
$size: 50px;
|
||||
width: $size;
|
||||
@@ -219,6 +235,7 @@ onMounted(() => {
|
||||
font-size: var(--el-font-size-base);
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
.t1 {
|
||||
display: flex;
|
||||
@@ -320,9 +337,7 @@ onMounted(() => {
|
||||
flex: 1;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-template-rows: var(--item-height) var(--item-height) var(--item-height) var(
|
||||
--item-height
|
||||
);
|
||||
grid-template-rows: var(--item-height) var(--item-height) var(--item-height) var(--item-height);
|
||||
gap: var(--el-font-size-base);
|
||||
|
||||
.item {
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
<template>
|
||||
<div class="left_menu_wrap">
|
||||
<div class="item online">
|
||||
<div class="item" :class="{ online: socketStore.online }" @click="connectWsHandle">
|
||||
<el-icon class="icon">
|
||||
<Monitor />
|
||||
</el-icon>
|
||||
<el-text type="success">在线</el-text>
|
||||
<el-text :type="socketStore.online ? 'success' : ''">
|
||||
<template v-if="socketStore.online">
|
||||
在线
|
||||
</template>
|
||||
<template v-else>
|
||||
离线
|
||||
</template>
|
||||
</el-text>
|
||||
</div>
|
||||
<router-link class="item" :class="{ active: route.path == item.path }" v-for="item in menus" :key="item.path"
|
||||
:to="item.path">
|
||||
@@ -21,16 +28,25 @@
|
||||
</div>
|
||||
</div>
|
||||
<!-- 更多 -->
|
||||
<more ref="moreref"></more>
|
||||
<more ref="moreref" @openCall="openCall"></more>
|
||||
<!-- 叫号 -->
|
||||
<callNumber ref="callNumberRef" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useSocket } from '@/store/socket.js'
|
||||
import more from '@/components/more.vue'
|
||||
import callNumber from './callNumber.vue'
|
||||
|
||||
const emits = defineEmits(['connectWsHandle'])
|
||||
|
||||
const socketStore = useSocket()
|
||||
|
||||
const route = useRoute()
|
||||
const moreref = ref(null)
|
||||
const callNumberRef = ref(null)
|
||||
const menus = ref([
|
||||
{
|
||||
label: '收银',
|
||||
@@ -42,16 +58,21 @@ const menus = ref([
|
||||
path: '/table',
|
||||
icon: 'Reading'
|
||||
},
|
||||
{
|
||||
label: '团购',
|
||||
path: '/group_buy',
|
||||
icon: 'Handbag'
|
||||
},
|
||||
{
|
||||
label: '订单',
|
||||
path: '/order',
|
||||
icon: 'Tickets'
|
||||
},
|
||||
{
|
||||
label: '网络',
|
||||
path: '/internat',
|
||||
icon: 'Paperclip'
|
||||
},
|
||||
// {
|
||||
// label: '网络',
|
||||
// path: '/internat',
|
||||
// icon: 'Paperclip'
|
||||
// },
|
||||
{
|
||||
label: '会员',
|
||||
path: '/member',
|
||||
@@ -63,6 +84,25 @@ const menus = ref([
|
||||
icon: 'SwitchButton'
|
||||
}
|
||||
])
|
||||
|
||||
// 更新叫号记录
|
||||
function updateCallNumber() {
|
||||
callNumberRef.value.getsendMessageAjax()
|
||||
}
|
||||
|
||||
function openCall() {
|
||||
callNumberRef.value.show()
|
||||
}
|
||||
|
||||
// 手动重新连接ws
|
||||
function connectWsHandle() {
|
||||
if (socketStore.online) return
|
||||
emits('connectWsHandle')
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
updateCallNumber
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@@ -184,7 +224,7 @@ const menus = ref([
|
||||
}
|
||||
|
||||
&.more {
|
||||
margin-top: 150px;
|
||||
margin-top: 120px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="drawerbox">
|
||||
<el-drawer size="50%" :with-header="false" direction="rtl" v-model="dialogVisible" style="padding: 0;">
|
||||
<el-drawer size="60%" :with-header="false" direction="rtl" v-model="dialogVisible" style="padding: 0;">
|
||||
<div class="drawerbox_box">
|
||||
<div class="drawerbox_bo_top">
|
||||
<div class="drawerbox_bo_top_left">
|
||||
@@ -9,7 +9,7 @@
|
||||
</div>
|
||||
<div class="drawerbox_bo_top_left_tow" style="margin-top: 10px;">
|
||||
收银员:{{ store.userInfo.userCode }} <span style="color: #666;">登录:{{
|
||||
store.userInfo.loginTime }}</span>
|
||||
store.userInfo.loginTime }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="drawerbox_bo_top_ring">
|
||||
@@ -32,7 +32,7 @@
|
||||
<div class="drawerbox_bo_box_itemb_felx">
|
||||
<div class="drawerbox_bo_box_itembox">
|
||||
<div class="drawerbox_bo_box_icon">
|
||||
<el-icon size="40" style="margin:30px;">
|
||||
<el-icon size="40">
|
||||
<Setting />
|
||||
</el-icon>
|
||||
</div>
|
||||
@@ -40,9 +40,19 @@
|
||||
设置
|
||||
</div>
|
||||
</div>
|
||||
<div class="drawerbox_bo_box_itembox" @click="openCallHandle">
|
||||
<div class="drawerbox_bo_box_icon">
|
||||
<el-icon size="40">
|
||||
<Bell />
|
||||
</el-icon>
|
||||
</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" style="margin:30px;">
|
||||
<el-icon size="40">
|
||||
<TurnOff />
|
||||
</el-icon>
|
||||
</div>
|
||||
@@ -52,7 +62,7 @@
|
||||
</div>
|
||||
<div class="drawerbox_bo_box_itembox" @click="screenref.shows()">
|
||||
<div class="drawerbox_bo_box_icon">
|
||||
<el-icon size="40" style="margin:30px;">
|
||||
<el-icon size="40">
|
||||
<Switch />
|
||||
</el-icon>
|
||||
</div>
|
||||
@@ -60,6 +70,19 @@
|
||||
锁屏
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="drawerbox_bo_box_itembox" @click="to('webview', {
|
||||
url: 'https://cashiernewadmin.sxczgkj.cn/',
|
||||
title: '后台管理'
|
||||
})">
|
||||
<div class="drawerbox_bo_box_icon">
|
||||
<el-icon size="40">
|
||||
<Monitor />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="drawerbox_bo_box_icontext">
|
||||
后台管理
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -86,6 +109,8 @@ import packageData from '../../package.json'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const emit = defineEmits(['openCall'])
|
||||
|
||||
const store = useUser()
|
||||
const screenref = ref(null)
|
||||
|
||||
@@ -95,6 +120,20 @@ function show() {
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
// 打开叫号弹窗
|
||||
function openCallHandle() {
|
||||
dialogVisible.value = false
|
||||
emit('openCall')
|
||||
}
|
||||
|
||||
// 跳转
|
||||
function to(pathName, data) {
|
||||
router.push({
|
||||
name: pathName,
|
||||
query: data
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
show
|
||||
})
|
||||
@@ -165,26 +204,25 @@ defineExpose({
|
||||
|
||||
.drawerbox_bo_box_itemb_felx {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
padding: 0 20px;
|
||||
|
||||
.drawerbox_bo_box_itembox:nth-child(1) {
|
||||
margin-left: 0px;
|
||||
|
||||
}
|
||||
|
||||
.drawerbox_bo_box_itembox {
|
||||
width: 20%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-left: 40px;
|
||||
margin-right: 20px;
|
||||
margin-bottom: 30px;
|
||||
|
||||
.drawerbox_bo_box_icon {
|
||||
border-radius: 6px;
|
||||
background: #2196f3;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.drawerbox_bo_box_icontext {
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<scanModal ref="scanModalRef" :amount="props.amount" :orderId="props.orderId" :selecttype="props.selecttype"
|
||||
@success="scanCodeSuccess" />
|
||||
:payType="payType" @success="scanCodeSuccess" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@@ -73,6 +73,10 @@ const props = defineProps({
|
||||
orderId: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
member: {
|
||||
type: Object,
|
||||
default: {}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -92,6 +96,7 @@ const waitPayMoney = computed(() => {
|
||||
})
|
||||
|
||||
const payActive = ref(0)
|
||||
const payType = ref('')
|
||||
const payList = ref([])
|
||||
const payLoading = ref(false)
|
||||
|
||||
@@ -103,13 +108,18 @@ function scanCodeSuccess() {
|
||||
// 切换支付类型
|
||||
function payTypeChange(index, item) {
|
||||
payActive.value = index
|
||||
payType.value = item.payType
|
||||
if (item.payType == 'scanCode') {
|
||||
scanModalRef.value.show()
|
||||
}
|
||||
if (payList.value[payActive.value].payType == 'deposit' && !props.member.id) {
|
||||
scanModalRef.value.show()
|
||||
}
|
||||
}
|
||||
|
||||
// 结算支付
|
||||
async function confirmOrder() {
|
||||
if (payLoading.value) return
|
||||
try {
|
||||
if (payList.value[payActive.value].payType == 'scanCode') {
|
||||
scanModalRef.value.show()
|
||||
@@ -118,13 +128,21 @@ async function confirmOrder() {
|
||||
payLoading.value = true
|
||||
switch (payList.value[payActive.value].payType) {
|
||||
case 'deposit'://储值卡
|
||||
if (props.selecttype == 1) {
|
||||
// if (props.selecttype == 1) {
|
||||
|
||||
} else {
|
||||
// } else {
|
||||
|
||||
// }
|
||||
if (props.member.id) {
|
||||
await accountPay({
|
||||
orderId: props.orderId,
|
||||
memberId: 1
|
||||
memberId: props.member.id,
|
||||
memberAccount: ''
|
||||
})
|
||||
} else {
|
||||
payLoading.value = false
|
||||
scanModalRef.value.show()
|
||||
return
|
||||
}
|
||||
break;
|
||||
case 'cash'://现金
|
||||
@@ -186,8 +204,9 @@ async function queryPayTypeAjax() {
|
||||
shopId: store.userInfo.shopId
|
||||
})
|
||||
payList.value = res
|
||||
if (res[0].payType == 'scanCode') {
|
||||
if (res[0].payType == 'scanCode' || res[0].payType == 'deposit') {
|
||||
scanModalRef.value.show()
|
||||
payType.value = res[0].payType
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
|
||||
@@ -2,12 +2,7 @@
|
||||
|
||||
<template>
|
||||
<div class="dialog">
|
||||
<el-dialog
|
||||
title="扫码支付"
|
||||
width="600"
|
||||
v-model="dialogVisible"
|
||||
@open="reset"
|
||||
>
|
||||
<el-dialog title="扫码支付" width="600" v-model="dialogVisible" @open="reset" @close="clearAutoCheckOrder">
|
||||
<div class="content">
|
||||
<div class="left">
|
||||
<el-image :src="icon" style="width: 60px; height: 60px"></el-image>
|
||||
@@ -18,15 +13,9 @@
|
||||
<span class="n">{{ props.amount }}</span>
|
||||
</div>
|
||||
<div class="input">
|
||||
<el-input
|
||||
ref="inputRef"
|
||||
v-model="scanCode"
|
||||
style="height: calc(var(--el-component-size-large) + 30px)"
|
||||
placeholder="请扫描付款码"
|
||||
clearable
|
||||
@change="inputChange"
|
||||
></el-input>
|
||||
<div class="tips">注意:扫码支付请保证输入框获得焦点</div>
|
||||
<el-input ref="inputRef" v-model="scanCode" style="height: calc(var(--el-component-size-large) + 30px)"
|
||||
placeholder="请扫描付款码" clearable @change="inputChange"></el-input>
|
||||
<div class="tips">注意:扫码支付请保证输入框获得焦点,输入内容结束后会自动支付,请勿重复操作</div>
|
||||
</div>
|
||||
<!-- <div class="number_warp">
|
||||
<div class="item" v-for="item in 9" :key="item" @click="inputHandle(item)">{{ item }}</div>
|
||||
@@ -39,36 +28,21 @@
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="btn">
|
||||
<el-button
|
||||
type="primary"
|
||||
style="width: 100%"
|
||||
v-loading="loading"
|
||||
@click="submitHandle"
|
||||
>立即支付</el-button
|
||||
>
|
||||
<el-button type="primary" style="width: 100%" v-loading="loading">立即支付</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pay_wait" v-else>
|
||||
<div
|
||||
class="loading"
|
||||
v-loading="loading"
|
||||
element-loading-text="用户支付中..."
|
||||
></div>
|
||||
<div class="loading" v-loading="loading" element-loading-text="用户支付中..."></div>
|
||||
<div class="btn">
|
||||
<el-button
|
||||
type="primary"
|
||||
style="width: 100%"
|
||||
v-loading="checkPayStatusLoading"
|
||||
@click="checkPayStauts"
|
||||
>
|
||||
<el-button type="primary" style="width: 100%" v-loading="checkPayStatusLoading" @click="checkPayStauts">
|
||||
<span v-if="!checkPayStatusLoading">查询用户支付状态</span>
|
||||
<span v-else>查询中...</span>
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="btn">
|
||||
<el-button style="width: 100%" @click="resetScanCode"
|
||||
>重新扫码</el-button
|
||||
>
|
||||
<el-button style="width: 100%" @click="resetScanCode">
|
||||
重新扫码
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -80,9 +54,11 @@
|
||||
import _ from "lodash";
|
||||
import { ref } from "vue";
|
||||
import icon from "@/assets/icon_scan.png";
|
||||
import { scanpay, queryOrder, quickPay } from "@/api/pay";
|
||||
import { scanpay, queryOrder, quickPay, queryQuickPayStatus, accountPay, queryScanPay } from "@/api/pay";
|
||||
import { useUser } from "@/store/user.js";
|
||||
import { useGlobal } from '@/store/global.js'
|
||||
const store = useUser();
|
||||
const global = useGlobal()
|
||||
import {
|
||||
queryMembermember,
|
||||
createMembermember,
|
||||
@@ -98,7 +74,7 @@ const props = defineProps({
|
||||
default: 0,
|
||||
},
|
||||
selecttype: {
|
||||
type: Number,
|
||||
type: [Number, String],
|
||||
default: 0,
|
||||
},
|
||||
orderId: {
|
||||
@@ -109,6 +85,10 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
payType: {
|
||||
type: [Number, String],
|
||||
default: "",
|
||||
}
|
||||
});
|
||||
|
||||
const dialogVisible = ref(false);
|
||||
@@ -119,6 +99,8 @@ const loading = ref(false);
|
||||
const userPayWait = ref(false);
|
||||
const checkPayStatusLoading = ref(false);
|
||||
|
||||
const fastOrder = ref('')
|
||||
|
||||
// 提交扫码支付
|
||||
async function submitHandle() {
|
||||
try {
|
||||
@@ -139,10 +121,19 @@ async function submitHandle() {
|
||||
payType: "scanCode",
|
||||
});
|
||||
} else {
|
||||
await scanpay({
|
||||
orderId: props.orderId,
|
||||
authCode: scanCode.value,
|
||||
});
|
||||
if (props.payType == 'scanCode') {
|
||||
await scanpay({
|
||||
orderId: props.orderId,
|
||||
authCode: scanCode.value,
|
||||
});
|
||||
}
|
||||
if (props.payType == 'deposit') {
|
||||
await accountPay({
|
||||
orderId: props.orderId,
|
||||
memberId: '',
|
||||
memberAccount: scanCode.value
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,30 +143,111 @@ async function submitHandle() {
|
||||
dialogVisible.value = false;
|
||||
emits("success");
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
if (error.code === "100015") {
|
||||
userPayWait.value = true;
|
||||
fastOrder.value = error.data
|
||||
autoCheckOrder()
|
||||
} else {
|
||||
scanCode.value = "";
|
||||
loading.value = false;
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const timer = ref(null)
|
||||
// 自动查询订单状态
|
||||
function autoCheckOrder() {
|
||||
timer.value = setInterval(() => {
|
||||
checkPayStauts(false)
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
// 清除自动查询扫码支付订单
|
||||
function clearAutoCheckOrder() {
|
||||
clearInterval(timer.value)
|
||||
timer.value = null
|
||||
// 开启叫号功能
|
||||
global.updateData(true)
|
||||
}
|
||||
|
||||
// 查询用户支付状态
|
||||
async function checkPayStauts() {
|
||||
async function checkPayStauts(tips = true) {
|
||||
try {
|
||||
const res = await queryOrder({ orderId: props.orderId });
|
||||
if (res.status == "closed") {
|
||||
ElMessage.success("支付成功");
|
||||
emits("success");
|
||||
return;
|
||||
}
|
||||
if (res.status == "paying") {
|
||||
ElMessage.warning("用户支付中...");
|
||||
return;
|
||||
if (props.selecttype == 1) {
|
||||
// 会员扫码充值
|
||||
const res = await queryScanPay({ flowId: fastOrder.value.id });
|
||||
if (res.status == 0) {
|
||||
userPayWait.value = false
|
||||
loading.value = false;
|
||||
scanCode.value = "";
|
||||
ElMessage.success("支付成功");
|
||||
dialogVisible.value = false;
|
||||
clearAutoCheckOrder()
|
||||
emits("success");
|
||||
return;
|
||||
}
|
||||
if (res.status == 7) {
|
||||
if (tips) {
|
||||
ElMessage.warning("用户支付中...");
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
clearAutoCheckOrder()
|
||||
ElMessage.error(res.payRemark || "支付失败!");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
ElMessage.error(res.payRemark || "支付失败!");
|
||||
return;
|
||||
// 其他扫码支付
|
||||
if (props.fast) {
|
||||
// 快捷收银
|
||||
const res = await queryQuickPayStatus({ orderId: fastOrder.value.orderNo });
|
||||
if (res.status == 0) {
|
||||
userPayWait.value = false
|
||||
loading.value = false;
|
||||
scanCode.value = "";
|
||||
ElMessage.success("支付成功");
|
||||
dialogVisible.value = false;
|
||||
clearAutoCheckOrder()
|
||||
emits("success");
|
||||
return;
|
||||
}
|
||||
if (res.status == 1) {
|
||||
if (tips) {
|
||||
ElMessage.warning("用户支付中...");
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
clearAutoCheckOrder()
|
||||
ElMessage.error(res.payRemark || "支付失败!");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// 扫码下单
|
||||
const res = await queryOrder({ orderId: props.orderId });
|
||||
if (res.status == "closed") {
|
||||
userPayWait.value = false
|
||||
loading.value = false;
|
||||
scanCode.value = "";
|
||||
ElMessage.success("支付成功");
|
||||
dialogVisible.value = false;
|
||||
clearAutoCheckOrder()
|
||||
emits("success");
|
||||
return;
|
||||
}
|
||||
if (res.status == "paying") {
|
||||
if (tips) {
|
||||
ElMessage.warning("用户支付中...");
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
clearAutoCheckOrder()
|
||||
ElMessage.error(res.payRemark || "支付失败!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
@@ -184,6 +256,7 @@ async function checkPayStauts() {
|
||||
|
||||
// 重新扫码
|
||||
function resetScanCode() {
|
||||
clearAutoCheckOrder()
|
||||
userPayWait.value = false;
|
||||
loading.value = false;
|
||||
scanCode.value = "";
|
||||
@@ -211,7 +284,7 @@ function delHandle() {
|
||||
const inputChange = _.debounce(function (e) {
|
||||
// console.log(e);
|
||||
submitHandle();
|
||||
}, 500);
|
||||
}, 100);
|
||||
|
||||
function show() {
|
||||
dialogVisible.value = true;
|
||||
@@ -227,6 +300,8 @@ function close() {
|
||||
function reset() {
|
||||
loading.value = false;
|
||||
scanCode.value = "";
|
||||
// 关闭叫号功能
|
||||
global.updateData(false)
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="content">
|
||||
<el-input type="textarea" :rows="6" v-model="remark" placeholder="请输入备注"></el-input>
|
||||
<el-input type="textarea" :rows="6" v-model="remark" placeholder="请输入备注" @focus="
|
||||
global.updateData(false)" @blur="global.updateData(true)"></el-input>
|
||||
</div>
|
||||
<div class="footer_wrap">
|
||||
<div class="btn">
|
||||
@@ -18,6 +19,8 @@
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { useGlobal } from '@/store/global.js'
|
||||
const global = useGlobal()
|
||||
const emit = defineEmits(['success'])
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { createRouter, createWebHashHistory } from "vue-router"
|
||||
import home from "@/views/home/index.vue"
|
||||
import test from "@/views/home/test.vue"
|
||||
import { createRouter, createWebHashHistory } from "vue-router";
|
||||
import home from "@/views/home/index.vue";
|
||||
import test from "@/views/home/test.vue";
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: "/",
|
||||
name: "home",
|
||||
// component: test,
|
||||
component: home,
|
||||
},
|
||||
{
|
||||
@@ -24,6 +25,14 @@ const routes = [
|
||||
},
|
||||
component: () => import("@/views/register.vue"),
|
||||
},
|
||||
{
|
||||
path: "/group_buy",
|
||||
name: "group_buy",
|
||||
meta: {
|
||||
index: 1,
|
||||
},
|
||||
component: () => import("@/views/group_buy/index.vue"),
|
||||
},
|
||||
{
|
||||
path: "/table",
|
||||
name: "table",
|
||||
@@ -78,7 +87,12 @@ const routes = [
|
||||
path: "/add_label",
|
||||
name: "add_label",
|
||||
component: () => import("@/views/device/add_label.vue"),
|
||||
}
|
||||
},
|
||||
{
|
||||
path: "/webview",
|
||||
name: "webview",
|
||||
component: () => import("@/views/webview/index.vue"),
|
||||
},
|
||||
];
|
||||
|
||||
const router = createRouter({
|
||||
|
||||
15
src/store/global.js
Normal file
15
src/store/global.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
export const useGlobal = defineStore({
|
||||
id: "global",
|
||||
state: () => ({
|
||||
// 是否监听叫号
|
||||
isCallNumber: true,
|
||||
}),
|
||||
actions: {
|
||||
// 更新状态
|
||||
updateData(state) {
|
||||
this.isCallNumber = state;
|
||||
},
|
||||
},
|
||||
});
|
||||
118
src/store/print.js
Normal file
118
src/store/print.js
Normal file
@@ -0,0 +1,118 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { ipcRenderer } from "electron";
|
||||
import { bySubType } from "@/api/device";
|
||||
import { useUser } from "@/store/user.js";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
export const usePrint = defineStore({
|
||||
id: "print",
|
||||
state: () => ({
|
||||
localDevices: [], // 本地打印机列表
|
||||
deviceNoteList: [], // 添加的打印机
|
||||
deviceLableList: [], // 添加的打印机
|
||||
labelList: [], // 要打印的队列数据
|
||||
printTimer: null,
|
||||
}),
|
||||
actions: {
|
||||
// 获取本地打印机和已添加的可以用打印机列表
|
||||
async init() {
|
||||
const store = useUser();
|
||||
|
||||
// 获取本地打印机
|
||||
ipcRenderer.send("getPrintList");
|
||||
ipcRenderer.on("printList", (event, arg) => {
|
||||
// localPrintList.value = arg;
|
||||
// console.log(localPrintList.value);
|
||||
this.localDevices = arg;
|
||||
});
|
||||
|
||||
// 获取已添加的小票打印机
|
||||
this.deviceNoteList = await bySubType({
|
||||
shopId: store.userInfo.shopId,
|
||||
contentType: "local",
|
||||
subType: "cash",
|
||||
});
|
||||
|
||||
// 获取已添加的标签打印机
|
||||
this.deviceLableList = await bySubType({
|
||||
shopId: store.userInfo.shopId,
|
||||
contentType: "local",
|
||||
subType: "label",
|
||||
});
|
||||
console.log("打印队列初始化成功");
|
||||
},
|
||||
// 检查本地打印机是否能正常使用
|
||||
checkLocalPrint(deviceName) {
|
||||
let print = "";
|
||||
for (let item of this.localDevices) {
|
||||
if (item.name == deviceName) {
|
||||
print = item;
|
||||
}
|
||||
}
|
||||
|
||||
if (!print.name) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
// 打印标签小票
|
||||
labelPrint(props) {
|
||||
if (this.checkLocalPrint(this.deviceLableList[0].config.deviceName)) {
|
||||
let pids = this.deviceLableList[0].config.categoryList.map(
|
||||
(item) => item.id
|
||||
);
|
||||
|
||||
let count = 0;
|
||||
let sum = 0;
|
||||
|
||||
props.carts.map((item) => {
|
||||
if (pids.some((el) => el == item.categoryId)) {
|
||||
for (let i = 0; i < item.number; i++) {
|
||||
sum++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
props.carts.map((item) => {
|
||||
if (pids.some((el) => el == item.categoryId)) {
|
||||
for (let i = 0; i < item.number; i++) {
|
||||
count++;
|
||||
this.labelList.push({
|
||||
outNumber: props.outNumber,
|
||||
name: item.name,
|
||||
skuName: item.skuName,
|
||||
masterId: props.orderInfo.tableName,
|
||||
deviceName: this.deviceLableList[0].config.deviceName,
|
||||
// deviceName: "Xprinter XP-T202UA",
|
||||
createdAt: dayjs(props.createdAt).format("YYYY-MM-DD HH:mm:ss"),
|
||||
isPrint: false,
|
||||
count: `${count}/${sum}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
// 执行打印操作
|
||||
this.startLabelPrint();
|
||||
}
|
||||
},
|
||||
// 开始打印标签数据
|
||||
startLabelPrint() {
|
||||
if (this.printTimer != null) return;
|
||||
this.printTimer = setInterval(() => {
|
||||
let item = "";
|
||||
if (!this.labelList.length) {
|
||||
clearInterval(this.printTimer);
|
||||
this.printTimer = null;
|
||||
} else {
|
||||
item = this.labelList[0];
|
||||
if (!item.isPrint) {
|
||||
ipcRenderer.send("printerTagSync", JSON.stringify(item));
|
||||
this.labelList[0].isPrint = true;
|
||||
this.labelList.splice(0, 1);
|
||||
}
|
||||
}
|
||||
}, 800);
|
||||
},
|
||||
},
|
||||
});
|
||||
14
src/store/socket.js
Normal file
14
src/store/socket.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
export const useSocket = defineStore({
|
||||
id: "socket",
|
||||
state: () => ({
|
||||
online: false,
|
||||
}),
|
||||
actions: {
|
||||
// 登录
|
||||
changeOnline(state) {
|
||||
this.online = state;
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -1,23 +1,24 @@
|
||||
import { defineStore } from "pinia"
|
||||
import { login } from '@/api/user'
|
||||
import useStorage from '@/utils/useStorage'
|
||||
import { defineStore } from "pinia";
|
||||
import { login } from "@/api/user";
|
||||
import useStorage from "@/utils/useStorage";
|
||||
|
||||
export const useUser = defineStore({
|
||||
id: "user",
|
||||
state: () => ({
|
||||
userInfo: useStorage.get('userInfo'),
|
||||
token: useStorage.get('token'),
|
||||
userInfo: useStorage.get("userInfo"),
|
||||
token: useStorage.get("token"),
|
||||
}),
|
||||
actions: {
|
||||
// 登录
|
||||
userlogin(param) {
|
||||
return login(param).then(res => {
|
||||
this.userInfo = res
|
||||
this.token = res.token
|
||||
return login(param).then((res) => {
|
||||
this.userInfo = res;
|
||||
this.token = res.token;
|
||||
useStorage.set("token", this.token);
|
||||
// this.userInfo.shopId = "24";
|
||||
useStorage.set("userInfo", this.userInfo);
|
||||
return this.userInfo;
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
* @param {Object} Max
|
||||
*/
|
||||
export function RandomNumBoth(Max, Min = 0) {
|
||||
var Range = Max - Min;
|
||||
var Rand = Math.random();
|
||||
var num = Min + Math.round(Rand * Range); //四舍五入
|
||||
return num;
|
||||
var Range = Max - Min;
|
||||
var Rand = Math.random();
|
||||
var num = Min + Math.round(Rand * Range); //四舍五入
|
||||
return num;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -15,23 +15,40 @@ export function RandomNumBoth(Max, Min = 0) {
|
||||
* @param {Object} obj
|
||||
*/
|
||||
export function clearNoNum(obj) {
|
||||
//如果用户第一位输入的是小数点,则重置输入框内容
|
||||
if (obj.value != '' && obj.value.substr(0, 1) == '.') {
|
||||
obj.value = '';
|
||||
//如果用户第一位输入的是小数点,则重置输入框内容
|
||||
if (obj.value != "" && obj.value.substr(0, 1) == ".") {
|
||||
obj.value = "";
|
||||
}
|
||||
obj.value = obj.value.replace(/^0*(0\.|[1-9])/, "$1"); //粘贴不生效
|
||||
obj.value = obj.value.replace(/[^\d.]/g, ""); //清除“数字”和“.”以外的字符
|
||||
obj.value = obj.value.replace(/\.{2,}/g, "."); //只保留第一个. 清除多余的
|
||||
obj.value = obj.value
|
||||
.replace(".", "$#$")
|
||||
.replace(/\./g, "")
|
||||
.replace("$#$", ".");
|
||||
obj.value = obj.value.replace(/^(\-)*(\d+)\.(\d\d).*$/, "$1$2.$3"); //只能输入两个小数
|
||||
if (obj.value.indexOf(".") < 0 && obj.value != "") {
|
||||
//以上已经过滤,此处控制的是如果没有小数点,首位不能为类似于 01、02的金额
|
||||
if (obj.value.substr(0, 1) == "0" && obj.value.length == 2) {
|
||||
obj.value = obj.value.substr(1, obj.value.length);
|
||||
}
|
||||
obj.value = obj.value.replace(/^0*(0\.|[1-9])/, '$1'); //粘贴不生效
|
||||
obj.value = obj.value.replace(/[^\d.]/g, ''); //清除“数字”和“.”以外的字符
|
||||
obj.value = obj.value.replace(/\.{2,}/g, '.'); //只保留第一个. 清除多余的
|
||||
obj.value = obj.value
|
||||
.replace('.', '$#$')
|
||||
.replace(/\./g, '')
|
||||
.replace('$#$', '.');
|
||||
obj.value = obj.value.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3'); //只能输入两个小数
|
||||
if (obj.value.indexOf('.') < 0 && obj.value != '') {
|
||||
//以上已经过滤,此处控制的是如果没有小数点,首位不能为类似于 01、02的金额
|
||||
if (obj.value.substr(0, 1) == '0' && obj.value.length == 2) {
|
||||
obj.value = obj.value.substr(1, obj.value.length);
|
||||
}
|
||||
}
|
||||
return obj.value;
|
||||
}
|
||||
return obj.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保留小数n位,不进行四舍五入
|
||||
* num你传递过来的数字,
|
||||
* decimal你保留的几位,默认保留小数后两位
|
||||
*/
|
||||
export function formatDecimal(num, decimal = 2) {
|
||||
num = num.toString();
|
||||
const index = num.indexOf(".");
|
||||
if (index !== -1) {
|
||||
num = num.substring(0, decimal + index + 1);
|
||||
} else {
|
||||
num = num.substring(0);
|
||||
}
|
||||
//截取后保留两位小数
|
||||
return parseFloat(num).toFixed(decimal);
|
||||
}
|
||||
60
src/utils/request_php.js
Normal file
60
src/utils/request_php.js
Normal file
@@ -0,0 +1,60 @@
|
||||
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"
|
||||
? "/php/"
|
||||
: import.meta.env.VITE_API_URL,
|
||||
// withCredentials: true, // 跨域请求时发送 cookies
|
||||
timeout: 5000, // 请求超时
|
||||
});
|
||||
|
||||
// 请求拦截器
|
||||
service.interceptors.request.use(
|
||||
(config) => {
|
||||
// 在发送请求之前做些什么 token
|
||||
if (useStorage.get("douyin") && useStorage.get("douyin").token) {
|
||||
config.headers["bausertoken"] = useStorage.get("douyin").token;
|
||||
// config.headers['Content-Type'] = 'application/json'
|
||||
}
|
||||
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;
|
||||
@@ -1,10 +1,7 @@
|
||||
<template>
|
||||
<div class="device_container">
|
||||
<div class="header" @click="router.back()">
|
||||
<el-icon
|
||||
style="position: relative; top: 2px; margin-right: 4px"
|
||||
size="22"
|
||||
>
|
||||
<el-icon style="position: relative; top: 2px; margin-right: 4px" size="22">
|
||||
<ArrowLeft />
|
||||
</el-icon>
|
||||
<el-text>{{ form.id ? "编辑小票打印机" : "添加小票打印机" }}</el-text>
|
||||
@@ -26,28 +23,15 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="选择设备">
|
||||
<el-select v-model="form.config.deviceName">
|
||||
<el-option
|
||||
:label="item.name"
|
||||
:value="item.name"
|
||||
v-for="item in printList"
|
||||
:key="item.name"
|
||||
></el-option>
|
||||
<el-option :label="item.name" :value="item.name" v-for="item in printList" :key="item.name"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备名称">
|
||||
<el-input
|
||||
v-model="form.name"
|
||||
placeholder="请输入设备名称"
|
||||
></el-input>
|
||||
<el-input v-model="form.name" placeholder="请输入设备名称"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="打印份数">
|
||||
<el-select v-model="form.config.printerNum">
|
||||
<el-option
|
||||
:label="item"
|
||||
:value="item"
|
||||
v-for="item in 4"
|
||||
:key="item"
|
||||
></el-option>
|
||||
<el-option :label="item" :value="item" v-for="item in 4" :key="item"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品模式">
|
||||
@@ -70,12 +54,7 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="尾部留空">
|
||||
<el-select v-model="form.config.feet">
|
||||
<el-option
|
||||
:label="`${item}行`"
|
||||
:value="`${item}`"
|
||||
v-for="item in feets"
|
||||
:key="item"
|
||||
></el-option>
|
||||
<el-option :label="`${item}行`" :value="`${item}`" v-for="item in feets" :key="item"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@@ -144,12 +123,7 @@
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="btn">
|
||||
<el-button
|
||||
type="primary"
|
||||
style="width: 100%"
|
||||
:loading="loading"
|
||||
@click="submitHandle"
|
||||
>
|
||||
<el-button type="primary" style="width: 100%" :loading="loading" @click="submitHandle">
|
||||
保存
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -161,6 +135,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import dayjs from 'dayjs'
|
||||
import { ipcRenderer } from "electron";
|
||||
import { onMounted, ref } from "vue";
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
@@ -211,10 +186,43 @@ function printHandle() {
|
||||
ElMessage.warning("请选择打印设备");
|
||||
return;
|
||||
}
|
||||
ipcRenderer.send(
|
||||
"printStart",
|
||||
JSON.stringify({ deviceName: form.value.config.deviceName })
|
||||
);
|
||||
|
||||
// ipcRenderer.send(
|
||||
// "printStart",
|
||||
// JSON.stringify({ deviceName: form.value.config.deviceName })
|
||||
// );
|
||||
|
||||
const data = {
|
||||
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));
|
||||
}
|
||||
|
||||
// 提交打印机
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
<template>
|
||||
<div class="device_container">
|
||||
<div class="header" @click="router.back()">
|
||||
<el-icon
|
||||
style="position: relative; top: 2px; margin-right: 4px"
|
||||
size="22"
|
||||
>
|
||||
<el-icon style="position: relative; top: 2px; margin-right: 4px" size="22">
|
||||
<ArrowLeft />
|
||||
</el-icon>
|
||||
<el-text>{{ form.id ? "编辑便签打印机" : "添加便签打印机" }}</el-text>
|
||||
@@ -26,28 +23,15 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="选择设备">
|
||||
<el-select v-model="form.config.deviceName">
|
||||
<el-option
|
||||
:label="item.name"
|
||||
:value="item.name"
|
||||
v-for="item in printList"
|
||||
:key="item.name"
|
||||
></el-option>
|
||||
<el-option :label="item.name" :value="item.name" v-for="item in printList" :key="item.name"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备名称">
|
||||
<el-input
|
||||
v-model="form.name"
|
||||
placeholder="请输入设备名称"
|
||||
></el-input>
|
||||
<el-input v-model="form.name" placeholder="请输入设备名称"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="打印份数">
|
||||
<el-select v-model="form.config.printerNum">
|
||||
<el-option
|
||||
:label="item"
|
||||
:value="item"
|
||||
v-for="item in 4"
|
||||
:key="item"
|
||||
></el-option>
|
||||
<el-option :label="item" :value="item" v-for="item in 4" :key="item"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品模式">
|
||||
@@ -58,16 +42,10 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="商品分类">
|
||||
<div style="cursor: pointer" @click="classifyRef.show()">
|
||||
<span
|
||||
style="color: #409eff"
|
||||
v-for="item in form.config.categoryList"
|
||||
>
|
||||
<span style="color: #409eff" v-for="item in form.config.categoryList">
|
||||
{{ item.name }},
|
||||
</span>
|
||||
<span
|
||||
style="color: #e65d6e"
|
||||
v-if="!form.config.categoryList.length"
|
||||
>
|
||||
<span style="color: #e65d6e" v-if="!form.config.categoryList.length">
|
||||
请选择分类
|
||||
</span>
|
||||
</div>
|
||||
@@ -98,52 +76,51 @@
|
||||
</div>
|
||||
<div class="menu_wrap">
|
||||
<div class="print_view">
|
||||
<div class="title t1 blod">#A9 #A9</div>
|
||||
<div class="row blod">
|
||||
<span>甜橙马黛茶</span>
|
||||
<span style="margin-left: 30px">1</span>
|
||||
<canvas class="ewm" ref="canvasRef"></canvas>
|
||||
<div class="header">
|
||||
<img class="logo" src="../../assets/prinnt_label_logo.png" />
|
||||
<!-- <span class="title">双屿Pisces</span> -->
|
||||
</div>
|
||||
<div class="row blod">加奶、加珍珠</div>
|
||||
<div class="row blod" style="margin-top: 10px">
|
||||
<span>03-08 16:58</span>
|
||||
<span style="margin-left: 30px">¥28</span>
|
||||
<div class="number_wrap">
|
||||
<div class="num" v-if="printData.outNumber">{{ printData.outNumber }}</div>
|
||||
<div class="info" v-if="printData.masterId">座位号:{{ printData.masterId }}</div>
|
||||
</div>
|
||||
<div class="btn_wrap">
|
||||
<div class="btn">
|
||||
<el-button plain style="width: 100%" @click="printHandle">
|
||||
打印测试小票
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="btn">
|
||||
<el-button
|
||||
type="primary"
|
||||
style="width: 100%"
|
||||
:loading="loading"
|
||||
@click="submitHandle"
|
||||
>
|
||||
保存
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="shop_info">
|
||||
<div class="name">{{ printData.name }}</div>
|
||||
<div class="text" v-if="printData.skuName">【{{ printData.skuName }}】</div>
|
||||
</div>
|
||||
<div class="time">{{ printData.createdAt }}</div>
|
||||
<div class="tips">建议尽快享用,风味更佳 {{ printData.count }}</div>
|
||||
</div>
|
||||
<div class="btn_wrap">
|
||||
<div class="btn">
|
||||
<el-button plain style="width: 100%" @click="printHandle">
|
||||
打印测试小票
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="btn">
|
||||
<el-button type="primary" style="width: 100%" :loading="loading" @click="submitHandle">
|
||||
保存
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<classify
|
||||
ref="classifyRef"
|
||||
@success="(e) => (form.config.categoryList = e)"
|
||||
/>
|
||||
<classify ref="classifyRef" @success="(e) => (form.config.categoryList = e)" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import _ from 'lodash'
|
||||
import { ipcRenderer } from "electron";
|
||||
import { onMounted, ref } from "vue";
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { ElMessage, dayjs } from "element-plus";
|
||||
import { tbPrintMachinePost, tbPrintMachineDetail } from "@/api/device";
|
||||
import { useUser } from "@/store/user.js";
|
||||
import { Loading } from "element-plus/es/components/loading/src/service";
|
||||
import classify from "@/components/classify/index.vue";
|
||||
import QRCode from 'qrcode'
|
||||
|
||||
const store = useUser();
|
||||
|
||||
@@ -175,6 +152,16 @@ const form = ref({
|
||||
shopId: store.userInfo.shopId,
|
||||
});
|
||||
|
||||
const canvasRef = ref(null)
|
||||
const printData = ref({
|
||||
deviceName: '',
|
||||
outNumber: '123',
|
||||
name: '甜橙马黛茶',
|
||||
skuName: '加奶、加珍珠',
|
||||
masterId: '#A9',
|
||||
createdAt: dayjs().format('YYYY-MM-DD HH:mm:ss')
|
||||
})
|
||||
|
||||
// 获取打印机列表
|
||||
function getPrintList() {
|
||||
ipcRenderer.send("getPrintList");
|
||||
@@ -184,16 +171,16 @@ function getPrintList() {
|
||||
}
|
||||
|
||||
// 测试打印
|
||||
function printHandle() {
|
||||
const printHandle = _.throttle(function () {
|
||||
if (!form.value.config.deviceName) {
|
||||
ElMessage.warning("请选择打印设备");
|
||||
ElMessage.error("请选择打印设备");
|
||||
return;
|
||||
}
|
||||
ipcRenderer.send(
|
||||
"printStart",
|
||||
JSON.stringify({ deviceName: form.value.config.deviceName })
|
||||
"printerTagSync",
|
||||
JSON.stringify(printData.value)
|
||||
);
|
||||
}
|
||||
}, 1500, { leading: true, trailing: false })
|
||||
|
||||
// 提交打印机
|
||||
async function submitHandle() {
|
||||
@@ -217,6 +204,7 @@ async function tbPrintMachineDetailAjax() {
|
||||
try {
|
||||
const res = await tbPrintMachineDetail(route.query.id);
|
||||
form.value = res;
|
||||
printData.value.deviceName = res.config.deviceName
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
@@ -227,6 +215,11 @@ onMounted(() => {
|
||||
if (route.query.id) {
|
||||
tbPrintMachineDetailAjax(route.query.id);
|
||||
}
|
||||
|
||||
QRCode.toCanvas(canvasRef.value, printData.value.outNumber, function (error) {
|
||||
if (error) console.error(error)
|
||||
// console.log('success!');
|
||||
})
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -267,76 +260,59 @@ onMounted(() => {
|
||||
padding: 0 15px;
|
||||
|
||||
.print_view {
|
||||
position: relative;
|
||||
|
||||
.ewm {
|
||||
$size: 50px;
|
||||
width: $size;
|
||||
height: $size;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.logo {
|
||||
$size: 90px;
|
||||
width: $size;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-left: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.number_wrap {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
|
||||
.num {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.info {
|
||||
margin-left: 12px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.time {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.btn_wrap {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
padding: 20px 0;
|
||||
.blod {
|
||||
font-weight: 600;
|
||||
}
|
||||
.title {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 4px;
|
||||
|
||||
&.t1 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
&.t2 {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.row {
|
||||
margin-top: 2px;
|
||||
|
||||
&.between {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
.btn_wrap {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
padding: 20px 0;
|
||||
|
||||
.btn {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.line {
|
||||
margin: 10px 0;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.table {
|
||||
width: 100%;
|
||||
|
||||
tr {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
td {
|
||||
flex: 1;
|
||||
|
||||
&:nth-child(1) {
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
&:not(:first-child) {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.sku {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
111
src/views/group_buy/components/refundDialog.vue
Normal file
111
src/views/group_buy/components/refundDialog.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<el-dialog title="退款" v-model="showDialog" width="400px" @close="reset">
|
||||
<el-form ref="refundFormRef" :model="refundForm" :rules="refundFormRules" label-position="top">
|
||||
<el-form-item label="退单数" prop="num">
|
||||
<el-select v-model="refundForm.num" placeholder="请选择退单数" style="width: 100%;" @change="refundNumChange">
|
||||
<el-option :label="item" :value="item" v-for="item in refundNumList" :key="item"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="退单金额">
|
||||
<el-input v-model="refundForm.refundAmount" disabled placeholder="请选择退单数"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="退款原因">
|
||||
<el-input v-model="refundForm.refundReason" type="textarea" placeholder="请输入退款原因"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="showDialog = false" style="width: 100%;">取消</el-button>
|
||||
<el-button type="primary" :loading="refundLoading" @click="refundConfirm" style="width: 100%;">确
|
||||
定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { returnGpOrder } from '@/api/group'
|
||||
import { ref, reactive } from 'vue'
|
||||
import { ElMessage } from "element-plus";
|
||||
|
||||
const emits = defineEmits(["success"]);
|
||||
|
||||
const newRow = ref('')
|
||||
const showDialog = ref(false)
|
||||
const refundLoading = ref(false)
|
||||
const refundFormRef = ref(null)
|
||||
const refundForm = reactive({
|
||||
num: '',
|
||||
orderId: '',
|
||||
refundAmount: '',
|
||||
refundDesc: '',
|
||||
refundReason: ''
|
||||
})
|
||||
|
||||
const refundFormRules = reactive({
|
||||
num: [
|
||||
{
|
||||
required: true,
|
||||
message: ' ',
|
||||
trigger: 'change'
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
const refundNumList = ref([])
|
||||
|
||||
// 提交退单
|
||||
function refundConfirm() {
|
||||
refundFormRef.value.validate(async valid => {
|
||||
if (valid) {
|
||||
try {
|
||||
refundLoading.value = true
|
||||
const res = await returnGpOrder(refundForm)
|
||||
ElMessage.success('退单成功')
|
||||
refundLoading.value = false
|
||||
showDialog.value = false
|
||||
emits('succcess')
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
refundLoading.value = false
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 计算退单金额
|
||||
function refundNumChange(e) {
|
||||
refundForm.refundAmount = Math.floor(newRow.value.orderAmount / newRow.value.number * e * 100) / 100
|
||||
}
|
||||
|
||||
// 显示
|
||||
function show(row) {
|
||||
showDialog.value = true;
|
||||
newRow.value = row
|
||||
let arr = []
|
||||
for (let i = 1; i <= row.number - row.refundNumber; i++) {
|
||||
arr.push(i)
|
||||
}
|
||||
refundNumList.value = arr
|
||||
refundForm.orderId = row.id
|
||||
}
|
||||
|
||||
// 初始化
|
||||
function reset() {
|
||||
newRow.value = ''
|
||||
refundNumList.value = []
|
||||
refundForm.orderId = ''
|
||||
for (let key in refundForm) {
|
||||
refundForm[key] = ''
|
||||
}
|
||||
refundFormRef.value.resetFields()
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
show
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
476
src/views/group_buy/components/scanGroup.vue
Normal file
476
src/views/group_buy/components/scanGroup.vue
Normal file
@@ -0,0 +1,476 @@
|
||||
<!-- 扫码弹窗 -->
|
||||
|
||||
<template>
|
||||
<div class="dialog">
|
||||
<el-dialog :title="`核销${props.title}团购券`" width="600" v-model="dialogVisible" @open="reset">
|
||||
<div class="content">
|
||||
<div class="left">
|
||||
<el-image :src="icon" style="width: 60px; height: 60px"></el-image>
|
||||
</div>
|
||||
<div class="right" v-if="!userPayWait">
|
||||
<div class="amount">
|
||||
<span class="t">扫码核销</span>
|
||||
<!-- <span class="n">{{ props.amount }}</span> -->
|
||||
</div>
|
||||
<div class="input">
|
||||
<el-input ref="inputRef" v-model="scanCode"
|
||||
style="height: calc(var(--el-component-size-large) + 30px)" placeholder="请扫描团购券" clearable
|
||||
@change="inputChange"></el-input>
|
||||
<div class="tips">注意:扫码支付请保证输入框获得焦点,输入内容结束后会自动核销,请勿重复操作</div>
|
||||
</div>
|
||||
<!-- <div class="number_warp">
|
||||
<div class="item" v-for="item in 9" :key="item" @click="inputHandle(item)">{{ item }}</div>
|
||||
<div class="item disabled">.</div>
|
||||
<div class="item" @click="inputHandle(0)">0</div>
|
||||
<div class="item" @click="delHandle">
|
||||
<el-icon>
|
||||
<CloseBold />
|
||||
</el-icon>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="btn">
|
||||
<el-button type="primary" style="width: 100%" v-loading="loading">立即核销</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pay_wait" v-else>
|
||||
<div class="loading" v-loading="loading" element-loading-text="用户支付中..."></div>
|
||||
<div class="btn">
|
||||
<el-button type="primary" style="width: 100%" v-loading="checkPayStatusLoading"
|
||||
@click="checkPayStauts">
|
||||
<span v-if="!checkPayStatusLoading">查询用户支付状态</span>
|
||||
<span v-else>查询中...</span>
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="btn">
|
||||
<el-button style="width: 100%" @click="resetScanCode">
|
||||
重新扫码
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<el-dialog title="团购券详情" width="600" v-model="detailVisible">
|
||||
<div class="group_detil">
|
||||
<div class="shop_info" v-if="props.type == 1">
|
||||
<el-image :src="groupDetail.images[0]" style="width: 50px;height: 50px;"></el-image>
|
||||
<div class="info">
|
||||
<div class="name">{{ groupDetail.productName }}</div>
|
||||
<div class="price">
|
||||
<span class="p">¥{{ groupDetail.salePrice }}</span>
|
||||
<span class="o">¥{{ groupDetail.originPrice }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table">
|
||||
<el-table :data="groupDetail.productList" border v-if="props.type == 1">
|
||||
<el-table-column label="名称" prop="title"></el-table-column>
|
||||
<el-table-column label="数量" prop="number"></el-table-column>
|
||||
<el-table-column label="商品信息">
|
||||
<template v-slot="scope">
|
||||
<div class="shop_list">
|
||||
<div class="item" v-for="(item, index) in scope.row.goods" :key="item.id">
|
||||
<span class="dot"></span>
|
||||
<div class="name">
|
||||
<div class="t">{{ item.name }}</div>
|
||||
<div class="t">x{{ item.groupNum }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<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 label="名称" prop="title"></el-table-column>
|
||||
<el-table-column label="价格" prop="amount"></el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<el-button style="width: 100%;" @click="detailVisible = false">取消</el-button>
|
||||
<el-button type="primary" style="width: 100%;" :loading="groupDetailLoading"
|
||||
@click="groupOrdergroupScanHandle">确认核销</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import _ from "lodash";
|
||||
import { ref } from "vue";
|
||||
import icon from "@/assets/icon_scan.png";
|
||||
import { groupOrderorderInfo, groupOrdergroupScan, douyinfulfilmentcertificateprepare, douyincertificateprepare } from '@/api/group'
|
||||
import { useUser } from "@/store/user.js";
|
||||
const store = useUser();
|
||||
import {
|
||||
queryMembermember,
|
||||
createMembermember,
|
||||
membermemberScanPay,
|
||||
accountPaymember,
|
||||
} from "@/api/member/index.js";
|
||||
import { ElMessage } from "element-plus";
|
||||
const emits = defineEmits(["success"]);
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
type: {
|
||||
type: Number,
|
||||
default: 1
|
||||
}
|
||||
});
|
||||
|
||||
const dialogVisible = ref(false);
|
||||
const scanCode = ref("");
|
||||
const inputRef = ref(null);
|
||||
|
||||
const loading = ref(false);
|
||||
const userPayWait = ref(false);
|
||||
const checkPayStatusLoading = ref(false);
|
||||
|
||||
const fastOrder = ref('')
|
||||
|
||||
const groupDetailLoading = ref(false)
|
||||
const groupDetail = ref({})
|
||||
const detailVisible = ref(false)
|
||||
|
||||
// 团购卷核销(仅核销待使用订单)
|
||||
async function groupOrdergroupScanHandle() {
|
||||
try {
|
||||
switch (props.type) {
|
||||
case 1:
|
||||
{
|
||||
groupDetailLoading.value = true
|
||||
const res = await groupOrdergroupScan({
|
||||
id: groupDetail.value.id
|
||||
})
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
groupDetailLoading.value = true
|
||||
let encrypted_codes = groupDetail.value.goods.map(item => item.encrypted_code)
|
||||
const res = await douyincertificateprepare({
|
||||
verify_token: groupDetail.value.verify_token,
|
||||
encrypted_codes: encrypted_codes.join(','),
|
||||
id: groupDetail.value.id
|
||||
})
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
groupDetailLoading.value = false
|
||||
detailVisible.value = false
|
||||
scanCode.value = ''
|
||||
inputRef.value.focus();
|
||||
ElMessage.success('核销成功')
|
||||
emits('succcess')
|
||||
} catch (error) {
|
||||
groupDetailLoading.value = false
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
const douyin_table = ref(null)
|
||||
|
||||
// 选择要核销的券
|
||||
function douyinSelectionChange(e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
// 核销券码
|
||||
async function submitHandle() {
|
||||
try {
|
||||
loading.value = true
|
||||
switch (props.type) {
|
||||
case 1:
|
||||
{
|
||||
const res = await groupOrderorderInfo({
|
||||
coupon: scanCode.value,
|
||||
});
|
||||
loading.value = false
|
||||
groupDetail.value = res
|
||||
detailVisible.value = true
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
const res = await douyinfulfilmentcertificateprepare({
|
||||
object_id: decodeURI(scanCode.value),
|
||||
});
|
||||
loading.value = false
|
||||
groupDetail.value = res
|
||||
detailVisible.value = true
|
||||
setTimeout(() => {
|
||||
groupDetail.value.goods.map(item => {
|
||||
douyin_table.value.toggleRowSelection(item)
|
||||
})
|
||||
}, 100)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
loading.value = false
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
// 重新扫码
|
||||
function resetScanCode() {
|
||||
userPayWait.value = false;
|
||||
loading.value = false;
|
||||
scanCode.value = "";
|
||||
inputRef.value.focus();
|
||||
}
|
||||
|
||||
// 输入
|
||||
function inputHandle(n) {
|
||||
scanCode.value += n;
|
||||
inputRef.value.focus();
|
||||
}
|
||||
|
||||
// 删除
|
||||
function delHandle() {
|
||||
if (!scanCode.value) return;
|
||||
scanCode.value = scanCode.value.substring(0, scanCode.value.length - 1);
|
||||
inputRef.value.focus();
|
||||
}
|
||||
|
||||
// 监听扫码枪回车事件
|
||||
// function enterHandle() {
|
||||
// inputRef.value.focus()
|
||||
// }
|
||||
|
||||
const inputChange = _.debounce(function (e) {
|
||||
// console.log(e);
|
||||
if (scanCode.value) {
|
||||
submitHandle();
|
||||
}
|
||||
}, 500);
|
||||
|
||||
function show() {
|
||||
dialogVisible.value = true;
|
||||
setTimeout(() => {
|
||||
inputRef.value.focus();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function close() {
|
||||
dialogVisible.value = false;
|
||||
}
|
||||
|
||||
function reset() {
|
||||
loading.value = false;
|
||||
scanCode.value = "";
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
show,
|
||||
close,
|
||||
loading,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.footer {
|
||||
display: flex;
|
||||
padding: 0 14px 14px;
|
||||
}
|
||||
|
||||
.group_detil {
|
||||
padding: 14px;
|
||||
|
||||
.shop_info {
|
||||
display: flex;
|
||||
|
||||
.info {
|
||||
flex: 1;
|
||||
padding-left: 10px;
|
||||
|
||||
.name {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.price {
|
||||
.p {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.o {
|
||||
color: #999;
|
||||
text-decoration: line-through;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table {
|
||||
padding-top: 14px;
|
||||
}
|
||||
|
||||
.shop_list {
|
||||
.item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&:not(:first-child) {
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.dot {
|
||||
$size: 6px;
|
||||
width: $size;
|
||||
height: $size;
|
||||
border-radius: 50%;
|
||||
background-color: #1890FF;
|
||||
}
|
||||
|
||||
.name {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
margin-left: 10px;
|
||||
align-items: center;
|
||||
|
||||
.t {
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
width: 100px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.del {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
color: #555;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.tips {
|
||||
padding-top: 10px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.dialog :deep(.el-dialog__body) {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
|
||||
.left {
|
||||
width: 200px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #efefef;
|
||||
}
|
||||
|
||||
.right {
|
||||
flex: 1;
|
||||
padding: var(--el-font-size-base);
|
||||
|
||||
.amount {
|
||||
display: flex;
|
||||
height: calc(var(--el-component-size-large) + 20px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
color: var(--primary-color);
|
||||
background-color: #555;
|
||||
border-radius: 6px;
|
||||
padding: 0 var(--el-font-size-base);
|
||||
font-size: calc(var(--el-font-size-base) + 10px);
|
||||
}
|
||||
|
||||
.input {
|
||||
padding: var(--el-font-size-base) 0;
|
||||
|
||||
:deep(.el-input__inner) {
|
||||
font-size: calc(var(--el-font-size-base) + 10px);
|
||||
}
|
||||
}
|
||||
|
||||
.number_warp {
|
||||
--h: 50px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-template-rows: var(--h) var(--h) var(--h) var(--h);
|
||||
gap: 8px;
|
||||
|
||||
.item {
|
||||
background-color: #dddddd;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(var(--el-font-size-base) + 10px);
|
||||
border-radius: 4px;
|
||||
|
||||
&.disabled {
|
||||
color: #999;
|
||||
background-color: #efefef;
|
||||
|
||||
&:active {
|
||||
background-color: #efefef;
|
||||
}
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: #b9b9b9;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// .btn {
|
||||
// padding-top: 20px;
|
||||
// }
|
||||
}
|
||||
|
||||
.pay_wait {
|
||||
flex: 1;
|
||||
padding: 0 var(--el-font-size-base);
|
||||
height: 400px;
|
||||
padding-bottom: 100px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.loading {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
--el-loading-spinner-size: 100px;
|
||||
|
||||
:deep(.el-loading-text) {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 200px;
|
||||
padding-top: var(--el-font-size-base);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
431
src/views/group_buy/index.vue
Normal file
431
src/views/group_buy/index.vue
Normal file
@@ -0,0 +1,431 @@
|
||||
<template>
|
||||
<div class="content">
|
||||
<div class="cart_wrap card">
|
||||
<div class="header">
|
||||
<div class="left">
|
||||
<el-select v-model="tableData.type" placeholder="核销类型">
|
||||
<el-option v-for="item in typeList" :key="item.value" :value="item.value"
|
||||
:label="item.label"></el-option>
|
||||
</el-select>
|
||||
<el-input placeholder="搜索订单" v-model="tableData.proName" @focus="
|
||||
global.updateData(false)" @blur="global.updateData(true)"></el-input>
|
||||
<el-select v-model="tableData.status" placeholder="订单状态">
|
||||
<el-option v-for="item in statusList" :key="item.value" :value="item.value"
|
||||
:label="item.label"></el-option>
|
||||
</el-select>
|
||||
<div class="btn">
|
||||
<el-button type="primary" :icon="Search" @click="groupOrderlistAjax">搜索</el-button>
|
||||
<el-button :icon="RefreshRight" :loading="tableData.resetLoading"
|
||||
@click="resetHandle">重置</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-button type="warning" :icon="FullScreen" @click="scanGroupRef.show()">核销团购券</el-button>
|
||||
</div>
|
||||
<div class="tab_container">
|
||||
<el-table :data="tableData.list" height="540px" v-loading="tableData.loading"
|
||||
v-if="tableData.type == 1">
|
||||
<el-table-column label="订单号" prop="orderNo" width="100px"></el-table-column>
|
||||
<el-table-column label="优惠卷" prop="proImg" width="200px">
|
||||
<template v-slot="scope">
|
||||
<div class="info_wrap">
|
||||
<el-image :src="scope.row.proImg" style="width: 40px;height: 40px;flex-shrink: 0;" />
|
||||
<div class="t">{{ scope.row.proName }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column label="支付方式" prop="payType">
|
||||
<template v-slot="scope">
|
||||
{{ payTypeFilter(scope.row.payType) }}
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<el-table-column label="订单金额" prop="orderAmount">
|
||||
<template v-slot="scope">
|
||||
¥{{ scope.row.orderAmount }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="实付金额" prop="payAmount">
|
||||
<template v-slot="scope">
|
||||
¥{{ scope.row.payAmount }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="下单数量" prop="number">
|
||||
<template v-slot="scope">
|
||||
{{ scope.row.number }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" prop="status">
|
||||
<template v-slot="scope">
|
||||
{{ statusFilter(scope.row.status) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" fixed="right">
|
||||
<template v-slot="scope">
|
||||
<el-button type="primary" size="small"
|
||||
v-if="scope.row.refundAble == 1 && scope.row.status == 'unused'"
|
||||
@click="refundDialogRef.show(scope.row)">退款</el-button>
|
||||
<el-button type="primary" size="small" disabled v-else>退款</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-table :data="tableData.list" height="540px" v-loading="tableData.loading"
|
||||
v-if="tableData.type == 2">
|
||||
<el-table-column label="抖音订单号" prop="d_order_id" width="240"></el-table-column>
|
||||
<el-table-column label="总金额" prop="pay_amount" width="100">
|
||||
<template v-slot="scope">
|
||||
<span style="color: var(--primary-color);">¥{{ scope.row.pay_amount }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="商品信息" prop="douyinCodeGoods">
|
||||
<template v-slot="scope">
|
||||
<div class="goods_list">
|
||||
<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;">
|
||||
{{ item.title }}
|
||||
</div>
|
||||
<div class="item" style="flex: 1;margin-right: 10px;color: var(--primary-color);">
|
||||
¥{{ item.pay_amount }}
|
||||
</div>
|
||||
<div class="item" style="margin-right: 10px;">
|
||||
<el-tag type="success" disable-transitions size="default" effect="light" round>
|
||||
{{ item.status_text }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div class="item" style="flex: 1;display: flex;justify-content: flex-end;">
|
||||
<el-button type="danger" size="small" v-if="item.is_show_cacel_banner"
|
||||
@click="cacelDouyinHandle(item)">撤销</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<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>
|
||||
<scanGroup ref="scanGroupRef" :title="typeList.find(item => item.value == tableData.type).label"
|
||||
:type="tableData.type" @succcess="groupOrderlistAjax" />
|
||||
<refundDialog ref="refundDialogRef" @success="groupOrderlistAjax" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { groupOrderlist, douyinorderlist, douyinfulfilmentcertificatecancel } from '@/api/group'
|
||||
import { Search, RefreshRight, FullScreen } from '@element-plus/icons-vue'
|
||||
import { ElMessageBox, ElMessage } from 'element-plus'
|
||||
import { ref, onMounted, reactive } from 'vue'
|
||||
import scanGroup from './components/scanGroup.vue'
|
||||
import refundDialog from './components/refundDialog.vue'
|
||||
import { useUser } from "@/store/user.js"
|
||||
const store = useUser()
|
||||
|
||||
import { useGlobal } from '@/store/global.js'
|
||||
const global = useGlobal()
|
||||
|
||||
const scanGroupRef = ref(null)
|
||||
const refundDialogRef = ref(null)
|
||||
|
||||
const tableData = reactive({
|
||||
resetLoading: false,
|
||||
proName: '',
|
||||
type: 1,
|
||||
status: '',
|
||||
loading: false,
|
||||
list: [],
|
||||
page: 1,
|
||||
size: 10,
|
||||
total: 0
|
||||
})
|
||||
|
||||
// 支付方式类型
|
||||
function payTypeFilter(t) {
|
||||
const m = {
|
||||
wechatPay: '微信支付',
|
||||
aliPay: '支付宝支付'
|
||||
}
|
||||
return m[t]
|
||||
}
|
||||
|
||||
// 订单类型
|
||||
const typeList = reactive([
|
||||
{
|
||||
value: 1,
|
||||
label: '自营'
|
||||
},
|
||||
{
|
||||
value: 2,
|
||||
label: '抖音'
|
||||
}
|
||||
])
|
||||
|
||||
const statusList = reactive([
|
||||
{
|
||||
value: 'unpaid',
|
||||
label: '待付款'
|
||||
},
|
||||
{
|
||||
value: 'unused',
|
||||
label: '待使用'
|
||||
},
|
||||
{
|
||||
value: 'closed',
|
||||
label: '已完成'
|
||||
},
|
||||
{
|
||||
value: 'refunding',
|
||||
label: '退款中'
|
||||
},
|
||||
{
|
||||
value: 'refund',
|
||||
label: '已退款'
|
||||
},
|
||||
{
|
||||
value: 'cancelled',
|
||||
label: '已取消'
|
||||
}
|
||||
])
|
||||
|
||||
// 状态
|
||||
function statusFilter(t) {
|
||||
return statusList.find(item => item.value == t)?.label
|
||||
}
|
||||
|
||||
// 分页变化
|
||||
function paginationChange(e) {
|
||||
tableData.page = e
|
||||
groupOrderlistAjax()
|
||||
}
|
||||
|
||||
// 重置
|
||||
function resetHandle() {
|
||||
tableData.proName = ''
|
||||
tableData.status = ''
|
||||
tableData.page = 1
|
||||
tableData.resetLoading = true
|
||||
groupOrderlistAjax()
|
||||
}
|
||||
|
||||
// 显示团购核销撤销
|
||||
function cacelDouyinHandle(item) {
|
||||
ElMessageBox.confirm(
|
||||
'是否撤销该团购?',
|
||||
'注意').then(async () => {
|
||||
await douyinfulfilmentcertificatecancel({ verify_id: item.verify_id, certificate_id: item.certificate_id })
|
||||
ElMessage.success('撤销成功')
|
||||
groupOrderlistAjax()
|
||||
}).catch(() => { })
|
||||
}
|
||||
|
||||
// 获取团购订单数据
|
||||
async function groupOrderlistAjax() {
|
||||
try {
|
||||
tableData.loading = true
|
||||
let res = ''
|
||||
switch (tableData.type) {
|
||||
case 1:
|
||||
// 获取本店团购数据
|
||||
res = await groupOrderlist({
|
||||
shopId: store.userInfo.shopId,
|
||||
proName: tableData.proName,
|
||||
status: tableData.status,
|
||||
page: tableData.page,
|
||||
size: tableData.size
|
||||
})
|
||||
tableData.resetLoading = false
|
||||
tableData.loading = false
|
||||
tableData.list = res.list
|
||||
tableData.total = res.total
|
||||
break;
|
||||
case 2:
|
||||
// 获取抖音团购数据
|
||||
res = await douyinorderlist({
|
||||
page: tableData.page
|
||||
})
|
||||
tableData.resetLoading = false
|
||||
tableData.loading = false
|
||||
tableData.list = res.list
|
||||
tableData.total = res.count
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
tableData.loading = false
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
groupOrderlistAjax()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.pagination {
|
||||
display: flex;
|
||||
padding: 0 14px;
|
||||
}
|
||||
|
||||
.info_wrap {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
|
||||
.t {
|
||||
width: 100px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.cart_wrap {
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
.right_card {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
margin-left: var(--el-font-size-base);
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
padding: 14px;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #ececec;
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
|
||||
.btn {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.menus {
|
||||
display: flex;
|
||||
padding: 0 10px;
|
||||
|
||||
.item {
|
||||
padding: 0 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
|
||||
span {
|
||||
font-size: var(--el-font-size-base);
|
||||
}
|
||||
|
||||
&.active {
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
width: 70%;
|
||||
height: 4px;
|
||||
border-radius: 4px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 15%;
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
|
||||
span {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.all {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.tab_container {
|
||||
padding: 0 var(--el-font-size-base) var(--el-font-size-base);
|
||||
|
||||
.tab_head {
|
||||
padding-bottom: var(--el-font-size-base);
|
||||
}
|
||||
|
||||
.overflow_y {
|
||||
height: calc(100vh - 225px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.tab_list {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||
grid-template-rows: auto;
|
||||
gap: var(--el-font-size-base);
|
||||
|
||||
.item {
|
||||
background-color: #efefef;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
border: 2px solid #fff;
|
||||
|
||||
&.active {
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tab_title {
|
||||
height: var(--el-component-size-large);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 10px;
|
||||
color: #fff;
|
||||
|
||||
&.subscribe {
|
||||
background-color: var(--el-color-success);
|
||||
}
|
||||
|
||||
&.closed {
|
||||
background-color: #999;
|
||||
}
|
||||
|
||||
&.opening {
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
|
||||
&.cleaning {
|
||||
background-color: var(--el-color-danger);
|
||||
}
|
||||
}
|
||||
|
||||
.tab_cont {
|
||||
height: 120px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.icon {
|
||||
color: #555;
|
||||
font-size: 30px;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.goods_list {
|
||||
.row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&:not(:first-child) {
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -27,26 +27,33 @@
|
||||
</div>
|
||||
<div class="search_wrap">
|
||||
<div class="input">
|
||||
<el-input placeholder="请输入商品名称查询" prefix-icon="Search" v-model="commdityName" clearable
|
||||
@input="inputChange"></el-input>
|
||||
<el-input placeholder="请输入商品名称查询" v-model="commdityName" clearable @focus="
|
||||
global.updateData(false)" @blur="global.updateData(true)" @input="inputChange"></el-input>
|
||||
</div>
|
||||
<el-button :icon="shopListType == 'text' ? 'PictureRounded' : 'PriceTag'"
|
||||
@click="changeShopListType"></el-button>
|
||||
<el-button :loading="searchLoading" :icon="Search" @click="searchHandle">搜索</el-button>
|
||||
<!-- <el-button :icon="shopListType == 'text' ? 'PictureRounded' : 'PriceTag'"
|
||||
@click="changeShopListType"></el-button> -->
|
||||
</div>
|
||||
<div class="shop_list" :class="{ img: shopListType == 'img' }" v-loading="loading">
|
||||
<div class="item_wrap" v-for="item in goodsList" :key="item.id" @click="showSkuHandle(item)">
|
||||
<div class="item">
|
||||
<div class="dot" v-if="item.orderCount">{{ item.orderCount }}</div>
|
||||
<div class="cover" v-if="shopListType == 'img'">
|
||||
<el-image :src="item.coverImg" class="el_img" fit="cover" lazy></el-image>
|
||||
<!-- <swiper class="swiper_box" direction="vertical" @slideChange="onSlideChange"> -->
|
||||
<swiper class="swiper_box" direction="vertical" @slideChange="onSlideChange">
|
||||
<swiper-slide class="slide_item" v-for="(goods, index) in goodsList" :key="index">
|
||||
<div class="item_wrap" v-for="item in goods" :key="item.id" @click="showSkuHandle(item)">
|
||||
<div class="item">
|
||||
<div class="dot" v-if="item.orderCount">{{ item.orderCount }}</div>
|
||||
<div class="cover" v-if="shopListType == 'img'">
|
||||
<el-image :src="`${item.coverImg}?x-oss-process=image/resize,m_lfit,w_150,h_150`"
|
||||
class="el_img" fit="cover"></el-image>
|
||||
</div>
|
||||
<div class="name"><el-text line-clamp="1">{{ item.name }}</el-text></div>
|
||||
<div class="item_empty" v-if="shopListType == 'text'"></div>
|
||||
<div class="price">
|
||||
<el-text>¥{{ item.lowPrice }}</el-text>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="name"><el-text line-clamp="2">{{ item.name }}</el-text></div>
|
||||
<div class="item_empty" v-if="shopListType == 'text'"></div>
|
||||
<div class="price">
|
||||
<el-text>¥{{ item.lowPrice }}</el-text>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</swiper-slide>
|
||||
</swiper>
|
||||
</div>
|
||||
<div class="empty">
|
||||
<el-empty description="空空如也~" v-if="!goodsList.length" />
|
||||
@@ -56,14 +63,24 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { Search } from '@element-plus/icons-vue'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import _ from 'lodash'
|
||||
import useStorage from "@/utils/useStorage";
|
||||
|
||||
import skuModal from '@/components/skuModal.vue'
|
||||
|
||||
import { queryCategory, productqueryCommodityInfo, queryProductSku } from '@/api/product'
|
||||
import { queryCategory, queryNewCommodityInfo, queryProductSku } from '@/api/product'
|
||||
import { useUser } from "@/store/user.js"
|
||||
|
||||
import { Swiper, SwiperSlide } from 'swiper/vue'
|
||||
import "swiper/swiper-bundle.css";
|
||||
|
||||
|
||||
import { useGlobal } from '@/store/global.js'
|
||||
const global = useGlobal()
|
||||
|
||||
|
||||
const store = useUser()
|
||||
|
||||
const props = defineProps({
|
||||
@@ -77,7 +94,7 @@ const emit = defineEmits(['success'])
|
||||
|
||||
const skuModalRef = ref(null)
|
||||
|
||||
const shopListType = ref('text')
|
||||
const shopListType = ref('img')
|
||||
|
||||
const categorys = ref([])
|
||||
const categorysActive = ref(0)
|
||||
@@ -86,13 +103,33 @@ const commdityName = ref('')
|
||||
|
||||
const loading = ref(false)
|
||||
const goodsList = ref([])
|
||||
const goodsPage = ref(1)
|
||||
const goodsPageSize = ref(12)
|
||||
const finish = ref(false) // 是否加载完
|
||||
const currentGoodsIndex = ref(0)
|
||||
const loopMax = ref(0)
|
||||
const loopTimer = ref(null)
|
||||
|
||||
const showPopover = ref(false)
|
||||
|
||||
const inputChange = _.debounce(function () {
|
||||
productqueryCommodityInfoAjax()
|
||||
searchHandle()
|
||||
}, 500)
|
||||
|
||||
// 搜索
|
||||
const searchLoading = ref(false)
|
||||
function searchHandle() {
|
||||
searchLoading.value = true
|
||||
goodsList.value = []
|
||||
goodsPage.value = 1
|
||||
finish.value = false
|
||||
currentGoodsIndex.value = 0
|
||||
loopMax.value = 0
|
||||
loopTimer.value = null
|
||||
|
||||
updataGoods()
|
||||
}
|
||||
|
||||
// 确认选择规格回调
|
||||
function skuConfirm(params) {
|
||||
emit('success', params)
|
||||
@@ -156,7 +193,15 @@ function changeCategory(index) {
|
||||
|
||||
useStorage.set('categorysActive', index)
|
||||
|
||||
productqueryCommodityInfoAjax()
|
||||
goodsList.value = []
|
||||
goodsPage.value = 1
|
||||
finish.value = false
|
||||
currentGoodsIndex.value = 0
|
||||
loopMax.value = 0
|
||||
clearInterval(loopTimer.value)
|
||||
loopTimer.value = null
|
||||
|
||||
updataGoods()
|
||||
}
|
||||
|
||||
// 从本地更新已选择的选项
|
||||
@@ -191,37 +236,129 @@ async function queryCategoryAjax() {
|
||||
// 查询商品信息
|
||||
async function productqueryCommodityInfoAjax() {
|
||||
try {
|
||||
loading.value = true
|
||||
const res = await productqueryCommodityInfo({
|
||||
// loading.value = true
|
||||
const res = await queryNewCommodityInfo({
|
||||
shopId: store.userInfo.shopId,
|
||||
categoryId: categorys.value[categorysActive.value].id,
|
||||
commdityName: commdityName.value,
|
||||
page: 1,
|
||||
pageSize: 500,
|
||||
page: goodsPage.value,
|
||||
pageSize: goodsPageSize.value,
|
||||
masterId: props.masterId
|
||||
})
|
||||
goodsList.value = res
|
||||
loading.value = false
|
||||
if (res.list.length < goodsPageSize.value) {
|
||||
finish.value = true
|
||||
}
|
||||
// loading.value = false
|
||||
|
||||
// if (res.pages > 2 && loopTimer.value == null) {
|
||||
// // 启动循环任务
|
||||
// // loopMax.value = parseInt(res.total / goodsPageSize.value)
|
||||
// loopGetGoods()
|
||||
// }
|
||||
// if (goodsPage.value >= res.pages) {
|
||||
// clearInterval(loopTimer.value)
|
||||
// loopTimer.value = null
|
||||
// }
|
||||
return res
|
||||
} catch (error) {
|
||||
loading.value = false
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
|
||||
// 循环获取商品
|
||||
function loopGetGoods() {
|
||||
loopTimer.value = setInterval(async () => {
|
||||
goodsPage.value++
|
||||
const res = await productqueryCommodityInfoAjax()
|
||||
goodsList.value.push(res.list)
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
// 更新商品数据
|
||||
async function updateData() {
|
||||
localUpdateShopListType()
|
||||
await updateCategoryActive()
|
||||
await queryCategoryAjax()
|
||||
await productqueryCommodityInfoAjax()
|
||||
updataGoods()
|
||||
}
|
||||
|
||||
// 更新商品数据
|
||||
async function updataGoods() {
|
||||
if (!goodsList.value.length) {
|
||||
const res = await productqueryCommodityInfoAjax()
|
||||
goodsList.value.push(res.list)
|
||||
|
||||
if (!res.isLastPage) {
|
||||
goodsPage.value++
|
||||
const res2 = await productqueryCommodityInfoAjax()
|
||||
goodsList.value.push(res2.list)
|
||||
}
|
||||
searchLoading.value = false
|
||||
} else {
|
||||
goodsPage.value = currentGoodsIndex.value + 1
|
||||
// console.log('更新第二页数据', goodsPage.value);
|
||||
const res = await productqueryCommodityInfoAjax()
|
||||
goodsList.value[currentGoodsIndex.value] = res.list
|
||||
searchLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 轮播图开始滑动
|
||||
const onSlideChange = _.debounce(async function (e) {
|
||||
if (e.activeIndex == e.previousIndex) return
|
||||
if (e.activeIndex > e.previousIndex) {
|
||||
// console.log('向下滑动');
|
||||
{
|
||||
goodsPage.value++
|
||||
const res = await productqueryCommodityInfoAjax()
|
||||
res.list.length && goodsList.value.push(res.list)
|
||||
}
|
||||
|
||||
{
|
||||
goodsPage.value++
|
||||
const res = await productqueryCommodityInfoAjax()
|
||||
res.list.length && goodsList.value.push(res.list)
|
||||
}
|
||||
// goodsList.value.shift()
|
||||
} else {
|
||||
// console.log('向上滑动');
|
||||
// goodsPage.value--
|
||||
// const res = await productqueryCommodityInfoAjax()
|
||||
// goodsList.value.unshift(res)
|
||||
// goodsList.value.pop()
|
||||
}
|
||||
currentGoodsIndex.value = e.activeIndex
|
||||
}, 500)
|
||||
|
||||
// 订单已结算,清楚商品所有数字
|
||||
function clearDot() {
|
||||
goodsList.value.map(item => {
|
||||
item.map(val => {
|
||||
val.orderCount = 0
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
updateData
|
||||
updateData,
|
||||
clearDot
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
localUpdateShopListType()
|
||||
await updateCategoryActive()
|
||||
await queryCategoryAjax()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.swiper_box {
|
||||
height: 100%;
|
||||
|
||||
.slide_item {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.loading_wrap {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@@ -325,10 +462,11 @@ defineExpose({
|
||||
}
|
||||
|
||||
.shop_list {
|
||||
max-height: calc(100vh - 40px - 80px - 40px);
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
// max-height: calc(100vh - 40px - 80px - 40px);
|
||||
height: calc(100vh - 40px - 80px - 28px);
|
||||
// overflow-y: auto;
|
||||
// display: flex;
|
||||
// flex-wrap: wrap;
|
||||
padding: 0 10px;
|
||||
|
||||
&.img {
|
||||
@@ -338,11 +476,14 @@ defineExpose({
|
||||
}
|
||||
|
||||
.item_wrap {
|
||||
float: left;
|
||||
width: 20%;
|
||||
height: 33.333%;
|
||||
padding: 0 5px;
|
||||
padding-bottom: 10px;
|
||||
|
||||
.item {
|
||||
height: 100%;
|
||||
border: 1px solid #ececec;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
@@ -366,7 +507,7 @@ defineExpose({
|
||||
|
||||
.cover {
|
||||
width: 100%;
|
||||
padding-bottom: 100%;
|
||||
height: 60%;
|
||||
position: relative;
|
||||
|
||||
.el_img {
|
||||
@@ -381,8 +522,10 @@ defineExpose({
|
||||
|
||||
.name {
|
||||
padding: 0 10px;
|
||||
height: 40px;
|
||||
margin-top: 20px;
|
||||
height: 20%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// margin-top: 20px;
|
||||
|
||||
span {
|
||||
font-weight: bold;
|
||||
@@ -394,6 +537,7 @@ defineExpose({
|
||||
}
|
||||
|
||||
.price {
|
||||
height: 20%;
|
||||
padding: 6px 10px;
|
||||
background-color: var(--primary-color);
|
||||
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
<!-- 结算订单 -->
|
||||
|
||||
<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="cart_list">
|
||||
<div class="nav_wrap card">
|
||||
@@ -16,11 +11,12 @@
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="master_id">{{ props.masterId }}</div>
|
||||
<div class="master_id">
|
||||
<span>{{ props.masterId }}</span>
|
||||
<span class="member_info" v-if="memberInfo.telephone">会员:{{ memberInfo.telephone }}</span>
|
||||
</div>
|
||||
<div class="btm">
|
||||
<span class="p"
|
||||
>服务员:{{ store.userInfo.shopName || "暂无" }}</span
|
||||
>
|
||||
<span class="p">服务员:{{ store.userInfo.shopName || "暂无" }}</span>
|
||||
<span class="t">{{
|
||||
props.orderInfo.createdAt &&
|
||||
dayjs(props.orderInfo.createdAt).format("MM-DD HH:mm")
|
||||
@@ -28,10 +24,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="list_wrap card"
|
||||
style="margin-top: var(--el-font-size-base)"
|
||||
>
|
||||
<div class="list_wrap card" style="margin-top: var(--el-font-size-base)">
|
||||
<div class="item" v-for="item in props.cart" :key="item.id">
|
||||
<div class="top">
|
||||
<span class="name">{{ item.name }}</span>
|
||||
@@ -48,11 +41,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="packge_Wrap" v-if="item.isPack == 'true'">
|
||||
<div
|
||||
class="icon_item"
|
||||
v-if="item.isPack == 'true'"
|
||||
@click="giftPackHandle('isPack', item)"
|
||||
>
|
||||
<div class="icon_item" v-if="item.isPack == 'true'" @click="giftPackHandle('isPack', item)">
|
||||
<el-icon class="icon" style="color: var(--primary-color)">
|
||||
<Box />
|
||||
</el-icon>
|
||||
@@ -63,45 +52,35 @@
|
||||
<div class="footer">
|
||||
<!-- <el-button icon="Edit"></el-button> -->
|
||||
<div class="button">
|
||||
<el-checkbox
|
||||
v-model="isPrint"
|
||||
border
|
||||
label="打印结算小票"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<el-checkbox v-model="isPrint" border label="打印结算小票" style="width: 100%" />
|
||||
</div>
|
||||
<div class="print">
|
||||
<el-button
|
||||
type="primary"
|
||||
v-loading="printLoading"
|
||||
@click="printHandle"
|
||||
>打印预结单</el-button
|
||||
>
|
||||
<el-button type="primary" v-loading="printLoading" @click="printHandle">打印预结单</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pay_wrap">
|
||||
<payCard
|
||||
:amount="props.amount"
|
||||
:orderId="props.orderInfo.id"
|
||||
@paySuccess="paySuccess"
|
||||
/>
|
||||
<payCard :amount="props.amount" :member="props.member" :orderId="props.orderInfo.id" @paySuccess="paySuccess" />
|
||||
</div>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import _ from 'lodash'
|
||||
import { onMounted, ref } from "vue";
|
||||
import { useUser } from "@/store/user.js";
|
||||
import payCard from "@/components/payCard/payCard.vue";
|
||||
import { print } from "@/api/pay";
|
||||
import { bySubType } from "@/api/device";
|
||||
import { orderfindOrder } from '@/api/order/index.js'
|
||||
import { ElMessage } from "element-plus";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
import useStorage from '@/utils/useStorage'
|
||||
import { ipcRenderer } from "electron";
|
||||
|
||||
import { usePrint } from '@/store/print.js'
|
||||
const printStore = usePrint()
|
||||
|
||||
const store = useUser();
|
||||
|
||||
const emit = defineEmits("paySuccess");
|
||||
@@ -130,81 +109,121 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
member: {
|
||||
type: Object,
|
||||
default: {}
|
||||
}
|
||||
});
|
||||
|
||||
const isPrint = ref(true);
|
||||
|
||||
const printList = ref([]);
|
||||
|
||||
// 获取打印机状态
|
||||
async function bySubTypeAjax() {
|
||||
// 预打印操作
|
||||
const printHandle = _.throttle(async function () {
|
||||
try {
|
||||
const res = await bySubType({
|
||||
shopId: store.userInfo.shopId,
|
||||
contentType: "local",
|
||||
subType: "cash",
|
||||
});
|
||||
printList.value = res;
|
||||
if (!isPrint.value) return;
|
||||
const data = {
|
||||
shop_name: store.userInfo.merchantName,
|
||||
carts: props.cart,
|
||||
amount: props.amount,
|
||||
remark: props.remark,
|
||||
orderInfo: props.orderInfo,
|
||||
createdAt: dayjs(props.orderInfo.createdAt).format(
|
||||
"YYYY-MM-DD HH:mm:ss"
|
||||
),
|
||||
printTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
||||
};
|
||||
printStore.labelPrint(data)
|
||||
|
||||
try {
|
||||
printLoading.value = true;
|
||||
await print({
|
||||
type: "normal",
|
||||
ispre: true,
|
||||
orderId: props.orderInfo.id,
|
||||
});
|
||||
printLoading.value = false;
|
||||
// ElMessage.success("打印成功");
|
||||
} catch (error) {
|
||||
printLoading.value = false;
|
||||
console.log(error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
}, 1500, { leading: true, trailing: false })
|
||||
|
||||
async function printHandle() {
|
||||
// try {
|
||||
// if (!isPrint.value) return;
|
||||
// if (printList.value.length) {
|
||||
// const data = {
|
||||
// shop_name: store.userInfo.merchantName,
|
||||
// carts: props.cart,
|
||||
// amount: props.amount,
|
||||
// remark: props.remark,
|
||||
// orderInfo: props.orderInfo,
|
||||
// deviceName: printList.value[0].config.deviceName,
|
||||
// createdAt: dayjs(props.orderInfo.createdAt).format(
|
||||
// "YYYY-MM-DD HH:mm:ss"
|
||||
// ),
|
||||
// printTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
||||
// };
|
||||
// ipcRenderer.send("printerInfoSync", JSON.stringify(data));
|
||||
// } else {
|
||||
// ElMessage.error("您还没有添加打印设备");
|
||||
// }
|
||||
// } catch (error) {
|
||||
// console.log(error);
|
||||
// }
|
||||
// 打印订单标签
|
||||
async function printOrderLable() {
|
||||
try {
|
||||
printLoading.value = true;
|
||||
await print({
|
||||
type: "normal",
|
||||
ispre: true,
|
||||
orderId: props.orderInfo.id,
|
||||
});
|
||||
printLoading.value = false;
|
||||
ElMessage.success("打印成功");
|
||||
const res = await orderfindOrder({
|
||||
shopId: store.userInfo.shopId,
|
||||
status: '',
|
||||
size: 10,
|
||||
page: 1,
|
||||
orderNo: props.orderInfo.orderNo
|
||||
})
|
||||
|
||||
const printLabelOrder = res.list[0]
|
||||
|
||||
const data = {
|
||||
shop_name: store.userInfo.merchantName,
|
||||
carts: [],
|
||||
orderInfo: printLabelOrder,
|
||||
outNumber: printLabelOrder.outNumber,
|
||||
createdAt: dayjs(printLabelOrder.createdAt).format(
|
||||
"YYYY-MM-DD HH:mm:ss"
|
||||
)
|
||||
}
|
||||
printLabelOrder.skuInfos.map(item => {
|
||||
data.carts.push(
|
||||
{
|
||||
categoryId: item.categoryId,
|
||||
name: item.productName,
|
||||
number: item.num,
|
||||
skuName: item.productSkuName
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
// console.log('重打标签小票', data);
|
||||
printStore.labelPrint(data)
|
||||
} catch (error) {
|
||||
printLoading.value = false;
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
// 订单已支付
|
||||
function paySuccess() {
|
||||
useStorage.del('memberInfo')
|
||||
dialogVisible.value = false;
|
||||
printHandle();
|
||||
printOrderLable()
|
||||
emit("paySuccess");
|
||||
}
|
||||
|
||||
function show() {
|
||||
dialogVisible.value = true;
|
||||
getLocalMemberInfo()
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
show,
|
||||
});
|
||||
|
||||
|
||||
const memberInfo = ref('')
|
||||
|
||||
// 从本地获取会员信息
|
||||
function getLocalMemberInfo() {
|
||||
let localMemberInfo = useStorage.get('memberInfo')
|
||||
if (localMemberInfo && localMemberInfo.telephone) {
|
||||
memberInfo.value = localMemberInfo
|
||||
} else {
|
||||
memberInfo.value = ''
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
bySubTypeAjax();
|
||||
getLocalMemberInfo()
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -254,6 +273,14 @@ onMounted(() => {
|
||||
font-size: calc(var(--el-font-size-base) + 10px);
|
||||
border-bottom: 1px solid #ececec;
|
||||
padding: $padding 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.member_info {
|
||||
color: #999;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.btm {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<div class="number" @click="takeFoodCodeRef.show()">
|
||||
<el-text class="t">{{ masterId }}</el-text>
|
||||
</div>
|
||||
<div class="select_user" @click="fastCashierRef.show()">
|
||||
<div class="select_user" @click="fastCashierRef.show()" v-if="!memberInfo.telephone">
|
||||
<el-icon class="icon">
|
||||
<WalletFilled />
|
||||
</el-icon>
|
||||
@@ -20,25 +20,20 @@
|
||||
<ArrowRight />
|
||||
</el-icon>
|
||||
</div>
|
||||
<!-- <div class="select_user" @click="membershow = true">
|
||||
<div class="select_user" v-else @click="clearMember">
|
||||
<el-icon class="icon">
|
||||
<UserFilled />
|
||||
</el-icon>
|
||||
<el-text class="t">选择会员</el-text>
|
||||
<el-text class="t">{{ memberInfo.telephone }}</el-text>
|
||||
<el-icon class="arrow">
|
||||
<ArrowRight />
|
||||
<Close />
|
||||
</el-icon>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="shop_operation" v-loading="cartLoading">
|
||||
<div class="shop_list">
|
||||
<div
|
||||
class="item"
|
||||
:class="{ active: cartListActive == index }"
|
||||
v-for="(item, index) in cartList"
|
||||
:key="item.id"
|
||||
@click="selectCartItemHandle(item, index)"
|
||||
>
|
||||
<div class="item" :class="{ active: cartListActive == index }" v-for="(item, index) in cartList"
|
||||
:key="item.id" @click="selectCartItemHandle(item, index)">
|
||||
<div class="name_wrap">
|
||||
<span>{{ item.name }}</span>
|
||||
<span>¥{{ item.salePrice }}</span>
|
||||
@@ -50,20 +45,12 @@
|
||||
</div>
|
||||
<div class="num">
|
||||
<div class="left">
|
||||
<div
|
||||
class="icon_item"
|
||||
v-if="item.isGift == 'true'"
|
||||
@click="giftPackHandle('isGift', item)"
|
||||
>
|
||||
<div class="icon_item" v-if="item.isGift == 'true'" @click="giftPackHandle('isGift', item)">
|
||||
<el-icon class="icon">
|
||||
<ShoppingBag />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div
|
||||
class="icon_item"
|
||||
v-if="item.isPack == 'true'"
|
||||
@click="giftPackHandle('isPack', item)"
|
||||
>
|
||||
<div class="icon_item" v-if="item.isPack == 'true'" @click="giftPackHandle('isPack', item)">
|
||||
<el-icon class="icon" style="color: var(--primary-color)">
|
||||
<Box />
|
||||
</el-icon>
|
||||
@@ -77,13 +64,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<!-- 购物车操作栏 -->
|
||||
<cartOperation
|
||||
:item="cartList[cartListActive]"
|
||||
@confirm="(res) => addCart(res, 'edit')"
|
||||
@delete="delCartHandle"
|
||||
@pending="pendingCart"
|
||||
@clearCart="clearCartHandle"
|
||||
/>
|
||||
<cartOperation :item="cartList[cartListActive]" @confirm="(res) => addCart(res, 'edit')" @delete="delCartHandle"
|
||||
@pending="pendingCart" @clearCart="clearCartHandle" />
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div class="top">
|
||||
@@ -97,26 +79,17 @@
|
||||
<el-text class="t">打包(¥{{ cartInfo.packAmount || 0 }})</el-text>
|
||||
</div>
|
||||
<div class="num-wrap">
|
||||
<el-text
|
||||
>共{{ cartInfo.productNum || 0 }}种商品,{{
|
||||
cartInfo.productSum || 0
|
||||
}}件</el-text
|
||||
>
|
||||
<el-text>共{{ cartInfo.productNum || 0 }}种商品,{{
|
||||
cartInfo.productSum || 0
|
||||
}}件</el-text>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btm">
|
||||
<el-button icon="Edit" @click="remarkRef.show()"></el-button>
|
||||
<div class="button">
|
||||
<el-button
|
||||
type="primary"
|
||||
style="width: 100%"
|
||||
:disabled="!cartList.length"
|
||||
v-loading="createOrderLoading"
|
||||
@click="createOrderHandle"
|
||||
>
|
||||
<span v-if="!createOrderLoading"
|
||||
>结算(¥{{ cartInfo.totalAmount || 0 }})</span
|
||||
>
|
||||
<el-button type="primary" style="width: 100%" :disabled="!cartList.length" v-loading="createOrderLoading"
|
||||
@click="createOrderHandle">
|
||||
<span v-if="!createOrderLoading">结算(¥{{ cartInfo.totalAmount || 0 }})</span>
|
||||
<span v-else>下单中...</span>
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -133,32 +106,15 @@
|
||||
<remarkModal ref="remarkRef" @success="(e) => (remark = e)" />
|
||||
<!-- 修改取餐号 -->
|
||||
<takeFoodCode />
|
||||
<el-drawer
|
||||
v-model="membershow"
|
||||
:with-header="true"
|
||||
size="90%"
|
||||
title="选择会员"
|
||||
>
|
||||
<el-drawer v-model="membershow" :with-header="true" size="90%" title="选择会员">
|
||||
<member :membershow="'1'"></member>
|
||||
</el-drawer>
|
||||
<takeFoodCode
|
||||
ref="takeFoodCodeRef"
|
||||
title="修改取餐号"
|
||||
placeholder="请输入取餐号"
|
||||
@success="takeFoodCodeSuccess"
|
||||
/>
|
||||
<takeFoodCode ref="takeFoodCodeRef" title="修改取餐号" placeholder="请输入取餐号" @success="takeFoodCodeSuccess" />
|
||||
<!-- 结算订单 -->
|
||||
<settleAccount
|
||||
ref="settleAccountRef"
|
||||
:cart="cartList"
|
||||
:amount="cartInfo.totalAmount"
|
||||
:remark="remark"
|
||||
:masterId="masterId"
|
||||
:orderInfo="orderInfo"
|
||||
@paySuccess="createCodeAjax(1)"
|
||||
/>
|
||||
<settleAccount ref="settleAccountRef" :cart="cartList" :amount="cartInfo.totalAmount" :remark="remark"
|
||||
:masterId="masterId" :orderInfo="orderInfo" :member="memberInfo" @paySuccess="createCodeAjax(1)" />
|
||||
<!-- 快捷收银 -->
|
||||
<fastCashier ref="fastCashierRef" />
|
||||
<fastCashier ref="fastCashierRef" type="0" />
|
||||
<!-- 挂起订单 -->
|
||||
<pendingCartModal ref="pendingCartModalRef" @select="pendingCartHandle" />
|
||||
</template>
|
||||
@@ -170,6 +126,7 @@ export default {
|
||||
</script>
|
||||
<script setup>
|
||||
import { onMounted, ref } from "vue";
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useUser } from "@/store/user.js";
|
||||
import remarkModal from "@/components/remarkModal.vue";
|
||||
import takeFoodCode from "@/components/takeFoodCode.vue";
|
||||
@@ -177,6 +134,7 @@ import cartOperation from "@/views/home/components/cartOperation.vue";
|
||||
import settleAccount from "@/views/home/components/settleAccount.vue";
|
||||
import fastCashier from "@/views/home/components/fastCashier.vue";
|
||||
import pendingCartModal from "@/views/home/components/pendingCartModal.vue";
|
||||
import useStorage from '@/utils/useStorage'
|
||||
|
||||
import {
|
||||
createCart,
|
||||
@@ -193,6 +151,8 @@ import {
|
||||
import goods from "@/views/home/components/goods.vue";
|
||||
import member from "@/views/member/index.vue";
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const membershow = ref(false);
|
||||
const store = useUser();
|
||||
const remarkRef = ref(null);
|
||||
@@ -213,6 +173,8 @@ const cartLoading = ref(false);
|
||||
const orderInfo = ref({});
|
||||
const createOrderLoading = ref(false);
|
||||
|
||||
const memberInfo = ref({})
|
||||
|
||||
// 取餐码
|
||||
const masterId = ref("");
|
||||
|
||||
@@ -245,6 +207,9 @@ async function clearCartHandle() {
|
||||
masterId: masterId.value,
|
||||
});
|
||||
queryCartAjax();
|
||||
|
||||
// 清除商品所有红点
|
||||
goodsRef.value.clearDot()
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
@@ -405,13 +370,36 @@ async function createCodeAjax(type = "0") {
|
||||
});
|
||||
masterId.value = res.code;
|
||||
queryCartAjax();
|
||||
getLocalMemberInfo()
|
||||
|
||||
if (type == 1) {
|
||||
// 结算订单 清楚商品所有红点
|
||||
goodsRef.value.clearDot()
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
// 从本地获取会员信息
|
||||
function getLocalMemberInfo() {
|
||||
let localMemberInfo = useStorage.get('memberInfo')
|
||||
if (localMemberInfo && localMemberInfo.telephone) {
|
||||
memberInfo.value = localMemberInfo
|
||||
} else {
|
||||
memberInfo.value = {}
|
||||
}
|
||||
}
|
||||
|
||||
// 清除本地会员
|
||||
function clearMember() {
|
||||
useStorage.del('memberInfo')
|
||||
getLocalMemberInfo()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
createCodeAjax();
|
||||
getLocalMemberInfo()
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -452,8 +440,9 @@ onMounted(() => {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: var(--el-color-info-light-7);
|
||||
padding-left: var(--el-font-size-base);
|
||||
// padding-left: var(--el-font-size-base);
|
||||
|
||||
.t {
|
||||
font-size: var(--el-font-size-base);
|
||||
|
||||
@@ -1,20 +1,271 @@
|
||||
<template>
|
||||
<el-button @click="chooseSerial">打印</el-button>
|
||||
<!-- <el-button @click="chooseSerial">获取串口列表</el-button> -->
|
||||
<el-button @click="initWebSocket()">连接ws</el-button>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import _ from 'lodash'
|
||||
import { bySubType } from "@/api/device";
|
||||
import { ElMessage } from "element-plus";
|
||||
import dayjs from 'dayjs'
|
||||
import { ipcRenderer } from 'electron'
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { useUser } from "@/store/user.js";
|
||||
import useStorage from '@/utils/useStorage'
|
||||
const store = useUser();
|
||||
|
||||
// 小票打印机列表
|
||||
const printList = ref([]);
|
||||
// 标签打印机列表
|
||||
const printLabelList = ref([]);
|
||||
const localPrintList = ref([])
|
||||
|
||||
// 获取打印机状态
|
||||
async function bySubTypeAjax() {
|
||||
try {
|
||||
const res1 = await bySubType({
|
||||
shopId: store.userInfo.shopId,
|
||||
contentType: "local",
|
||||
subType: "cash",
|
||||
});
|
||||
const res2 = await bySubType({
|
||||
shopId: store.userInfo.shopId,
|
||||
contentType: "local",
|
||||
subType: "label",
|
||||
});
|
||||
printList.value = res1;
|
||||
printLabelList.value = res2;
|
||||
} 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
|
||||
}
|
||||
}
|
||||
|
||||
// 打印小票
|
||||
function printBill(props) {
|
||||
if (!checkLocalPrint(printLabelList.value[0].config.deviceName)) {
|
||||
ElMessage.error("本地打印机无法使用,请检查打印机是否正确连接");
|
||||
} else {
|
||||
const data = {
|
||||
shop_name: store.userInfo.merchantName,
|
||||
carts: props.carts,
|
||||
amount: props.amount,
|
||||
remark: props.remark,
|
||||
orderInfo: props.orderInfo,
|
||||
deviceName: printList.value[0].config.deviceName,
|
||||
createdAt: dayjs(props.orderInfo.createdAt).format(
|
||||
"YYYY-MM-DD HH:mm:ss"
|
||||
),
|
||||
printTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
||||
};
|
||||
ipcRenderer.send("printerInfoSync", JSON.stringify(data));
|
||||
}
|
||||
}
|
||||
|
||||
// 检测是否打印标签小票
|
||||
function checkLabelPrint(props) {
|
||||
if (!checkLocalPrint(printLabelList.value[0].config.deviceName)) {
|
||||
ElMessage.error("本地打印机无法使用,请检查打印机是否正确连接");
|
||||
} else {
|
||||
let pids = printLabelList.value[0].config.categoryList.map(item => item.id)
|
||||
let labelList = []
|
||||
props.carts.map(item => {
|
||||
if (pids.some(el => el == item.categoryId)) {
|
||||
for (let i = 0; i < item.number; i++) {
|
||||
labelList.push(
|
||||
{
|
||||
outNumber: props.outNumber,
|
||||
name: item.name,
|
||||
skuName: item.skuName,
|
||||
masterId: props.orderInfo.tableName,
|
||||
deviceName: printLabelList.value[0].config.deviceName,
|
||||
createdAt: dayjs(props.createdAt).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
printLabel(labelList)
|
||||
}
|
||||
}
|
||||
|
||||
// 打印标签
|
||||
let labelCount = ref(0)
|
||||
let labelPrintTimer = ref(null)
|
||||
function printLabel(list) {
|
||||
console.log(list);
|
||||
if (!checkLocalPrint(printLabelList.value[0].config.deviceName)) {
|
||||
ElMessage.error("本地打印机无法使用,请检查打印机是否正确连接");
|
||||
} else {
|
||||
labelPrintTimer.value = setInterval(() => {
|
||||
// console.log('labelCount', labelCount.value);
|
||||
list[labelCount.value].count = `${list.length - labelCount.value}/${list.length}`
|
||||
ipcRenderer.send('printerTagSync', JSON.stringify(list[labelCount.value]))
|
||||
labelCount.value++
|
||||
if (labelCount.value > list.length - 1) {
|
||||
clearInterval(labelPrintTimer.value)
|
||||
labelPrintTimer.value = null
|
||||
labelCount.value = 0
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
|
||||
let ws = ref(null)
|
||||
let wsIsClose = ref(false)
|
||||
// 初始化websocket
|
||||
function initWebSocket(wsUrl = 'wss://wxcashiertest.sxczgkj.cn/client') {
|
||||
ws.value = new WebSocket(wsUrl);
|
||||
console.log("websocket:", ws.value);
|
||||
|
||||
ws.value.onopen = function () {
|
||||
console.log('wss连接成功');
|
||||
// 清除心跳
|
||||
clearInterval(heartbeatTimer.value)
|
||||
heartbeatTimer.value = null
|
||||
startheartbeat()
|
||||
|
||||
// 清除重连
|
||||
clearInterval(reConnectTimer.value)
|
||||
reConnectTimer.value = null
|
||||
reConnectCount.value = 0
|
||||
|
||||
ws.value.send(JSON.stringify({
|
||||
type: "connect",
|
||||
shopId: store.userInfo.shopId,
|
||||
clientId: useStorage.get('uuid')
|
||||
}))
|
||||
};
|
||||
|
||||
// 接收消息
|
||||
ws.value.onmessage = function (e) {
|
||||
// websocketonmessage(e);
|
||||
let data = JSON.parse(e.data)
|
||||
if (data.type == 'order') {
|
||||
console.log('接收消息', data);
|
||||
// 接收订单消息,打印小票
|
||||
// printBill(data)
|
||||
|
||||
// 检测是否需要打印标签小票
|
||||
checkLabelPrint(data)
|
||||
}
|
||||
};
|
||||
|
||||
// 连接发生错误
|
||||
ws.value.onerror = function () {
|
||||
console.log("WebSocket连接发生错误");
|
||||
|
||||
// 清除心跳
|
||||
clearInterval(heartbeatTimer.value)
|
||||
heartbeatTimer.value = null
|
||||
|
||||
// 手动关闭后不在执行自动连接任务
|
||||
if (!wsIsClose.value) reConnect(wsUrl);
|
||||
};
|
||||
|
||||
// 关闭
|
||||
ws.value.onclose = function (e) {
|
||||
console.log('ws关闭了', e);
|
||||
|
||||
// 清除心跳
|
||||
clearInterval(heartbeatTimer.value)
|
||||
heartbeatTimer.value = null
|
||||
|
||||
// 手动关闭后不在执行自动连接任务
|
||||
if (!wsIsClose.value) reConnect(wsUrl);
|
||||
};
|
||||
}
|
||||
|
||||
// 启动心跳连接
|
||||
let heartbeatTimer = ref(null)
|
||||
function startheartbeat() {
|
||||
heartbeatTimer.value = setInterval(() => {
|
||||
ws.value.send(JSON.stringify({ type: 'heartbeat' }))
|
||||
}, 10000)
|
||||
}
|
||||
|
||||
// 重连最大次数5次
|
||||
let reConnectCount = ref(0)
|
||||
let reConnectTimer = ref(null)
|
||||
function reConnect(wsUrl) {
|
||||
if (reConnectTimer.value != null) return
|
||||
reConnectTimer.value = setInterval(() => {
|
||||
// 自动连接超过5次不在连接,需手动出发
|
||||
console.log('reConnectCount.value===', reConnectCount.value);
|
||||
if (reConnectCount.value >= 5) {
|
||||
console.log('重连超过5次,不在连接');
|
||||
clearInterval(reConnectTimer.value)
|
||||
reConnectTimer.value = null
|
||||
reConnectCount.value = 0
|
||||
wsIsClose.value = true
|
||||
ws.value.close()
|
||||
} else {
|
||||
reConnectCount.value++
|
||||
initWebSocket(wsUrl)
|
||||
}
|
||||
}, 5000)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 打印标签小票
|
||||
const printTag = () => {
|
||||
ipcRenderer.send('printerTagSync', JSON.stringify({
|
||||
deviceName: 'Xprinter XP-365B123'
|
||||
}))
|
||||
}
|
||||
|
||||
//选择串口设备
|
||||
const chooseSerial = async () => {
|
||||
let printNum = localStorage.getItem('printNum')
|
||||
if (!printNum) {
|
||||
printNum = 1
|
||||
localStorage.setItem('printNum', printNum)
|
||||
} else {
|
||||
printNum++
|
||||
localStorage.setItem('printNum', printNum)
|
||||
}
|
||||
ipcRenderer.send('printStart', printNum)
|
||||
// let printNum = localStorage.getItem('printNum')
|
||||
// if (!printNum) {
|
||||
// printNum = 1
|
||||
// localStorage.setItem('printNum', printNum)
|
||||
// } else {
|
||||
// printNum++
|
||||
// localStorage.setItem('printNum', printNum)
|
||||
// }
|
||||
// ipcRenderer.send('printStart', printNum)
|
||||
// ipcRenderer.send('getSerialPort')
|
||||
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
ipcRenderer.on('seriaportList', (e, a) => {
|
||||
console.log('seriaportList', a);
|
||||
})
|
||||
|
||||
getPrintList();
|
||||
bySubTypeAjax();
|
||||
initWebSocket()
|
||||
})
|
||||
</script>
|
||||
@@ -51,6 +51,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
import packageData from '../../package.json'
|
||||
|
||||
import logo from "@/assets/logo.png";
|
||||
@@ -58,8 +59,9 @@ import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { reactive, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { ipcRenderer } from "electron";
|
||||
|
||||
import { RandomNumBoth } from '@/utils'
|
||||
import useStorage from '@/utils/useStorage'
|
||||
import { douyincheckIn } from '@/api/group'
|
||||
|
||||
import { useUser } from "@/store/user.js";
|
||||
const store = useUser();
|
||||
@@ -106,7 +108,13 @@ const submitHandle = () => {
|
||||
formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
loading.value = true;
|
||||
store.userlogin(form).then((res) => {
|
||||
store.userlogin(form).then(async (res) => {
|
||||
// const douyin = await douyincheckIn({
|
||||
// token: res.token,
|
||||
// loginName: res.loginName,
|
||||
// clientType: 'pc'
|
||||
// })
|
||||
// useStorage.set('douyin', douyin.userInfo)
|
||||
ElMessage.success("登录成功");
|
||||
setTimeout(() => {
|
||||
router.replace({
|
||||
|
||||
@@ -3,19 +3,25 @@
|
||||
<div class="dialog_footer" v-for="(item, index) in props.flowingwater.list" :key="index">
|
||||
<div class="dialog_footer_left">
|
||||
<span>{{ item.biz_name }}</span>
|
||||
<span>{{ dayjs(item.create_time).format("YYYY-MM-DD") }}</span>
|
||||
<span>{{ dayjs(item.create_time).format("YYYY-MM-DD HH:mm:ss") }}</span>
|
||||
</div>
|
||||
<div class="dialog_footer_right">
|
||||
<span>{{ item.balance }}</span>
|
||||
<span>{{ item.amount }}</span>
|
||||
<span :class="{ active: item.type == '+' }">
|
||||
<template v-if="item.type == '+'">+</template>
|
||||
<template v-else>-</template>
|
||||
¥{{ formatDecimal(item.amount) }}
|
||||
</span>
|
||||
<span>余额:¥{{ formatDecimal(item.balance) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-empty description="暂无数据" v-if="!props.flowingwater.list.length" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { dayjs } from 'element-plus'
|
||||
import { formatDecimal } from '@/utils/index'
|
||||
|
||||
const props = defineProps({
|
||||
flowingwater: {
|
||||
@@ -29,6 +35,7 @@ const props = defineProps({
|
||||
.box {
|
||||
height: 400px;
|
||||
overflow: auto;
|
||||
|
||||
.dialog_footer:nth-child(1) {
|
||||
margin-top: 0;
|
||||
}
|
||||
@@ -38,7 +45,7 @@ const props = defineProps({
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #ccc;
|
||||
border-bottom: 1px solid #ececec;
|
||||
padding-bottom: 6px;
|
||||
|
||||
.dialog_footer_left {
|
||||
@@ -54,7 +61,8 @@ const props = defineProps({
|
||||
|
||||
span:nth-child(2) {
|
||||
margin-top: 10px;
|
||||
color: #333;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,14 +72,18 @@ const props = defineProps({
|
||||
align-items: flex-end;
|
||||
|
||||
span:nth-child(1) {
|
||||
color: #fc3d3d;
|
||||
font-size: 16px;
|
||||
|
||||
&.active {
|
||||
color: #fc3d3d;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
span:nth-child(2) {
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
55
src/views/member/components/userCharge.vue
Normal file
55
src/views/member/components/userCharge.vue
Normal file
@@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<el-drawer size="100%" :with-header="false" direction="btt" v-model="dialogVisible">
|
||||
<div class="drawer_wrap">
|
||||
<div class="pay_wrap">
|
||||
<fastPayCard ref="fastPayCardRef" type="1" :userInfo="userInfo" @paySuccess="paySuccess"
|
||||
@close="dialogVisible = false" />
|
||||
</div>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import fastPayCard from "@/components/fastPayCard.vue";
|
||||
|
||||
const props = defineProps({
|
||||
userInfo: {
|
||||
type: Object,
|
||||
default: {}
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(["paySuccess"]);
|
||||
|
||||
const dialogVisible = ref(false);
|
||||
const fastPayCardRef = ref(null);
|
||||
|
||||
// 订单已支付
|
||||
function paySuccess() {
|
||||
dialogVisible.value = false;
|
||||
emit("paySuccess");
|
||||
}
|
||||
|
||||
function show() {
|
||||
dialogVisible.value = true;
|
||||
fastPayCardRef.value.reset();
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
show,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.drawer_wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
padding: var(--el-font-size-base) 0;
|
||||
|
||||
.pay_wrap {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -3,12 +3,13 @@
|
||||
<div class="orderbox_left">
|
||||
<div class="demo_tabs" v-if="props.membershow == '0'">
|
||||
<div class="demo_tabs_div">
|
||||
<el-input v-model="tableData.phone" placeholder="请输入手机号或编号" @input="inputChange" clearable />
|
||||
<el-input v-model="tableData.phone" placeholder="请输入手机号" @input="inputChange" clearable @focus="
|
||||
global.updateData(false)" @blur="global.updateData(true)" />
|
||||
<el-button style="margin-left: 10px;" type="primary" @click="memberaddshow = true">添加</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table :data="tableData.list" style="width: 100%;margin-top: 10px;height:80%;"
|
||||
:row-class-name="tableRowClassName" @cell-click="cellclicktableData">
|
||||
:row-class-name="tableRowClassName" @cell-click="cellclicktableData" v-loading="loading">
|
||||
<el-table-column prop="name" label="昵称" />
|
||||
<el-table-column prop="telephone" label="手机" width="200px" />
|
||||
<el-table-column prop="code" label="编号" width="150px" />
|
||||
@@ -27,15 +28,15 @@
|
||||
</div>
|
||||
<div class="orderbox_right_topdiv">
|
||||
<span>手机号码:</span>
|
||||
<span>{{ tableData.list.length != 0 ? tableData.list[datarow].telephone : '无' }}</span>
|
||||
<span>{{ tableData.list.length != 0 ? tableData.list[datarow].telephone : '无' }}</span>
|
||||
</div>
|
||||
<div class="orderbox_right_topdiv">
|
||||
<span>会员编号:</span>
|
||||
<span>{{ tableData.list.length != 0 ? tableData.list[datarow].code : '无' }}</span>
|
||||
<span>{{ tableData.list.length != 0 ? tableData.list[datarow].code : '无' }}</span>
|
||||
</div>
|
||||
<div class="orderbox_right_topdiv">
|
||||
<span>会员等级:</span>
|
||||
<span>{{ tableData.list.length != 0 ? tableData.list[datarow].level : '无' }}</span>
|
||||
<span>{{ tableData.list.length != 0 ? tableData.list[datarow].level : '无' }}</span>
|
||||
</div>
|
||||
<div class="orderbox_right_top_item">
|
||||
<div class="orderbox_right_top_item_one">
|
||||
@@ -44,7 +45,8 @@
|
||||
</el-icon>
|
||||
<span class="orderbox_right_top_item_onespan">会员积分</span>
|
||||
</div>
|
||||
<div class="orderbox_right_top_item_tow">{{ tableData.list.length != 0 ? tableData.list[datarow].levelConsume : '无' }}</div>
|
||||
<div class="orderbox_right_top_item_tow">{{ tableData.list.length != 0 ?
|
||||
tableData.list[datarow].levelConsume : '无' }}</div>
|
||||
</div>
|
||||
<div class="orderbox_right_top_item" @click="stored = true">
|
||||
<div class="orderbox_right_top_item_one">
|
||||
@@ -54,7 +56,7 @@
|
||||
<span class="orderbox_right_top_item_onespan">储值余额</span>
|
||||
</div>
|
||||
<div class="orderbox_right_top_item_tow">
|
||||
<span>{{ tableData.list.length != 0 ? tableData.list[datarow].amount : '无' }}</span>
|
||||
<span>{{ tableData.list.length != 0 ? tableData.list[datarow].amount : '无' }}</span>
|
||||
<el-icon size="10">
|
||||
<ArrowRight />
|
||||
</el-icon>
|
||||
@@ -81,10 +83,9 @@
|
||||
</div>
|
||||
<keyboard v-if="props.membershow == '1'" @consumeFees="consumeFees"></keyboard>
|
||||
<div class="orderbox_right_button" v-if="props.membershow == '0'">
|
||||
<router-link to="/" style="width: 35%;">
|
||||
<el-button style="width: 100%;">创建订单</el-button>
|
||||
</router-link>
|
||||
<el-button style="width: 60%;" type="primary" @click="recharge = true">账户充值</el-button>
|
||||
<el-button style="width: 100%;" @click="toHome">创建订单</el-button>
|
||||
<!-- <el-button style="width: 60%;" type="primary" @click="recharge = true">账户充值</el-button> -->
|
||||
<el-button style="width: 60%;" type="primary" @click="userChargeRef.show()">账户充值</el-button>
|
||||
</div>
|
||||
<div class="orderbox_right_button" v-if="props.membershow == '1'">
|
||||
<router-link to="/" style="width: 35%;">
|
||||
@@ -101,15 +102,18 @@
|
||||
@open="membrform = { ...resetMembrform }">
|
||||
<el-form ref="formRef" :rules="rules" :model="membrform" label-width="70px" hide-required-asterisk>
|
||||
<el-form-item label="手机号" prop="phone">
|
||||
<el-input v-model="membrform.phone" />
|
||||
<el-input v-model="membrform.phone" @focus="
|
||||
global.updateData(false)" @blur="global.updateData(true)" />
|
||||
</el-form-item>
|
||||
<el-form-item label="昵称" prop="nickName">
|
||||
<el-input v-model="membrform.nickName" />
|
||||
<el-input v-model="membrform.nickName" @focus="
|
||||
global.updateData(false)" @blur="global.updateData(true)" />
|
||||
</el-form-item>
|
||||
<el-form-item label="生日" prop="birthDay">
|
||||
<el-col :span="11">
|
||||
<el-date-picker v-model="membrform.birthDay" type="date" placeholder="请选择生日"
|
||||
style="width: 100%" />
|
||||
<el-date-picker v-model="membrform.birthDay" type="date" placeholder="请选择生日" style="width: 100%"
|
||||
@focus="
|
||||
global.updateData(false)" @blur="global.updateData(true)" />
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
<el-form-item label="性别" prop="sex">
|
||||
@@ -159,8 +163,7 @@
|
||||
:close-on-click-modal="false">
|
||||
<payCard :amount="moneys" :orderId="orderId" :selecttype="1" @paySuccess="paySuccess" />
|
||||
</el-dialog>
|
||||
|
||||
|
||||
<userCharge ref="userChargeRef" :userInfo="tableData.list[datarow]" @paySuccess="asyncqueryMembermember" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@@ -173,6 +176,16 @@ import add from '@/views/member/components/add.vue'
|
||||
import cwxeyboard from '@/components/cwx-keyboard/cwx-keyboard.vue'
|
||||
import keyboard from '@/views/home/components/keyboard.vue'
|
||||
import payCard from '@/components/payCard/payCard.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import useStorage from '@/utils/useStorage'
|
||||
import userCharge from './components/userCharge.vue'
|
||||
|
||||
import { useGlobal } from '@/store/global.js'
|
||||
const global = useGlobal()
|
||||
|
||||
const userChargeRef = ref(null)
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const store = useUser()
|
||||
|
||||
@@ -206,6 +219,8 @@ const props = defineProps({//首页传值
|
||||
}
|
||||
})
|
||||
|
||||
const loading = ref(false)
|
||||
|
||||
const flowingwater = reactive({//获取流水初始化
|
||||
total: '',
|
||||
list: []
|
||||
@@ -282,6 +297,7 @@ const inputChange = lodash.debounce(function () { //搜索手机号
|
||||
}, 500)
|
||||
|
||||
const asyncqueryMembermember = async () => {//会员列表数据
|
||||
loading.value = true
|
||||
let res = await queryMembermember({
|
||||
shopId: store.userInfo.shopId,
|
||||
page: tableData.page,
|
||||
@@ -289,10 +305,11 @@ const asyncqueryMembermember = async () => {//会员列表数据
|
||||
phone: tableData.phone
|
||||
})
|
||||
if (res) {
|
||||
if (res.list.length != 0) {
|
||||
tableData.list = res.list
|
||||
MemberAccount()
|
||||
}
|
||||
setTimeout(() => {
|
||||
loading.value = false
|
||||
}, 300)
|
||||
tableData.list = res.list
|
||||
MemberAccount()
|
||||
tableData.total = res.total
|
||||
}
|
||||
}
|
||||
@@ -400,6 +417,14 @@ const createMembermemberSubmit = async () => { ///添加会员
|
||||
});
|
||||
}
|
||||
const moneys = ref('')// 钱数
|
||||
|
||||
const toHome = () => {
|
||||
useStorage.set('memberInfo', tableData.list[datarow.value])
|
||||
router.push({
|
||||
name: 'home'
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// resetMembrform.value = { ...membrform.value }
|
||||
asyncqueryMembermember()
|
||||
|
||||
100
src/views/order/components/cashTable.vue
Normal file
100
src/views/order/components/cashTable.vue
Normal file
@@ -0,0 +1,100 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="tab_container">
|
||||
<el-table :data="tableData.list" height="560px" v-loading="tableData.loading">
|
||||
<el-table-column label="订单号" prop="orderNo"></el-table-column>
|
||||
<el-table-column label="金额" prop="amount">
|
||||
<template v-slot="scope">
|
||||
¥{{ scope.row.amount }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="支付类型" prop="payType">
|
||||
<template v-slot="scope">
|
||||
<el-tag disable-transitions :type="payTypeFilter(scope.row.payType).type">
|
||||
{{ payTypeFilter(scope.row.payType).label }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" prop="createTime">
|
||||
<template v-slot="scope">
|
||||
{{ dayjs(scope.row.createTime).format('YYYY-MM-DD HH:mm:ss') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<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>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import dayjs from 'dayjs'
|
||||
import { queryQuickPay } from '@/api/order'
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
|
||||
const tableData = reactive({
|
||||
resetLoading: false,
|
||||
proName: '',
|
||||
status: '',
|
||||
loading: false,
|
||||
list: [],
|
||||
page: 1,
|
||||
size: 10,
|
||||
total: 0
|
||||
})
|
||||
|
||||
// 分页变化
|
||||
function paginationChange(e) {
|
||||
tableData.page = e
|
||||
queryQuickPayAjax()
|
||||
}
|
||||
|
||||
// 支付类型
|
||||
function payTypeFilter(t) {
|
||||
const m = {
|
||||
cash: {
|
||||
type: 'primary',
|
||||
label: '现金'
|
||||
},
|
||||
scanCode: {
|
||||
type: 'warning',
|
||||
label: '扫码'
|
||||
}
|
||||
}
|
||||
return m[t]
|
||||
}
|
||||
|
||||
// 查询快捷收银订单
|
||||
async function queryQuickPayAjax() {
|
||||
try {
|
||||
tableData.loading = true
|
||||
const res = await queryQuickPay({
|
||||
page: tableData.page,
|
||||
pageSize: tableData.size
|
||||
})
|
||||
tableData.loading = false
|
||||
tableData.list = res.list
|
||||
tableData.total = res.total
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
queryQuickPayAjax()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.tab_container {
|
||||
padding: 0 var(--el-font-size-base) var(--el-font-size-base);
|
||||
}
|
||||
|
||||
.pagination {
|
||||
display: flex;
|
||||
padding: 0 14px;
|
||||
}
|
||||
</style>
|
||||
@@ -4,7 +4,9 @@
|
||||
<el-tabs v-model="ordereData.status" class="demo-tabs" @tab-click="handleClick">
|
||||
<el-tab-pane label="全部" name="">
|
||||
<div class="demo_tabs_div">
|
||||
<el-input v-model="ordereData.orderNo" placeholder="请输入订单号查询" @input="inputChange" clearable />
|
||||
<el-input v-model="ordereData.orderNo" placeholder="请输入订单号查询" @input="inputChange" clearable
|
||||
@focus="
|
||||
global.updateData(false)" @blur="global.updateData(true)" />
|
||||
<!-- <el-button style="margin-left: 10px;" type="primary" @click="onSubmit">搜索</el-button> -->
|
||||
</div>
|
||||
<add :loading="loadingboxshow" :ordereData="ordereData" @emititemboxshow="emititemboxshow"
|
||||
@@ -31,6 +33,9 @@
|
||||
style="margin-top: 20px;" :total="Number(ordereData.total)"
|
||||
@current-change="handleCurrentChange" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="快捷收银" name="cash">
|
||||
<cashTable />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
<div class="orderbox_right" v-if="itemboxshow" v-loading="orderDetaildata.loading" :loading="loadingboxshow">
|
||||
@@ -49,7 +54,7 @@
|
||||
</div>
|
||||
<div class="orderbox_right_item">
|
||||
<span class="span">创建时间:</span><span class="nunber">{{ dayjs(
|
||||
orderDetaildata.createdAt).format("YYYY-MM-DD HH:mm:ss") }}</span>
|
||||
orderDetaildata.createdAt).format("YYYY-MM-DD HH:mm:ss") }}</span>
|
||||
</div>
|
||||
<div class="orderbox_right_item">
|
||||
<span class="span">终端:</span><span class="nunber">{{ orderDetaildata.zdNo }}</span>
|
||||
@@ -93,15 +98,23 @@
|
||||
style="border: 2px solid red; color: red; padding: 4px 2px;">已退</span></div>
|
||||
<div v-else>{{ item.priceAmount }}</div>
|
||||
</div>
|
||||
<div :style="{ 'height': reforderboxrightbuttonheight + 'px' }"></div>
|
||||
</div>
|
||||
<div class="orderbox_right_button">
|
||||
<el-button style="width: 100%;"
|
||||
v-if="orderDetaildata.orderType != 'return' && (orderDetaildata.status == 'refund' || orderDetaildata.status == 'closed')"
|
||||
type="primary" @click="recharge = true">退单</el-button>
|
||||
|
||||
<div class="orderbox_right_button" ref="reforderboxrightbutton">
|
||||
<div class="orderbox_right_buttonbutton">
|
||||
<!-- // -->
|
||||
<el-button @click="print('normal')" style="width: 45%;" type="">重打收银打票</el-button>
|
||||
<el-button @click="print('label')" style="width: 45%;" type="">重打标签小票</el-button>
|
||||
<el-button style="width: 100%;" type="warning" :loading="callLoading" @click="callNumberHandle">
|
||||
叫号
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="orderbox_right_buttonbutton">
|
||||
<el-button style="width: 100%;"
|
||||
v-if="orderDetaildata.orderType != 'return' && (orderDetaildata.status == 'refund' || orderDetaildata.status == 'closed')"
|
||||
type="primary" @click="recharge = true">退单</el-button>
|
||||
</div>
|
||||
<div class="orderbox_right_buttonbutton">
|
||||
<el-button @click="print('normal')" style="flex: 1;">重打收银打票</el-button>
|
||||
<el-button @click="print('label')" style="flex: 1;">重打标签小票</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -146,7 +159,9 @@
|
||||
<el-dialog v-model="recharge" title="退单" width="800" :before-close="handlerecharge">
|
||||
<div class="recharge_footer">
|
||||
<div class="recharge_footer_item">
|
||||
<el-input v-model="remark" style="width: 100%" :rows="2" type="textarea" placeholder="请输入退单原因" />
|
||||
<el-input v-model="remark" style="width: 100%" :rows="2" type="textarea" placeholder="请输入退单原因"
|
||||
@focus="
|
||||
global.updateData(false)" @blur="global.updateData(true)" />
|
||||
<div class="recharge_footer_items" @click="remark = '顾客取消'">
|
||||
<div>顾客取消</div>
|
||||
</div>
|
||||
@@ -198,7 +213,9 @@
|
||||
<!-- {{ item.num }} -->
|
||||
<el-input-number v-model="item.num" :min="1" size="small"
|
||||
:disabled="item.status == 'refund' ? true : false" :max="item.maxnum"
|
||||
@change="(currentValue, oldValue) => changezong(item, index, 1, 'num', currentValue, oldValue)" />
|
||||
@change="(currentValue, oldValue) => changezong(item, index, 1, 'num', currentValue, oldValue)"
|
||||
@focus="
|
||||
global.updateData(false)" @blur="global.updateData(true)" />
|
||||
<!-- @change="changezong(item, index, 1, 'num')" -->
|
||||
</div>
|
||||
<div class="recharge_footer_itemright_botton_itemthere">
|
||||
@@ -209,7 +226,8 @@
|
||||
<div class="recharge_footer_itemright_botton_box">
|
||||
<div class="recharge_footer_itemright_botton_boxone">
|
||||
<div class="recharge_footer_itemright_botton_boxoneabsolute">退单金额:</div>
|
||||
<div class="recharge_footer_itemright_botton_boxonetext">¥{{ refundamount > 0 ? refundamount : '0.00' }}</div>
|
||||
<div class="recharge_footer_itemright_botton_boxonetext">¥{{ refundamount > 0 ? refundamount
|
||||
: '0.00' }}</div>
|
||||
</div>
|
||||
<div class="recharge_footer_itemright_botton_boxtow">
|
||||
<el-button type="primary" style="width: 100%; height: 100%;" :loading="buttonloading"
|
||||
@@ -230,12 +248,25 @@ import { ref, onMounted, reactive } from 'vue'
|
||||
import { ElMessage, dayjs } from 'element-plus'
|
||||
import { useUser } from "@/store/user.js"
|
||||
import lodash from 'lodash'
|
||||
import { orderfindOrder, orderorderDetail, payreturnOrder, cloudPrinterprint } from '@/api/order/index.js'
|
||||
import { orderfindOrder, orderorderDetail, payreturnOrder, cloudPrinterprint, sendMessage } from '@/api/order/index.js'
|
||||
import add from '@/views/order/components/add.vue'
|
||||
import cashTable from '@/views/order/components/cashTable.vue'
|
||||
import { clearNoNum } from '@/utils'
|
||||
|
||||
import { useGlobal } from '@/store/global.js'
|
||||
const global = useGlobal()
|
||||
|
||||
const store = useUser()
|
||||
const itemboxshow = ref(false)
|
||||
|
||||
import { usePrint } from '@/store/print.js'
|
||||
const printStore = usePrint()
|
||||
|
||||
import { ipcRenderer } from 'electron'
|
||||
|
||||
const reforderboxrightbutton = ref(null);//定义ref
|
||||
const reforderboxrightbuttonheight = ref(null)//获取元素高度
|
||||
|
||||
const handleClick = (Name) => {//切换teb
|
||||
ordereData.status = Name.props.name
|
||||
asyncorderfindOrder()
|
||||
@@ -285,30 +316,61 @@ const payreturnOrderclick = lodash.debounce(async () => { //搜索手机号
|
||||
|
||||
} catch (error) {
|
||||
buttonloading.value = false
|
||||
|
||||
}
|
||||
}, 500)
|
||||
|
||||
|
||||
const print = async (e) => {
|
||||
// 重新打印标签/小票
|
||||
const print = lodash.throttle(async function (e) {
|
||||
try {
|
||||
await cloudPrinterprint({
|
||||
type: e,
|
||||
orderId: orderDetaildata.value.id,
|
||||
ispre: false
|
||||
})
|
||||
ElMessage({
|
||||
message: '成功打票',
|
||||
type: 'success',
|
||||
})
|
||||
} catch (error) {
|
||||
if (e == 'label') {
|
||||
// checkLabelPrint(printLabelOrder.value)
|
||||
const data = {
|
||||
shop_name: store.userInfo.merchantName,
|
||||
carts: [],
|
||||
orderInfo: printLabelOrder.value,
|
||||
outNumber: printLabelOrder.value.outNumber,
|
||||
createdAt: dayjs(printLabelOrder.value.createdAt).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
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
// console.log('重打标签小票', data);
|
||||
printStore.labelPrint(data)
|
||||
} else {
|
||||
await cloudPrinterprint({
|
||||
type: e,
|
||||
orderId: orderDetaildata.value.id,
|
||||
ispre: false
|
||||
})
|
||||
ElMessage({
|
||||
message: '成功打票',
|
||||
type: 'success',
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
}, 1500, { leading: true, trailing: false })
|
||||
|
||||
const loadingboxshow = ref(false);
|
||||
// 要打印标签的订单数据
|
||||
const printLabelOrder = ref('')
|
||||
|
||||
const emititemboxshow = async (e) => { //接收子组件值 并赋值给父组件
|
||||
// console.log('emititemboxshow', e);
|
||||
printLabelOrder.value = e
|
||||
|
||||
loadingboxshow.value = true
|
||||
try {
|
||||
let res = await orderorderDetail({
|
||||
@@ -318,6 +380,9 @@ const emititemboxshow = async (e) => { //接收子组件值 并赋值给父组
|
||||
itemboxshow.value = true
|
||||
loadingboxshow.value = false
|
||||
orderDetaildata.value = res
|
||||
if (reforderboxrightbutton.value) { //点击动态获取元素高度
|
||||
reforderboxrightbuttonheight.value = reforderboxrightbutton.value.offsetHeight;
|
||||
}
|
||||
orderDetaildata.value.detailList.forEach((e) => {
|
||||
e.checked = false
|
||||
e.zongprice = e.priceAmount / e.num
|
||||
@@ -422,6 +487,23 @@ const handleCurrentChange = (val) => { //页码
|
||||
const inputChange = lodash.debounce(function () { //搜索手机号
|
||||
asyncorderfindOrder()
|
||||
}, 500)
|
||||
|
||||
// 叫号
|
||||
const callLoading = ref(false)
|
||||
const callNumberHandle = async () => {
|
||||
try {
|
||||
callLoading.value = true
|
||||
const res = await sendMessage({
|
||||
orderId: orderDetaildata.value.id
|
||||
})
|
||||
callLoading.value = false
|
||||
ElMessage.success('叫号成功')
|
||||
} catch (error) {
|
||||
callLoading.value = false
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// resetMembrform.value = { ...membrform.value }
|
||||
asyncorderfindOrder()
|
||||
@@ -795,7 +877,7 @@ onMounted(() => {
|
||||
.tableDataclass {
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
height: 80%;
|
||||
height: 90%;
|
||||
|
||||
.orderbox_right_item {
|
||||
margin-top: 6px;
|
||||
@@ -809,8 +891,9 @@ onMounted(() => {
|
||||
|
||||
.orderbox_right_button {
|
||||
position: absolute;
|
||||
width: 90%;
|
||||
width: 96%;
|
||||
left: 50%;
|
||||
background: #fff;
|
||||
bottom: 16px;
|
||||
|
||||
.orderbox_right_buttonbutton {
|
||||
|
||||
61
src/views/webview/index.vue
Normal file
61
src/views/webview/index.vue
Normal file
@@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<div class="device_container">
|
||||
<div class="header" @click="router.back()">
|
||||
<el-icon style="position: relative; top: 2px; margin-right: 4px" size="22">
|
||||
<ArrowLeft />
|
||||
</el-icon>
|
||||
<el-text>{{ info.title }}</el-text>
|
||||
</div>
|
||||
<div class="d_content">
|
||||
<iframe class="iframe" seamless :src="info.url"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const info = ref({
|
||||
title: '',
|
||||
url: ''
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
console.log('iframe===', route);
|
||||
info.value = route.query
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.device_container {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
padding: 15px;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
.header {
|
||||
height: 50px;
|
||||
background-color: #fff;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.d_content {
|
||||
padding-top: 15px;
|
||||
display: flex;
|
||||
height: calc(100vh - 15px * 2 - 50px);
|
||||
|
||||
.iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -3,10 +3,10 @@
|
||||
<div class="box">
|
||||
<div class="box_top">
|
||||
<router-link to="/" class="box_top_left">
|
||||
<el-icon size="20">
|
||||
<ArrowLeft />
|
||||
</el-icon>
|
||||
<div style="margin-left: 10px;">返回</div>
|
||||
<el-icon size="20">
|
||||
<ArrowLeft />
|
||||
</el-icon>
|
||||
<div style="margin-left: 10px;">返回</div>
|
||||
</router-link>
|
||||
<router-link to='/workrecord' class="box_top_right">
|
||||
交班记录
|
||||
@@ -18,7 +18,7 @@
|
||||
<div class="box_content_left_top_item">
|
||||
<div class="box_content_left_top_item_top">
|
||||
<div style="color:#ff5252; font-size: 30px;">
|
||||
{{ infoData.orderNum || 0}}
|
||||
{{ infoData.orderNum || 0 }}
|
||||
</div>
|
||||
<div style="margin-top: 6px; color: #666;">
|
||||
总订单
|
||||
@@ -26,7 +26,7 @@
|
||||
</div>
|
||||
<div class="box_content_left_top_item_top">
|
||||
<div style="color:#ff5252; font-size: 30px;">
|
||||
{{ infoData.amount || 0}}
|
||||
{{ infoData.amount || 0 }}
|
||||
</div>
|
||||
<div style="margin-top: 6px; color: #666;">
|
||||
营业额
|
||||
@@ -36,7 +36,7 @@
|
||||
<div class="box_content_left_top_item">
|
||||
<div class="box_content_left_top_item_botton">
|
||||
<div style=" font-size: 20px;">
|
||||
{{ infoData.cashAmount|| 0}}
|
||||
{{ infoData.cashAmount || 0 }}
|
||||
</div>
|
||||
<div style="margin-top: 6px;">
|
||||
现金支付
|
||||
@@ -47,7 +47,7 @@
|
||||
</div>
|
||||
<div class="box_content_left_top_item_botton">
|
||||
<div style=" font-size: 20px;">
|
||||
{{ infoData.returnAmount || 0}}
|
||||
{{ infoData.returnAmount || 0 }}
|
||||
</div>
|
||||
<div style="margin-top: 6px;">
|
||||
退款金额
|
||||
@@ -60,9 +60,9 @@
|
||||
</div>
|
||||
<div class="box_content_left_bottom">
|
||||
<el-table :data="infoData.detailList" style="width: 100%;" height="400px">
|
||||
<el-table-column prop="productName" label="商品名称"/>
|
||||
<el-table-column prop="skuName" label="规格名称"/>
|
||||
<el-table-column prop="num" label="商品数量"/>
|
||||
<el-table-column prop="productName" label="商品名称" />
|
||||
<el-table-column prop="skuName" label="规格名称" />
|
||||
<el-table-column prop="num" label="商品数量" />
|
||||
<el-table-column prop="amount" label="商品金额" />
|
||||
</el-table>
|
||||
</div>
|
||||
@@ -89,7 +89,7 @@
|
||||
终端名称:
|
||||
</div>
|
||||
<div class="box_content_right_tiemright">
|
||||
{{ infoData.equipment || '无'}}
|
||||
{{ infoData.equipment || '无' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="box_content_right_tiem">
|
||||
@@ -97,7 +97,7 @@
|
||||
备用金:
|
||||
</div>
|
||||
<div class="box_content_right_tiemright">
|
||||
{{ infoData.pettyCash || '无'}}
|
||||
{{ infoData.pettyCash || '无' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="box_content_right_tiem">
|
||||
@@ -105,7 +105,7 @@
|
||||
收营员:
|
||||
</div>
|
||||
<div class="box_content_right_tiemright">
|
||||
{{ infoData.userName || '无'}}
|
||||
{{ infoData.userName || '无' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="box_content_right_tiembutton" :loading="loading" @click="exit">
|
||||
@@ -121,12 +121,18 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ipcRenderer } from "electron";
|
||||
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { ElMessage, dayjs } from 'element-plus'
|
||||
import { shopInfoqueryDuty, loginlogout } from '@/api/work/index.js'
|
||||
import { shopInfoqueryDuty, loginlogout, handoverData } from '@/api/work/index.js'
|
||||
import useStorage from '@/utils/useStorage'
|
||||
import { useRouter } from "vue-router";
|
||||
import { bySubType } from "@/api/device";
|
||||
import { useUser } from "@/store/user.js";
|
||||
|
||||
const store = useUser();
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
@@ -135,20 +141,96 @@ const dialogVisible = ref(true) //交班
|
||||
const infoData = ref({})
|
||||
const loading = ref(false);
|
||||
|
||||
const printList = ref([]);
|
||||
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 () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
let res = await loginlogout({
|
||||
status:1
|
||||
})
|
||||
useStorage.clear()
|
||||
ElMessage.success("交班成功");
|
||||
setTimeout(() => {
|
||||
router.replace({
|
||||
name: "login",
|
||||
});
|
||||
}, 1000);
|
||||
loading.value = false;
|
||||
if (printList.value.length) {
|
||||
if (!checkLocalPrint(printList.value[0].config.deviceName)) {
|
||||
loading.value = true;
|
||||
let res = await loginlogout({
|
||||
status: 1
|
||||
})
|
||||
useStorage.clear()
|
||||
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()
|
||||
ElMessage.success("交班成功");
|
||||
setTimeout(() => {
|
||||
router.replace({
|
||||
name: "login",
|
||||
});
|
||||
}, 1000);
|
||||
loading.value = false;
|
||||
}
|
||||
} else {
|
||||
loading.value = true;
|
||||
let res = await loginlogout({
|
||||
status: 1
|
||||
})
|
||||
useStorage.clear()
|
||||
ElMessage.success("交班成功");
|
||||
setTimeout(() => {
|
||||
router.replace({
|
||||
name: "login",
|
||||
});
|
||||
}, 1000);
|
||||
loading.value = false;
|
||||
}
|
||||
} catch (error) {
|
||||
loading.value = false;
|
||||
}
|
||||
@@ -166,6 +248,8 @@ const infoshopInfoqueryDutys = async () => {
|
||||
|
||||
}
|
||||
onMounted(() => {
|
||||
getPrintList()
|
||||
bySubTypeAjax()
|
||||
infoshopInfoqueryDutys()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,32 +1,38 @@
|
||||
import { defineConfig } from "vite";
|
||||
import { defineConfig, loadEnv } from "vite";
|
||||
import vue from "@vitejs/plugin-vue";
|
||||
import electron from "vite-plugin-electron";
|
||||
import electronRender from "vite-plugin-electron-renderer";
|
||||
import path from "path";
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
server: {
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'https://cashierclient.sxczgkj.cn/cashier-client', // 线上
|
||||
// target: 'http://192.168.2.27:10587/cashier-client', // 国成
|
||||
// target: 'http://192.168.2.128:10587/cashier-client',
|
||||
changeOrigin: true,
|
||||
rewrite: (path) => path.replace(/^\/api/, '')
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
vue(),
|
||||
electron({
|
||||
entry: "electron/main.js",
|
||||
}),
|
||||
electronRender(),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": path.resolve(__dirname, "./src"),
|
||||
export default defineConfig(({ command, mode }) => {
|
||||
const env = loadEnv(mode, process.cwd(), "");
|
||||
return {
|
||||
server: {
|
||||
proxy: {
|
||||
"/api": {
|
||||
target: env.VITE_API_URL,
|
||||
changeOrigin: true,
|
||||
rewrite: (path) => path.replace(/^\/api/, ""),
|
||||
},
|
||||
"/php": {
|
||||
target: env.VITE_API_PHP_URL,
|
||||
changeOrigin: true,
|
||||
rewrite: (path) => path.replace(/^\/php/, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
vue(),
|
||||
electron({
|
||||
entry: "electron/main.js",
|
||||
}),
|
||||
electronRender(),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": path.resolve(__dirname, "./src"),
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user