This commit is contained in:
parent
11290d1505
commit
0fbc614c61
|
|
@ -3,4 +3,4 @@ ENV = development
|
|||
|
||||
# 本地环境接口地址
|
||||
# VITE_API_URL = 'http://192.168.2.87:10587/cashier-client'
|
||||
VITE_API_URL = 'https://cashierclient.sxczgkj.cn/cashier-client'
|
||||
VITE_API_URL = 'https://cashiernew.sxczgkj.cn/cashier-client'
|
||||
|
|
@ -19,6 +19,7 @@ electron.app.whenReady().then(() => {
|
|||
});
|
||||
if (process.env.VITE_DEV_SERVER_URL) {
|
||||
win.loadURL(process.env.VITE_DEV_SERVER_URL);
|
||||
win.webContents.openDevTools();
|
||||
} else {
|
||||
win.loadFile(path.resolve(__dirname, "../dist/index.html"));
|
||||
}
|
||||
|
|
@ -30,24 +31,7 @@ electron.app.whenReady().then(() => {
|
|||
electron.ipcMain.on("quitHandler", (_, msg) => {
|
||||
electron.app.quit();
|
||||
});
|
||||
const printWin = new electron.BrowserWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
// 集成网页和 Node.js,也就是在渲染进程中,可以调用 Node.js 方法
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false
|
||||
}
|
||||
});
|
||||
if (process.env.VITE_DEV_SERVER_URL) {
|
||||
printWin.loadFile(path.join(__dirname, "../public/print.html"));
|
||||
} else {
|
||||
printWin.loadFile(path.resolve(__dirname, "../dist/print.html"));
|
||||
}
|
||||
electron.ipcMain.on("printerInfoSync", (event, params) => {
|
||||
printWin.webContents.send("getParams", params);
|
||||
});
|
||||
electron.ipcMain.on("printStart", () => {
|
||||
console.log("开始打印");
|
||||
electron.ipcMain.on("printStart", (event, arg) => {
|
||||
});
|
||||
});
|
||||
electron.app.on("window-all-closed", () => {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ app.whenReady().then(() => {
|
|||
if (process.env.VITE_DEV_SERVER_URL) {
|
||||
win.loadURL(process.env.VITE_DEV_SERVER_URL);
|
||||
// 使用vite开发服务的url路径访问应用
|
||||
// win.webContents.openDevTools();
|
||||
win.webContents.openDevTools();
|
||||
} else {
|
||||
win.loadFile(path.resolve(__dirname, "../dist/index.html")); // 打包后使用文件路径访问应用
|
||||
}
|
||||
|
|
@ -40,36 +40,37 @@ app.whenReady().then(() => {
|
|||
});
|
||||
|
||||
// 创建打印小票子窗口
|
||||
const printWin = new BrowserWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
// 集成网页和 Node.js,也就是在渲染进程中,可以调用 Node.js 方法
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false,
|
||||
},
|
||||
});
|
||||
// const printWin = new BrowserWindow({
|
||||
// show: false,
|
||||
// webPreferences: {
|
||||
// // 集成网页和 Node.js,也就是在渲染进程中,可以调用 Node.js 方法
|
||||
// nodeIntegration: true,
|
||||
// contextIsolation: false,
|
||||
// },
|
||||
// });
|
||||
|
||||
if (process.env.VITE_DEV_SERVER_URL) {
|
||||
// 加载打印的html文件
|
||||
printWin.loadFile(path.join(__dirname, "../public/print.html"));
|
||||
} else {
|
||||
printWin.loadFile(path.resolve(__dirname, "../dist/print.html")); // 打包后使用文件路径访问应用
|
||||
}
|
||||
// if (process.env.VITE_DEV_SERVER_URL) {
|
||||
// // 加载打印的html文件
|
||||
// printWin.loadFile(path.join(__dirname, "../public/print.html"));
|
||||
// } else {
|
||||
// printWin.loadFile(path.resolve(__dirname, "../dist/print.html")); // 打包后使用文件路径访问应用
|
||||
// }
|
||||
|
||||
// win.webContents.getPrintersAsync().then(res => {
|
||||
// console.log('list', res)
|
||||
// // console.log('list', res)
|
||||
// })
|
||||
|
||||
ipcMain.on("printerInfoSync", (event, params) => {
|
||||
// console.log(JSON.parse(params))
|
||||
printWin.webContents.send("getParams", params);
|
||||
});
|
||||
// ipcMain.on("printerInfoSync", (event, params) => {
|
||||
// // console.log(JSON.parse(params))
|
||||
// printWin.webContents.send("getParams", params);
|
||||
// });
|
||||
|
||||
// 执行打印操作
|
||||
ipcMain.on('printStart', () => {
|
||||
console.log('开始打印')
|
||||
ipcMain.on('printStart', (event, arg) => {
|
||||
// console.log('开始打印', arg)
|
||||
|
||||
let name = 'RONGTA 80mm Series Printer'
|
||||
// let name = 'Xprinter XP-365B'
|
||||
// // let name = 'Generic / Text Only'
|
||||
|
||||
// printWin.webContents.print({
|
||||
// silent: true,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "vite-electron",
|
||||
"private": true,
|
||||
"version": "0.0.5",
|
||||
"version": "0.0.7",
|
||||
"main": "dist-electron/main.js",
|
||||
"scripts": {
|
||||
"dev": "chcp 65001 && vite",
|
||||
|
|
@ -13,7 +13,8 @@
|
|||
"@element-plus/icons-vue": "^2.3.1",
|
||||
"axios": "^1.6.2",
|
||||
"dayjs": "^1.11.10",
|
||||
"electron-pos-printer": "^1.3.7",
|
||||
"electron-pos-printer": "^1.3.6",
|
||||
"electron-pos-printer-vue": "^1.0.9",
|
||||
"element-plus": "^2.4.3",
|
||||
"lodash": "^4.17.21",
|
||||
"pinia": "^2.1.7",
|
||||
|
|
|
|||
|
|
@ -7,114 +7,58 @@
|
|||
<meta charset="UTF-8" />
|
||||
<title>Print preview</title>
|
||||
<style>
|
||||
#app {
|
||||
padding: 30px;
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
.t1 {
|
||||
section {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.t2 {
|
||||
font-size: 18px;
|
||||
}
|
||||
.time {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.thead {
|
||||
display: flex;
|
||||
}
|
||||
.thead .item {
|
||||
flex: 1;
|
||||
font-weight: bold;
|
||||
}
|
||||
.tbody .tr {
|
||||
padding: 10px 0;
|
||||
display: flex;
|
||||
}
|
||||
.tbody .tr .item {
|
||||
flex: 1;
|
||||
}
|
||||
.html2cavas {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app">
|
||||
<div class="html2cavas">
|
||||
<div>---------------</div>
|
||||
<div>---------------</div>
|
||||
<div>---------------</div>
|
||||
<div>---------------</div>
|
||||
<div>---------------</div>
|
||||
<div>---------------</div>
|
||||
<ESC> "@"
|
||||
<ESC> "|cA" "Sample Text" <LF>
|
||||
<ESC> "|cA" "Price: $10.00" <LF>
|
||||
<ESC> "|cA" "Thank you!" <LF>
|
||||
<ESC> "d" "n" <LF>
|
||||
<pre style="text-align: center">{{data.shop_name || '结账单位'}}</pre>
|
||||
<div class="header">
|
||||
<div class="t2">结账单</div>
|
||||
</div>
|
||||
<div class="time">开始时间: 2024/3/7 09:56:23</div>
|
||||
<div class="time">结束时间: 2024/3/8 13:11:07</div>
|
||||
<div class="thead">品相 数量 单位 单价 小计 注</div>
|
||||
<div class="tbody">
|
||||
<div v-for="item in data.carts" :key="item.id" class="tr">
|
||||
{{item.name}} x{{item.number}} x{{item.number}} {{item.unitName}}
|
||||
{{item.salePrice}} {{item.salePrice}}
|
||||
</div>
|
||||
</div>
|
||||
<div>优惠信息</div>
|
||||
<div><br /></div>
|
||||
<div>赠送优惠:{{data.amount}}</div>
|
||||
<div><br /></div>
|
||||
<div>结算方式</div>
|
||||
<div>---------------</div>
|
||||
<div>---------------</div>
|
||||
<div>---------------</div>
|
||||
<div>---------------</div>
|
||||
<div>---------------</div>
|
||||
<div class="html2canvas" style="position: fixed;top: -1000%;">
|
||||
<section style="font-size: 22px;">#B1 B2</section>
|
||||
<section style="font-size: 22px;">喔喔奶茶 x12</section>
|
||||
<section style="font-size: 22px;">麻辣味</section></section></section>
|
||||
<section style="font-size: 22px;">03-08 16:32 ¥123.00</section>
|
||||
</div>
|
||||
<!-- <section>我是标签111</section>
|
||||
<section>我是标签222</section>
|
||||
<section>我是标签333</section>
|
||||
<section>我是标签444</section> -->
|
||||
</div>
|
||||
<script type="module">
|
||||
const { ipcRenderer } = require("electron");
|
||||
import {
|
||||
createApp,
|
||||
ref,
|
||||
onMounted,
|
||||
} from "../node_modules/vue/dist/vue.esm-browser.js";
|
||||
// import {
|
||||
// createApp,
|
||||
// ref,
|
||||
// onMounted,
|
||||
// } from "../node_modules/vue/dist/vue.esm-browser.js";
|
||||
|
||||
createApp({
|
||||
setup() {
|
||||
const data = ref({});
|
||||
import html2canvas from '../node_modules/html2canvas/dist/html2canvas.esm.js'
|
||||
|
||||
onMounted(() => {
|
||||
ipcRenderer.on("getParams", (event, arg) => {
|
||||
// console.log(arg);
|
||||
data.value = JSON.parse(arg);
|
||||
ipcRenderer.send("printStart");
|
||||
});
|
||||
});
|
||||
html2canvas(document.querySelector('.html2canvas')).then(canvas => {
|
||||
console.log(canvas)
|
||||
document.querySelector('#app').appendChild(canvas)
|
||||
}).catch(err=> {
|
||||
console.log(err);
|
||||
})
|
||||
|
||||
return {
|
||||
data,
|
||||
};
|
||||
},
|
||||
}).mount("#app");
|
||||
// createApp({
|
||||
// setup() {
|
||||
// const data = ref({});
|
||||
|
||||
// onMounted(() => {
|
||||
// ipcRenderer.on("getParams", (event, arg) => {
|
||||
// // console.log(arg);
|
||||
// data.value = JSON.parse(arg);
|
||||
|
||||
// setTimeout(() => {
|
||||
// ipcRenderer.send("printStart");
|
||||
// },500)
|
||||
// });
|
||||
// });
|
||||
|
||||
// return {
|
||||
// data,
|
||||
// };
|
||||
// },
|
||||
// }).mount("#app");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
20
src/App.vue
20
src/App.vue
|
|
@ -5,28 +5,36 @@
|
|||
<left-menu />
|
||||
</div>
|
||||
<div :class="{ view: route.path != '/login' }">
|
||||
<router-view />
|
||||
<!-- <div class="wrapper">
|
||||
<div class="wrapper">
|
||||
<div class="animation">
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition :name="transitionName">
|
||||
<!-- <transition :name="transitionName"> -->
|
||||
<keep-alive :include="includeList">
|
||||
<component :is="Component"></component>
|
||||
</transition>
|
||||
</keep-alive>
|
||||
<!-- </transition> -->
|
||||
</router-view>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-config-provider>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { ref, reactive, watch } from "vue";
|
||||
import { useRouter, useRoute } from "vue-router"
|
||||
import leftMenu from '@/components/leftMenu.vue'
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const includeList = reactive([]);
|
||||
watch(route, (to) => {
|
||||
if (to.meta.keepAlive) {
|
||||
includeList.push(to.name);
|
||||
}
|
||||
});
|
||||
|
||||
let transitionName = ref();
|
||||
let router = useRouter();
|
||||
router.beforeEach((to, from) => {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
<template>
|
||||
<el-dialog :title="goods.name" width="500" v-model="dialogVisible">
|
||||
<el-dialog :title="goods.name" width="600" v-model="dialogVisible">
|
||||
<div class="header">选择规格</div>
|
||||
<div v-loading="loading">
|
||||
<div class="row" v-for="(item, index) in goods.tbProductSpec.specList" :key="index">
|
||||
<div class="row" v-for="(item, index) in goods.selectSpec" :key="index">
|
||||
<div class="title">{{ item.name }}</div>
|
||||
<div class="sku_wrap">
|
||||
<!-- <div class="item" :class="{ active: val.active }" v-for="(val, i) in item.value" :key="i"
|
||||
@click="selectedSku(index, i)">{{ val.name }}</div> -->
|
||||
<el-button :plain="!val.active" type="primary" v-for="(val, i) in item.value" :key="i"
|
||||
@click="selectedSku(index, i)">{{ val.name }}</el-button>
|
||||
<el-button :plain="!val.active" type="primary" v-for="(val, i) in item.selectSpecResult
|
||||
" :key="i" @click="selectedSku(index, i)" class="btn">{{ val.name }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -68,14 +68,14 @@ function submitSku() {
|
|||
|
||||
// 选择规格
|
||||
function selectedSku(index, i) {
|
||||
goods.value.tbProductSpec.specList[index].value.map(item => {
|
||||
goods.value.selectSpec[index].selectSpecResult.map(item => {
|
||||
item.active = false
|
||||
})
|
||||
if (goods.value.tbProductSpec.specList[index].value[i].active) {
|
||||
goods.value.tbProductSpec.specList[index].value[i].active = false
|
||||
if (goods.value.selectSpec[index].selectSpecResult[i].active) {
|
||||
goods.value.selectSpec[index].selectSpecResult[i].active = false
|
||||
selectedSkuNum.value--
|
||||
} else {
|
||||
goods.value.tbProductSpec.specList[index].value[i].active = true
|
||||
goods.value.selectSpec[index].selectSpecResult[i].active = true
|
||||
selectedSkuNum.value++
|
||||
}
|
||||
selectedSuccess()
|
||||
|
|
@ -85,8 +85,8 @@ function selectedSku(index, i) {
|
|||
function selectedSuccess() {
|
||||
let num = 0
|
||||
let tag = []
|
||||
goods.value.tbProductSpec.specList.map(item => {
|
||||
item.value.map(val => {
|
||||
goods.value.selectSpec.map(item => {
|
||||
item.selectSpecResult.map(val => {
|
||||
if (val.active) {
|
||||
num++
|
||||
tag.push(val.name)
|
||||
|
|
@ -96,7 +96,7 @@ function selectedSuccess() {
|
|||
selectedSkuTag.value = tag.join(',')
|
||||
})
|
||||
|
||||
if (selectedSkuNum.value >= goods.value.tbProductSpec.specList.length) {
|
||||
if (selectedSkuNum.value >= goods.value.selectSpec.length) {
|
||||
// 规格选完了
|
||||
queryProductSkuAjax()
|
||||
}
|
||||
|
|
@ -133,34 +133,33 @@ function show(item, t = 'shop') {
|
|||
goods.value = ""
|
||||
goods.value = item
|
||||
type.value = t
|
||||
if (typeof goods.value.tbProductSpec.specList == 'string') {
|
||||
goods.value.tbProductSpec.specList = JSON.parse(goods.value.tbProductSpec.specList)
|
||||
goods.value.tbProductSpec.specList.map(item => {
|
||||
let arr = []
|
||||
item.value.map(val => {
|
||||
switch (type.value) {
|
||||
case 'shop':
|
||||
arr.push({
|
||||
active: false,
|
||||
name: val
|
||||
})
|
||||
break;
|
||||
case 'cart':
|
||||
// 如果从购物车选择规格需要做选中效果
|
||||
const skus = goods.value.skuName.split(',')
|
||||
arr.push({
|
||||
active: !!skus.find(item => item === val),
|
||||
name: val
|
||||
})
|
||||
break;
|
||||
goods.value.selectSpec = JSON.parse(goods.value.selectSpec)
|
||||
goods.value.selectSpec.map(item => {
|
||||
let arr = []
|
||||
item.selectSpecResult.map(val => {
|
||||
switch (type.value) {
|
||||
case 'shop':
|
||||
arr.push({
|
||||
active: false,
|
||||
name: val
|
||||
})
|
||||
break;
|
||||
case 'cart':
|
||||
// 如果从购物车选择规格需要做选中效果
|
||||
const skus = goods.value.skuName.split(',')
|
||||
arr.push({
|
||||
active: !!skus.find(item => item === val),
|
||||
name: val
|
||||
})
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
})
|
||||
item.value = arr
|
||||
default:
|
||||
break;
|
||||
}
|
||||
})
|
||||
}
|
||||
item.selectSpecResult = arr
|
||||
})
|
||||
console.log(goods.value)
|
||||
selectedSuccess()
|
||||
}
|
||||
|
||||
|
|
@ -185,7 +184,9 @@ defineExpose({
|
|||
|
||||
.sku_wrap {
|
||||
display: flex;
|
||||
padding: 14px 0;
|
||||
padding: var(--el-font-size-base) 0;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--el-font-size-base);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ const routes = [
|
|||
{
|
||||
path: "/",
|
||||
name: "home",
|
||||
meta: {
|
||||
keepAlive: true
|
||||
},
|
||||
component: home,
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -125,11 +125,11 @@ function skuConfirm(e) {
|
|||
padding: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
gap: 16px;
|
||||
|
||||
.item {
|
||||
width: 70px;
|
||||
height: 30px;
|
||||
height: 34px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
|
|
|||
|
|
@ -39,8 +39,7 @@
|
|||
<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" style="width: 100%;height: 100%;background-color: #efefef;"
|
||||
fit="contain"></el-image>
|
||||
<el-image :src="item.coverImg" class="el_img" fit="cover"></el-image>
|
||||
</div>
|
||||
<div class="name"><el-text line-clamp="2">{{ item.name }}</el-text></div>
|
||||
<div class="item_empty" v-if="shopListType == 'text'"></div>
|
||||
|
|
@ -330,7 +329,17 @@ defineExpose({
|
|||
|
||||
.cover {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
padding-bottom: 100%;
|
||||
position: relative;
|
||||
|
||||
.el_img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #efefef;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
|
|
|
|||
|
|
@ -104,6 +104,11 @@
|
|||
<pendingCartModal ref="pendingCartModalRef" @select="pendingCartHandle" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'home'
|
||||
}
|
||||
</script>
|
||||
<script setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useUser } from "@/store/user.js"
|
||||
|
|
|
|||
|
|
@ -1,37 +1,20 @@
|
|||
<template>
|
||||
<el-button @click="chooseSerial">选择扫码枪串口</el-button>
|
||||
<el-input ref="inputRef" v-model="printValue" @keyup.enter="enterHandle" @input="inputHandle"></el-input>
|
||||
<el-button @click="chooseSerial">打印</el-button>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import _ from 'lodash'
|
||||
import { ref, onMounted } from 'vue';
|
||||
|
||||
const inputRef = ref(null)
|
||||
|
||||
const printValue = ref('')
|
||||
|
||||
function enterHandle() {
|
||||
console.log('回车了')
|
||||
}
|
||||
|
||||
const inputHandle = _.debounce(function (e) {
|
||||
console.log('扫码枪输入完了', e)
|
||||
}, 100)
|
||||
import { ipcRenderer } from 'electron'
|
||||
|
||||
//选择串口设备
|
||||
const chooseSerial = async () => {
|
||||
if ('serial' in navigator) {
|
||||
// await port.close();
|
||||
console.log('当前浏览器支持serial')
|
||||
const port = await navigator.serial.requestPort()
|
||||
await port.open({ baudRate: 9600 })
|
||||
let printNum = localStorage.getItem('printNum')
|
||||
if (!printNum) {
|
||||
printNum = 1
|
||||
localStorage.setItem('printNum', printNum)
|
||||
} else {
|
||||
printNum++
|
||||
localStorage.setItem('printNum', printNum)
|
||||
}
|
||||
ipcRenderer.send('printStart', printNum)
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
inputRef.value.focus()
|
||||
}, 1000)
|
||||
})
|
||||
</script>
|
||||
|
|
@ -72,9 +72,9 @@ const loading = ref(false);
|
|||
const form = reactive({
|
||||
serialNumber: RandomNumBoth(1000, 9999),
|
||||
clientType: 'pc',
|
||||
merchantName: '18821670757',
|
||||
loginName: "18821670757",
|
||||
password: "123456",
|
||||
merchantName: '',
|
||||
loginName: "",
|
||||
password: "",
|
||||
});
|
||||
|
||||
const rules = reactive({
|
||||
|
|
|
|||
Loading…
Reference in New Issue