From 288ea7b80daa7c8564b66750d2d3edb5b7520edf Mon Sep 17 00:00:00 2001 From: Timi Date: Wed, 9 Sep 2026 16:55:41 +0800 Subject: [PATCH] add scanner --- src/pages/salesOrder/SalesOrderList.vue | 137 +++++++++++++++++++++--- 1 file changed, 120 insertions(+), 17 deletions(-) diff --git a/src/pages/salesOrder/SalesOrderList.vue b/src/pages/salesOrder/SalesOrderList.vue index 00ca0c6..385316e 100644 --- a/src/pages/salesOrder/SalesOrderList.vue +++ b/src/pages/salesOrder/SalesOrderList.vue @@ -2,7 +2,25 @@
- + + + +
+ +
[ ]); const keyword = ref(""); const customerId = ref(""); +const selectedCustomer = ref(); +const scannerVisible = ref(false); +const scanStatus = ref("点击扫码开始识别。"); +let latestDecodedText = ""; +let customerKeyword = ""; const orderType = ref("ALL"); type PaymentFilter = "ALL" | GaoSalesPaymentStatus | "PENDING_RECEIVE"; type RefundFilter = "ALL" | GaoSalesRefundStatus; @@ -151,6 +186,24 @@ function applyRouteFilters(): void { refundStatus.value = queryValue(route.query.refundStatus) as RefundFilter || "ALL"; } +function setCustomerKeyword(customer: Customer): void { + const value = customer.name?.trim() || customer.code?.trim() || ""; + customerId.value = customer.id || ""; + selectedCustomer.value = customer; + customerKeyword = value; + keyword.value = value; +} + +async function loadRouteCustomer(): Promise { + if (!customerId.value) { + selectedCustomer.value = undefined; + customerKeyword = ""; + return; + } + selectedCustomer.value = await CustomerAPI.detail(customerId.value); + setCustomerKeyword(selectedCustomer.value); +} + function buildPageFilter(): SalesOrderPage { const pendingReceive = paymentStatus.value === "PENDING_RECEIVE"; return { @@ -226,6 +279,39 @@ async function selectRefundStatus(value: DropdownValue): Promise { } } +async function toggleScanner(): Promise { + scannerVisible.value = !scannerVisible.value; + if (scannerVisible.value) { + latestDecodedText = ""; + scanStatus.value = "正在打开相机。"; + } +} + +async function handleDecodedText(rawText: string): Promise { + const code = rawText.trim(); + if (!code || code === latestDecodedText) { + return; + } + latestDecodedText = code; + try { + const customer = await CustomerAPI.findByCode(code); + if (!customer?.id) { + scanStatus.value = `客户 ${code} 不存在。`; + return; + } + setCustomerKeyword(customer); + scanStatus.value = `已识别 ${customer.name || customer.code || code},已填入搜索框。`; + scannerVisible.value = false; + await fetchList(true); + } catch (error) { + scanStatus.value = getErrorMessage(error, "客户查询失败,请重试。"); + } +} + +function handleScanStatusChange(value: string): void { + scanStatus.value = value; +} + async function toDetail(item: SalesOrder): Promise { if (item.id) await router.push(`/management/sales-orders/${item.id}`); } @@ -265,16 +351,35 @@ const search = Toolkit.debounce(async () => { Message.error(getErrorMessage(error, "销售订单加载失败")); } }, false); -watch(keyword, () => search()); +watch(keyword, async () => { + const isCustomerKeyword = !!customerId.value && keyword.value.trim() === customerKeyword; + customerKeyword = ""; + if (isCustomerKeyword) { + return; + } + customerId.value = ""; + selectedCustomer.value = undefined; + await search(); +}); watch(routeFilterKey, async () => { applyRouteFilters(); + try { + await loadRouteCustomer(); + } catch { + selectedCustomer.value = undefined; + } await fetchList(true); }); onMounted(async () => { navBarStore.clearRight(); navBarStore.setCustomRightVisible(!!actions.value.length); applyRouteFilters(); - try { await fetchList(true); } catch (error) { Message.error(getErrorMessage(error, "销售订单加载失败")); } + try { + await loadRouteCustomer(); + await fetchList(true); + } catch (error) { + Message.error(getErrorMessage(error, "销售订单加载失败")); + } }); onUnmounted(() => { navBarStore.clearRight(); search.cancel(); }); @@ -299,13 +404,21 @@ onUnmounted(() => { navBarStore.clearRight(); search.cancel(); }); display: flex; .keyword { + --td-button-border-radius: .75rem; --td-input-vertical-padding: .25rem 1rem; flex: 1; border: 1px solid var(--td-component-border); z-index: 2; background: var(--td-bg-color-container); + padding-right: .3rem; border-radius: 1rem; + + .actions { + gap: .25rem; + display: flex; + align-items: center; + } } .status { @@ -336,26 +449,16 @@ onUnmounted(() => { navBarStore.clearRight(); search.cancel(); }); border-top: none; padding-top: .8rem; border-radius: 0 0 1rem 1rem; - - &:after { - display: none; - } - - :deep(.t-dropdown-menu__item) { - min-width: 0; - } - - :deep(.t-dropdown-menu__title) { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - } } } .list-wrap { padding-top: 1rem; + .scanner-wrap { + margin: 0 1rem 1rem; + } + .items { gap: 1rem; display: flex;