Skip to content

Commit a69dc3a

Browse files
committed
【功能】添加扫描枪核销功能、根据当前登录人查询自提点功能和绑定自提员工功能
1 parent 4a2eddb commit a69dc3a

File tree

7 files changed

+579
-12
lines changed

7 files changed

+579
-12
lines changed

src/api/mall/trade/delivery/pickUpStore/index.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,13 @@ export const updateDeliveryPickUpStore = async (data: DeliveryPickUpStoreVO) =>
4444
export const deleteDeliveryPickUpStore = async (id: number) => {
4545
return await request.delete({ url: '/trade/delivery/pick-up-store/delete?id=' + id })
4646
}
47+
48+
//绑定自提店员
49+
export const bindStoreStaffId = async (data: any) => {
50+
return await request.post({ url: '/trade/delivery/pick-up-store/bind', data })
51+
}
52+
53+
//查询门店绑定情况
54+
export const getDeliveryPickUpStoreStaff = async (id: number) => {
55+
return await request.get({ url: '/trade/delivery/pick-up-store/get-store-staff?id=' + id })
56+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import request from '@/config/axios'
2+
3+
// 删除自提门店
4+
export const deleteDeliveryPickUpStoreStaff = async (userId: number,storeId: number) => {
5+
return await request.delete({ url: '/trade/delivery/pick-up-store-staff/delete?userId=' + userId +'&storeId=' + storeId})
6+
}

src/views/mall/trade/delivery/pickUpOrder/index.vue

Lines changed: 102 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@
2626
<el-select
2727
v-model="queryParams.pickUpStoreId"
2828
class="!w-280px"
29-
clearable
30-
multiple
3129
placeholder="全部"
30+
@change="handleQuery"
3231
>
3332
<el-option
3433
v-for="item in pickUpStoreList"
@@ -73,10 +72,16 @@
7372
<Icon class="mr-5px" icon="ep:refresh" />
7473
重置
7574
</el-button>
76-
<el-button @click="handlePickup" type="success" plain v-hasPermi="['trade:order:pick-up']">
75+
<el-button @click="handlePickup" type="success" plain v-hasPermi="['trade:order:pick-up']" :disabled="isUse">
7776
<Icon class="mr-5px" icon="ep:check" />
7877
核销
7978
</el-button>
79+
<el-button type="primary" @click="connectToSerialPort" :disabled="serialPort || isUse">
80+
连接扫描枪
81+
</el-button>
82+
<el-button type="danger" @click="cutPort" :disabled="!serialPort || isUse">
83+
断开扫描枪
84+
</el-button>
8085
</el-form-item>
8186
</el-form>
8287
</ContentWrap>
@@ -216,6 +221,12 @@ import { DeliveryTypeEnum } from '@/utils/constants'
216221
import { TradeOrderSummaryRespVO } from '@/api/mall/trade/order'
217222
import { DeliveryPickUpStoreVO } from '@/api/mall/trade/delivery/pickUpStore'
218223
import OrderPickUpForm from '@/views/mall/trade/order/form/OrderPickUpForm.vue'
224+
import { ref, onMounted } from "vue";
225+
const message = useMessage() // 消息弹窗
226+
227+
const port = ref("");
228+
const ports = ref([]);
229+
const reader = ref("");
219230
220231
defineOptions({ name: 'PickUpOrder' })
221232
@@ -227,6 +238,8 @@ const total = ref(2)
227238
const list = ref<TradeOrderApi.OrderVO[]>([])
228239
// 搜索的表单
229240
const queryFormRef = ref<FormInstance>()
241+
const serialPort = ref(false)
242+
const isUse = ref(true)
230243
// 初始表单参数
231244
const INIT_QUERY_PARAMS = {
232245
// 页数
@@ -240,6 +253,7 @@ const INIT_QUERY_PARAMS = {
240253
// 自提门店
241254
pickUpStoreId: undefined
242255
}
256+
243257
// 表单搜索
244258
const queryParams = ref({ ...INIT_QUERY_PARAMS })
245259
// 订单搜索类型 queryParam
@@ -294,6 +308,9 @@ const handleQuery = async () => {
294308
const resetQuery = () => {
295309
queryFormRef.value?.resetFields()
296310
queryParams.value = { ...INIT_QUERY_PARAMS }
311+
if(pickUpStoreList.value.length > 0) {
312+
queryParams.value.pickUpStoreId = pickUpStoreList.value[0].id
313+
}
297314
handleQuery()
298315
}
299316
@@ -309,10 +326,89 @@ const handlePickup = () => {
309326
pickUpForm.value.open()
310327
}
311328
329+
/** 连接扫码枪 */
330+
const connectToSerialPort = async () => {
331+
try {
332+
// 判断浏览器支持串口通信
333+
if ("serial" in navigator && navigator.serial != null && typeof navigator.serial === 'object' && "requestPort" in navigator.serial) {
334+
// 提示用户选择一个串口
335+
port.value = await navigator.serial.requestPort();
336+
} else {
337+
message.error("浏览器不支持扫码枪连接,请更换浏览器重试")
338+
return
339+
}
340+
341+
// 获取用户之前授予该网站访问权限的所有串口。
342+
ports.value = await navigator.serial.getPorts();
343+
344+
// console.log(port.value, ports.value);
345+
console.log(port.value);
346+
// 等待串口打开
347+
await port.value.open({ baudRate: 9600 , dataBits: 8 , stopBits: 2});
348+
349+
// console.log(typeof port.value);
350+
message.success("成功连接扫码枪")
351+
serialPort.value = true;
352+
// readData(port.value);
353+
readData();
354+
} catch (error) {
355+
// 处理连接串口出错的情况
356+
console.log("Error connecting to serial port:", error);
357+
}
358+
};
359+
360+
/** 监听扫码枪输入 */
361+
const readData = async () => {
362+
reader.value = port.value.readable.getReader();
363+
let data = ""; //扫码数据
364+
// 监听来自串口的数据
365+
while (true) {
366+
const { value, done } = await reader.value.read();
367+
if (done) {
368+
// 允许稍后关闭串口
369+
reader.value.releaseLock();
370+
break;
371+
}
372+
// 获取发送的数据
373+
const serialData = new TextDecoder().decode(value);
374+
data = `${data}${serialData}`;
375+
if (serialData.includes("\r")) {
376+
//读取结束
377+
let codeData = data.replace("\r","");
378+
data = ""; //清空下次读取不会叠加
379+
console.log(`二维码数据:${codeData}`);
380+
//处理拿到数据逻辑
381+
pickUpForm.value.open(codeData)
382+
}
383+
}
384+
};
385+
386+
/** 断开扫码枪 */
387+
const cutPort = async () => {
388+
if (port.value !== "") {
389+
await reader.value.cancel();
390+
await port.value.close();
391+
port.value = "";
392+
console.log("断开扫码枪连接");
393+
message.success("已成功断开扫码枪连接")
394+
serialPort.value = false;
395+
} else {
396+
message.warning("请先连接或打开扫码枪")
397+
}
398+
};
399+
312400
/** 初始化 **/
313-
onMounted(() => {
314-
getList()
315-
getPickUpStoreList()
401+
onMounted(async () => {
402+
await getPickUpStoreList()
403+
if(pickUpStoreList.value.length > 0){
404+
queryParams.value.pickUpStoreId = pickUpStoreList.value[0].id
405+
isUse.value = false
406+
await getList()
407+
}else{
408+
message.error("当前登录人没绑定任何自提点")
409+
loading.value = false
410+
isUse.value = true
411+
}
316412
})
317413
</script>
318414
<style lang="scss" scoped>
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
<template>
2+
<Dialog :title="dialogTitle" v-model="dialogVisible" width="20%">
3+
<el-form
4+
ref="formRef"
5+
:model="formData"
6+
:rules="formRules"
7+
label-width="120px"
8+
v-loading="formLoading"
9+
>
10+
<el-row>
11+
<el-col :span="24">
12+
<el-form-item label="门店名称" prop="name">
13+
<el-input v-model="formData.name" placeholder="请输入门店名称" :disabled="true"/>
14+
</el-form-item>
15+
</el-col>
16+
</el-row>
17+
<el-row>
18+
<el-col :span="24">
19+
<el-form-item label="门店店员" prop="storeStaffIds">
20+
<el-button type="primary" @click="storeStaffTableSelect.open()">选择店员</el-button>
21+
</el-form-item>
22+
<!-- 店员列表 -->
23+
<ContentWrap v-if="usersList.length > 0">
24+
<el-table :data="usersList">
25+
<el-table-column label="编号" align="center" prop="id" />
26+
<el-table-column
27+
label="用户昵称"
28+
align="center"
29+
prop="nickname"
30+
:show-overflow-tooltip="true"
31+
/>
32+
<el-table-column label="状态" align="center" key="status">
33+
<template #default="scope">
34+
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
35+
</template>
36+
</el-table-column>
37+
<el-table-column align="center" label="操作">
38+
<template #default="scope">
39+
<el-button
40+
v-hasPermi="['trade:delivery:pick-up-store:delete']"
41+
link
42+
type="danger"
43+
@click="handleDelete(scope.row.id)"
44+
>
45+
删除
46+
</el-button>
47+
</template>
48+
</el-table-column>
49+
</el-table>
50+
</ContentWrap>
51+
</el-col>
52+
</el-row>
53+
</el-form>
54+
<template #footer>
55+
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
56+
<el-button @click="dialogVisible = false">取 消</el-button>
57+
</template>
58+
</Dialog>
59+
<StoreStaffTableSelect ref="storeStaffTableSelect" @change="changeStoreStaff"/>
60+
</template>
61+
<script setup lang="ts">
62+
import * as DeliveryPickUpStoreApi from '@/api/mall/trade/delivery/pickUpStore'
63+
import StoreStaffTableSelect from './components/StoreStaffTableSelect.vue'
64+
import {DICT_TYPE} from "@/utils/dict";
65+
66+
const message = useMessage() // 消息弹窗
67+
const { t } = useI18n() // 国际化
68+
69+
const dialogVisible = ref(false) // 弹窗的是否展示
70+
const dialogTitle = ref('') // 弹窗的标题
71+
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
72+
const formData = ref({
73+
id: undefined,
74+
name: '',
75+
storeStaffIds: [],
76+
storeStaffs: [],
77+
})
78+
const formRules = reactive({
79+
name: [{ required: true, message: '门店名称不能为空', trigger: 'blur' }],
80+
})
81+
const formRef = ref() // 表单 Ref
82+
const storeStaffTableSelect = ref() // 表单 Ref
83+
84+
/** 打开弹窗 */
85+
const open = async (id: number) => {
86+
dialogVisible.value = true
87+
dialogTitle.value = '绑定自提门店员工'
88+
resetForm()
89+
formLoading.value = true
90+
try {
91+
await getList(id)
92+
} finally {
93+
formLoading.value = false
94+
}
95+
}
96+
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
97+
98+
/** 提交表单 */
99+
const submitForm = async () => {
100+
formData.value.storeStaffIds = usersList.value.map(item => item.id) as [];
101+
// 校验表单
102+
if (!formRef) return
103+
const valid = await formRef.value.validate()
104+
if (!valid) return
105+
// 提交请求
106+
formLoading.value = true
107+
try {
108+
const data = formData.value
109+
await DeliveryPickUpStoreApi.bindStoreStaffId(data)
110+
message.success("绑定成功")
111+
dialogVisible.value = false
112+
} finally {
113+
formLoading.value = false
114+
}
115+
}
116+
117+
/** 删除按钮操作 */
118+
const handleDelete = async (id: number) => {
119+
try {
120+
// 删除的二次确认
121+
await message.delConfirm()
122+
// 发起删除
123+
const index = usersList.value.findIndex(item => {
124+
if (item.id == id){
125+
return true;
126+
}
127+
})
128+
usersList.value.splice(index, 1);
129+
//await DeliveryPickUpStoreStaffApi.deleteDeliveryPickUpStoreStaff(id,formData.value.id)
130+
message.success(t('common.delSuccess'))
131+
// 刷新列表
132+
//await getList(formData.value.id)
133+
} catch {}
134+
}
135+
136+
/**
137+
* 查询自提点员工绑定关系
138+
*/
139+
const getList = async (id: number) => {
140+
formData.value = await DeliveryPickUpStoreApi.getDeliveryPickUpStoreStaff(id)
141+
if(formData.value.storeStaffs){
142+
usersList.value = formData.value.storeStaffs;
143+
}
144+
}
145+
146+
/** 重置表单 */
147+
const resetForm = () => {
148+
formData.value = {
149+
id: undefined,
150+
name: '',
151+
storeStaffIds: [],
152+
storeStaffs: [],
153+
}
154+
formRef.value?.resetFields()
155+
}
156+
157+
const usersList = ref([])
158+
const changeStoreStaff = (checkedUsers : []) => {
159+
usersList.value = checkedUsers
160+
}
161+
</script>

0 commit comments

Comments
 (0)