From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目
---
src/views/mall/trade/delivery/pickUpOrder/index.vue | 436 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 436 insertions(+), 0 deletions(-)
diff --git a/src/views/mall/trade/delivery/pickUpOrder/index.vue b/src/views/mall/trade/delivery/pickUpOrder/index.vue
new file mode 100644
index 0000000..5d4fc4f
--- /dev/null
+++ b/src/views/mall/trade/delivery/pickUpOrder/index.vue
@@ -0,0 +1,436 @@
+<template>
+ <doc-alert title="銆愪氦鏄撱�戜氦鏄撹鍗�" url="https://doc.iocoder.cn/mall/trade-order/" />
+ <doc-alert title="銆愪氦鏄撱�戣喘鐗╄溅" url="https://doc.iocoder.cn/mall/trade-cart/" />
+
+ <!-- 鎼滅储 -->
+ <ContentWrap>
+ <el-form
+ ref="queryFormRef"
+ :inline="true"
+ :model="queryParams"
+ class="-mb-15px"
+ label-width="68px"
+ >
+ <el-form-item label="鍒涘缓鏃堕棿" prop="createTime">
+ <el-date-picker
+ v-model="queryParams.createTime"
+ :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
+ class="!w-280px"
+ end-placeholder="鑷畾涔夋椂闂�"
+ start-placeholder="鑷畾涔夋椂闂�"
+ type="daterange"
+ value-format="YYYY-MM-DD HH:mm:ss"
+ />
+ </el-form-item>
+ <el-form-item label="鑷彁闂ㄥ簵" prop="pickUpStoreIds">
+ <el-select
+ v-model="queryParams.pickUpStoreIds"
+ class="!w-280px"
+ placeholder="鍏ㄩ儴"
+ @change="handleQuery"
+ >
+ <el-option
+ v-for="item in pickUpStoreList"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鑱氬悎鎼滅储">
+ <el-input
+ v-show="true"
+ v-model="queryParams[queryType.queryParam]"
+ class="!w-280px"
+ clearable
+ placeholder="璇疯緭鍏�"
+ :type="queryType.queryParam === 'userId' ? 'number' : 'text'"
+ >
+ <template #prepend>
+ <el-select
+ v-model="queryType.queryParam"
+ class="!w-110px"
+ placeholder="鍏ㄩ儴"
+ @change="inputChangeSelect"
+ >
+ <el-option
+ v-for="dict in dynamicSearchList"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value"
+ />
+ </el-select>
+ </template>
+ </el-input>
+ </el-form-item>
+ <el-form-item>
+ <el-button @click="handleQuery">
+ <Icon class="mr-5px" icon="ep:search" />
+ 鎼滅储
+ </el-button>
+ <el-button @click="resetQuery">
+ <Icon class="mr-5px" icon="ep:refresh" />
+ 閲嶇疆
+ </el-button>
+ <el-button
+ @click="handlePickup"
+ type="success"
+ plain
+ v-hasPermi="['trade:order:pick-up']"
+ :disabled="isUse"
+ >
+ <Icon class="mr-5px" icon="ep:check" />
+ 鏍搁攢
+ </el-button>
+ <el-button type="primary" @click="connectToSerialPort" :disabled="serialPort || isUse">
+ 杩炴帴鎵弿鏋�
+ </el-button>
+ <el-button type="danger" @click="cutPort" :disabled="!serialPort || isUse">
+ 鏂紑鎵弿鏋�
+ </el-button>
+ </el-form-item>
+ </el-form>
+ </ContentWrap>
+
+ <!-- 缁熻鍗$墖 -->
+ <el-row :gutter="16" class="summary">
+ <el-col :sm="6" :xs="12" v-loading="loading">
+ <SummaryCard
+ title="璁㈠崟鏁伴噺"
+ icon="icon-park-outline:transaction-order"
+ icon-color="bg-blue-100"
+ icon-bg-color="text-blue-500"
+ :value="summary?.orderCount || 0"
+ />
+ </el-col>
+ <el-col :sm="6" :xs="12" v-loading="loading">
+ <SummaryCard
+ title="璁㈠崟閲戦"
+ icon="streamline:money-cash-file-dollar-common-money-currency-cash-file"
+ icon-color="bg-purple-100"
+ icon-bg-color="text-purple-500"
+ prefix="锟�"
+ :decimals="2"
+ :value="fenToYuan(summary?.orderPayPrice || 0)"
+ />
+ </el-col>
+ <el-col :sm="6" :xs="12" v-loading="loading">
+ <SummaryCard
+ title="閫�娆惧崟鏁�"
+ icon="heroicons:receipt-refund"
+ icon-color="bg-yellow-100"
+ icon-bg-color="text-yellow-500"
+ :value="summary?.afterSaleCount || 0"
+ />
+ </el-col>
+ <el-col :sm="6" :xs="12" v-loading="loading">
+ <SummaryCard
+ title="閫�娆鹃噾棰�"
+ icon="ri:refund-2-line"
+ icon-color="bg-green-100"
+ icon-bg-color="text-green-500"
+ prefix="锟�"
+ :decimals="2"
+ :value="fenToYuan(summary?.afterSalePrice || 0)"
+ />
+ </el-col>
+ </el-row>
+
+ <!-- 鍒楄〃 -->
+ <ContentWrap>
+ <el-table v-loading="loading" :data="list">
+ <el-table-column label="璁㈠崟鍙�" align="center" prop="no" min-width="180" />
+ <el-table-column label="鐢ㄦ埛淇℃伅" align="center" prop="user.nickname" min-width="80" />
+ <el-table-column
+ label="鎺ㄨ崘浜轰俊鎭�"
+ align="center"
+ prop="brokerageUser.nickname"
+ min-width="100"
+ />
+ <el-table-column label="鍟嗗搧淇℃伅" align="center" prop="spuName" min-width="300">
+ <template #default="{ row }">
+ <div class="flex items-center" v-for="item in row.items" :key="item.id">
+ <el-image
+ :src="item.picUrl"
+ class="mr-10px h-30px w-30px flex-shrink-0"
+ :preview-src-list="[item.picUrl]"
+ preview-teleported
+ />
+ <span class="mr-10px">{{ item.spuName }}</span>
+ <div class="flex flex-col flex-wrap gap-1">
+ <el-tag
+ v-for="property in item.properties"
+ :key="property.propertyId"
+ class="mr-10px"
+ >
+ {{ property.propertyName }}: {{ property.valueName }}
+ </el-tag>
+ <span>{{ floatToFixed2(item.price) }} 鍏� x {{ item.count }}</span>
+ </div>
+ </div>
+ </template>
+ </el-table-column>
+ <el-table-column
+ label="瀹炰粯閲戦(鍏�)"
+ align="center"
+ prop="payPrice"
+ min-width="110"
+ :formatter="fenToYuanFormat"
+ />
+ <el-table-column label="鏍搁攢鍛�" align="center" prop="storeStaffName" min-width="70" />
+ <el-table-column label="鏍搁攢闂ㄥ簵" align="center" prop="pickUpStoreId" min-width="80">
+ <template #default="{ row }">
+ {{ pickUpStoreList.find((p) => p.id === row.pickUpStoreId)?.name }}
+ </template>
+ </el-table-column>
+ <el-table-column label="鏀粯鐘舵��" align="center" prop="payStatus" min-width="80">
+ <template #default="{ row }">
+ <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.payStatus || false" />
+ </template>
+ </el-table-column>
+ <el-table-column align="center" label="璁㈠崟鐘舵��" prop="status" width="120">
+ <template #default="{ row }">
+ <dict-tag :type="DICT_TYPE.TRADE_ORDER_STATUS" :value="row.status" />
+ </template>
+ </el-table-column>
+ <el-table-column
+ label="涓嬪崟鏃堕棿"
+ align="center"
+ prop="createTime"
+ min-width="170"
+ :formatter="dateFormatter"
+ />
+ </el-table>
+ <!-- 鍒嗛〉 -->
+ <Pagination
+ v-model:limit="queryParams.pageSize"
+ v-model:page="queryParams.pageNo"
+ :total="total"
+ @pagination="getList"
+ />
+ </ContentWrap>
+
+ <!-- 鍚勭鎿嶄綔鐨勫脊绐� -->
+ <OrderPickUpForm ref="pickUpForm" @success="getList" />
+</template>
+
+<script lang="ts" setup>
+import type { FormInstance } from 'element-plus'
+import * as TradeOrderApi from '@/api/mall/trade/order'
+import * as PickUpStoreApi from '@/api/mall/trade/delivery/pickUpStore'
+import { DICT_TYPE } from '@/utils/dict'
+import { fenToYuan, floatToFixed2 } from '@/utils'
+import { fenToYuanFormat } from '@/utils/formatter'
+import SummaryCard from '@/components/SummaryCard/index.vue'
+import { dateFormatter } from '@/utils/formatTime'
+import { DeliveryTypeEnum } from '@/utils/constants'
+import { TradeOrderSummaryRespVO } from '@/api/mall/trade/order'
+import { DeliveryPickUpStoreVO } from '@/api/mall/trade/delivery/pickUpStore'
+import OrderPickUpForm from '@/views/mall/trade/order/form/OrderPickUpForm.vue'
+import { ref, onMounted } from 'vue'
+import { useUserStore } from '@/store/modules/user'
+const message = useMessage() // 娑堟伅寮圭獥
+
+const port = ref('')
+const ports = ref([])
+const reader = ref('')
+
+defineOptions({ name: 'PickUpOrder' })
+
+const loading = ref(true) // 鍒楄〃鐨勫姞杞戒腑
+const total = ref(2) // 鍒楄〃鐨勬�婚〉鏁�
+const list = ref<TradeOrderApi.OrderVO[]>([]) // 鍒楄〃鐨勬暟鎹�
+const queryFormRef = ref<FormInstance>() // 鎼滅储鐨勮〃鍗�
+const INIT_QUERY_PARAMS = {
+ // 椤垫暟
+ pageNo: 1,
+ // 姣忛〉鏄剧ず鏁伴噺
+ pageSize: 10,
+ // 鍒涘缓鏃堕棿
+ createTime: undefined,
+ // 閰嶉�佹柟寮�
+ deliveryType: DeliveryTypeEnum.PICK_UP.type,
+ // 鑷彁闂ㄥ簵
+ pickUpStoreIds: -1
+} // 鍒濆琛ㄥ崟鍙傛暟
+
+const queryParams = ref({ ...INIT_QUERY_PARAMS }) // 琛ㄥ崟鎼滅储
+const queryType = reactive({ queryParam: 'no' }) // 璁㈠崟鎼滅储绫诲瀷 queryParam
+const summary = ref<TradeOrderSummaryRespVO>() // 璁㈠崟缁熻鏁版嵁
+
+const serialPort = ref(false) // 鏄惁杩炴帴鎵爜鏋�
+const isUse = ref(true) // 鏄惁鍙牳閿�
+
+// 璁㈠崟鑱氬悎鎼滅储 select 绫诲瀷閰嶇疆锛堝姩鎬佹悳绱級
+const dynamicSearchList = ref([
+ { value: 'no', label: '璁㈠崟鍙�' },
+ { value: 'userId', label: '鐢ㄦ埛 UID' },
+ { value: 'userNickname', label: '鐢ㄦ埛鏄电О' },
+ { value: 'userMobile', label: '鐢ㄦ埛鐢佃瘽' }
+])
+/**
+ * 鑱氬悎鎼滅储鍒囨崲鏌ヨ瀵硅薄鏃惰Е鍙�
+ * @param val
+ */
+const inputChangeSelect = (val: string) => {
+ dynamicSearchList.value
+ .filter((item) => item.value !== val)
+ ?.forEach((item) => {
+ // 娓呴櫎闆嗗悎鎼滅储鏃犵敤灞炴��
+ if (queryParams.value.hasOwnProperty(item.value)) {
+ delete queryParams.value[item.value]
+ }
+ })
+}
+
+/** 鏌ヨ鍒楄〃 */
+const getList = async () => {
+ loading.value = true
+ try {
+ // 缁熻
+ summary.value = await TradeOrderApi.getOrderSummary(unref(queryParams))
+ // 鍒嗛〉
+ const data = await TradeOrderApi.getOrderPage(unref(queryParams))
+ list.value = data.list
+ total.value = data.total
+ } finally {
+ loading.value = false
+ }
+}
+
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = async () => {
+ queryParams.value.pageNo = 1
+ await getList()
+}
+
+/** 閲嶇疆鎸夐挳鎿嶄綔 */
+const resetQuery = () => {
+ queryFormRef.value?.resetFields()
+ queryParams.value = { ...INIT_QUERY_PARAMS }
+ if (pickUpStoreList.value.length > 0) {
+ queryParams.value.pickUpStoreIds = pickUpStoreList.value[0].id
+ }
+ handleQuery()
+}
+
+/** 鑷彁闂ㄥ簵绮剧畝鍒楄〃 */
+const pickUpStoreList = ref<DeliveryPickUpStoreVO[]>([])
+const getPickUpStoreList = async () => {
+ pickUpStoreList.value = await PickUpStoreApi.getSimpleDeliveryPickUpStoreList()
+ // 绉婚櫎鑷繁鏃犳硶鏍搁攢鐨勯棬搴�
+ const userId = useUserStore().getUser.id
+ pickUpStoreList.value = pickUpStoreList.value.filter((item) =>
+ item.verifyUserIds?.includes(userId)
+ )
+}
+
+/** 鏄剧ず鏍搁攢琛ㄥ崟 */
+const pickUpForm = ref()
+const handlePickup = () => {
+ pickUpForm.value.open()
+}
+
+/** 杩炴帴鎵爜鏋� */
+const connectToSerialPort = async () => {
+ try {
+ // 鍒ゆ柇娴忚鍣ㄦ敮鎸佷覆鍙i�氫俊
+ if (
+ 'serial' in navigator &&
+ navigator.serial != null &&
+ typeof navigator.serial === 'object' &&
+ 'requestPort' in navigator.serial
+ ) {
+ // 鎻愮ず鐢ㄦ埛閫夋嫨涓�涓覆鍙�
+ port.value = await navigator.serial.requestPort()
+ } else {
+ message.error('娴忚鍣ㄤ笉鏀寔鎵爜鏋繛鎺ワ紝璇锋洿鎹㈡祻瑙堝櫒閲嶈瘯')
+ return
+ }
+
+ // 鑾峰彇鐢ㄦ埛涔嬪墠鎺堜簣璇ョ綉绔欒闂潈闄愮殑鎵�鏈変覆鍙c��
+ ports.value = await navigator.serial.getPorts()
+
+ // console.log(port.value, ports.value);
+ // console.log(port.value)
+ // 绛夊緟涓插彛鎵撳紑
+ await port.value.open({ baudRate: 9600, dataBits: 8, stopBits: 2 })
+
+ // console.log(typeof port.value);
+ message.success('鎴愬姛杩炴帴鎵爜鏋�')
+ serialPort.value = true
+ // readData(port.value);
+ readData()
+ } catch (error) {
+ // 澶勭悊杩炴帴涓插彛鍑洪敊鐨勬儏鍐�
+ console.log('Error connecting to serial port:', error)
+ }
+}
+
+/** 鐩戝惉鎵爜鏋緭鍏� */
+const readData = async () => {
+ reader.value = port.value.readable.getReader()
+ let data = '' //鎵爜鏁版嵁
+ // 鐩戝惉鏉ヨ嚜涓插彛鐨勬暟鎹�
+ while (true) {
+ const { value, done } = await reader.value.read()
+ if (done) {
+ // 鍏佽绋嶅悗鍏抽棴涓插彛
+ reader.value.releaseLock()
+ break
+ }
+ // 鑾峰彇鍙戦�佺殑鏁版嵁
+ const serialData = new TextDecoder().decode(value)
+ data = `${data}${serialData}`
+ if (serialData.includes('\r')) {
+ //璇诲彇缁撴潫
+ let codeData = data.replace('\r', '')
+ data = '' //娓呯┖涓嬫璇诲彇涓嶄細鍙犲姞
+ console.log(`浜岀淮鐮佹暟鎹�:${codeData}`)
+ //澶勭悊鎷垮埌鏁版嵁閫昏緫
+ pickUpForm.value.open(codeData)
+ }
+ }
+}
+
+/** 鏂紑鎵爜鏋� */
+const cutPort = async () => {
+ if (port.value !== '') {
+ await reader.value.cancel()
+ await port.value.close()
+ port.value = ''
+ console.log('鏂紑鎵爜鏋繛鎺�')
+ message.success('宸叉垚鍔熸柇寮�鎵爜鏋繛鎺�')
+ serialPort.value = false
+ } else {
+ message.warning('璇峰厛杩炴帴鎴栨墦寮�鎵爜鏋�')
+ }
+}
+
+/** 鍒濆鍖� **/
+onMounted(async () => {
+ await getPickUpStoreList()
+ if (pickUpStoreList.value.length === 0) {
+ message.error('褰撳墠鐧诲綍浜烘病缁戝畾浠讳綍鑷彁鐐�')
+ loading.value = false
+ isUse.value = true
+ return
+ }
+
+ // 鏌ヨ
+ queryParams.value.pickUpStoreIds = pickUpStoreList.value[0].id
+ isUse.value = false
+ await getList()
+})
+</script>
+<style lang="scss" scoped>
+:deep(.order-table-col > .cell) {
+ padding: 0;
+}
+
+.summary {
+ .el-col {
+ margin-bottom: 1rem;
+ }
+}
+</style>
--
Gitblit v1.8.0